---
```markdown
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- APZ WALLET — CONTRIBUTING GUIDE -->
<!-- ═══════════════════════════════════════════════════════════ -->
<div align="center">
# 🤝 Contributing to APZ Wallet
**Thank you for considering a contribution!**
Every pull request, issue report, and suggestion helps make APZ Wallet better.
[](http://makeapullrequest.com)
[](CODE_OF_CONDUCT.md)
</div>
---
- Code of Conduct
- Ways to Contribute
- Getting Started
- Development Workflow
- Branch Naming
- Commit Conventions
- Code Style Guide
- Testing Requirements
- Pull Request Process
- Review Guidelines
- Reporting Bugs
- Suggesting Features
- Security Vulnerabilities
- Documentation
- Translation
- Recognition
- License
- Questions?
This project and everyone participating in it is governed by our Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to conduct@apzchain.org.
In short:
- ✅ Be respectful and inclusive
- ✅ Welcome newcomers and help them learn
- ✅ Focus on constructive feedback
- ✅ Respect differing viewpoints and experiences
- ❌ No harassment, discrimination, or personal attacks
- ❌ No trolling, spam, or off-topic discussions
There are many ways to contribute — you don't need to be a developer!
Found something broken? Open an issue with details.
Have an idea? Submit a feature request.
Improve README, fix typos, add examples, or translate docs.
Contribute UI/UX improvements, icons, or design assets.
Help translate APZ Wallet into new languages (currently FA/EN/DE).
Fix bugs, add features, optimize performance, or refactor code.
Write tests, report edge cases, or test on different devices.
Help others in Discussions or answer questions.
Give us a star and share the project with others!
Before contributing code, ensure you have these tools installed:
| Tool | Version | Purpose | Install |
|---|---|---|---|
| Node.js | 20+ | JS runtime | nvm |
| JDK | 17 | Android builds | Adoptium |
| Android Studio | Latest | Android SDK | Download |
| Rust | 1.75+ | Crypto engine | rustup.rs |
| Go | 1.22+ | Network layer | go.dev |
| Ruby | 3.2+ | Fastlane | rbenv |
| Git | 2.40+ | Version control | git-scm.com |
# 1. Fork the repository on GitHub (click the "Fork" button)
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/APZ_WALLET.git
cd APZ_WALLET
# 3. Add upstream remote
git remote add upstream https://github.com/apzchain/APZ_WALLET.git
# 4. Install Node dependencies
npm install
# 5. Install Rust dependencies
cd crypto && cargo build --release && cd ..
# 6. Install Go dependencies
cd network && go mod download && cd ..
# 7. Install Ruby dependencies (for Fastlane)
cd android && bundle install && cd ..
# 8. Verify setup
npm run test # or individual test commands per module🌿 Keep Your Fork Updated
# Fetch latest changes from upstream
git fetch upstream
# Switch to main branch
git checkout main
# Merge upstream changes
git merge upstream/main
# Push to your fork
git push origin main🔄 Development Workflow
Standard Flow
1. Sync fork → git fetch upstream && git merge upstream/main
2. Create branch → git checkout -b feature/my-feature
3. Make changes → Edit files, write tests
4. Run tests → npm test (or per-language)
5. Lint & format → npm run lint && npm run format
6. Commit → git commit -m "feat: add my feature"
7. Push → git push origin feature/my-feature
8. Open PR → GitHub Pull Request
9. Address feedback → Respond to review comments
10. Merge → Maintainer merges
🏗️ Module-Specific Commands
Module Path Build Test Lint Android android/ ./gradlew assembleDebug ./gradlew test ./gradlew lint Web/PWA web/, docs/ python3 -m http.server Manual + Lighthouse ESLint Core (TS) core/ npm run build npm test npm run lint Crypto (Rust) crypto/ cargo build --release cargo test cargo clippy Network (Go) network/ go build ./... go test ./... golangci-lint run Explorer (Next.js) explorer-react/ npm run build npm test npm run lint
🌿 Branch Naming
Use descriptive branch names with prefixes:
Prefix Purpose Example feature/ New feature feature/hardware-wallet-support fix/ Bug fix fix/rpc-timeout-handling docs/ Documentation docs/api-reference-update refactor/ Refactoring refactor/crypto-engine-cleanup perf/ Performance perf/optimize-transaction-signing test/ Tests test/add-wallet-unit-tests chore/ Maintenance chore/update-dependencies ci/ CI/CD ci/add-nightly-build i18n/ Translation i18n/add-japanese-locale hotfix/ Urgent fix hotfix/security-patch
Rules:
· ✅ Use lowercase and hyphens (no underscores, no spaces) · ✅ Keep it short but descriptive (max 50 chars) · ✅ Reference issue number when applicable: fix/123-rpc-timeout · ❌ Avoid generic names like patch-1, update, test
📝 Commit Conventions
We follow Conventional Commits v1.0.0.
Format
<type>(<scope>): <subject>
<body>
<footer>
Types
Type Purpose Example feat New feature feat(wallet): add biometric auth fix Bug fix fix(rpc): handle network timeout docs Documentation docs(readme): update install steps style Code style (no logic change) style(android): format Kotlin files refactor Refactoring refactor(crypto): extract signing logic perf Performance perf(network): cache RPC responses test Tests test(core): add transaction tests build Build system build(gradle): upgrade to AGP 8.5 ci CI/CD ci(github): add release workflow chore Maintenance chore(deps): bump kotlin to 1.9 revert Revert previous commit revert: feat(wallet): biometric auth
Scopes (Optional)
wallet, crypto, network, rpc, explorer, pwa, ui, i18n, android, web, docs, ci, deps
Examples
Good:
feat(explorer): add smart contract ABI viewer
- Parse ABI from Sourcify
- Render read/write functions
- Support ERC-20/721/1155 detection
Closes #42
fix(rpc): prevent infinite retry loop on 502
The retry logic didn't count attempts correctly when the server
returned 502. Now limits to 3 retries with exponential backoff.
Fixes #128
Bad:
❌ updated stuff
❌ fix
❌ WIP
❌ asdfasdf
❌ Fixed the thing that was broken
Breaking Changes
For breaking changes, add ! after type or include BREAKING CHANGE: in footer:
feat(api)!: change wallet initialization signature
BREAKING CHANGE: `initWallet()` now requires a `network` parameter.
Old: `initWallet(seed)`
New: `initWallet(seed, network)`
Migration guide in docs/MIGRATION.md
Commit Message Rules
· ✅ Use imperative mood ("add", not "added" or "adds") · ✅ Keep subject under 72 characters · ✅ Capitalize the subject (after type) · ✅ No period at the end of subject · ✅ Use body to explain what and why, not how · ✅ Reference issues in footer (Closes #123, Fixes #456)
🎨 Code Style Guide
General Principles
· Readability over cleverness — code is read more than written · Consistency — follow existing patterns in the codebase · Simplicity — prefer simple solutions over complex ones · Comments — explain why, not what · Naming — descriptive names beat short names
🟣 Kotlin (Android)
Style: Kotlin Coding Conventions
// ✅ Good
class WalletRepository(
private val rpcClient: RpcClient,
private val cryptoEngine: CryptoEngine,
) {
suspend fun getBalance(address: String): Result<BigDecimal> {
return try {
val hex = rpcClient.call("eth_getBalance", listOf(address, "latest"))
Result.success(hex.toBigDecimal())
} catch (e: RpcException) {
Result.failure(e)
}
}
}
// ❌ Bad
class WalletRepo(private val r:RpcClient){
fun getBalance(a:String):BigDecimal{
val h=r.call("eth_getBalance",listOf(a,"latest"))
return h.toBigDecimal()
}
}Rules:
· ✅ 4 spaces indentation · ✅ Max line length: 120 chars · ✅ Trailing commas in multi-line · ✅ Use val over var when possible · ✅ Prefer Result over exceptions for recoverable errors · ✅ Use Jetpack Compose for UI (no XML layouts)
🔵 TypeScript (Core/Web)
Style: ESLint + Prettier (config in repo)
// ✅ Good
export interface WalletConfig {
readonly network: Network;
readonly rpcUrl: string;
readonly chainId: number;
}
export async function createWallet(config: WalletConfig): Promise<Wallet> {
const seed = await generateSeed();
return new Wallet(seed, config);
}
// ❌ Bad
export function createWallet(c:any){
return new Wallet(generateSeed(), c)
}Rules:
· ✅ 2 spaces indentation · ✅ Semicolons required · ✅ Single quotes · ✅ Trailing commas · ✅ readonly for immutable fields · ✅ No any — use unknown and narrow · ✅ Prefer interface over type for objects · ✅ Async/await over raw promises
🦀 Rust (Crypto)
Style: rustfmt + clippy (enforced in CI)
// ✅ Good
pub fn sign_transaction(
keypair: &Keypair,
message: &[u8],
) -> Result<Signature, CryptoError> {
if message.is_empty() {
return Err(CryptoError::EmptyMessage);
}
Ok(keypair.sign(message))
}
// ❌ Bad
pub fn sign(k:&Keypair,m:&[u8])->Signature{
k.sign(m)
}Rules:
· ✅ 4 spaces indentation (rustfmt default) · ✅ Max line length: 100 chars · ✅ Use Result<T, E> for fallible operations · ✅ Avoid unwrap() and expect() in library code · ✅ Document public items with /// · ✅ Use #![deny(warnings)] in CI · ✅ No unsafe code without documented justification
🐹 Go (Network)
Style: gofmt + golangci-lint
// ✅ Good
type RpcClient struct {
url string
client *http.Client
}
func (c *RpcClient) Call(ctx context.Context, method string, params []any) (json.RawMessage, error) {
body, err := json.Marshal(rpcRequest{
JSONRPC: "2.0",
Method: method,
Params: params,
ID: 1,
})
if err != nil {
return nil, fmt.Errorf("marshal request: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.url, bytes.NewReader(body))
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("send request: %w", err)
}
defer resp.Body.Close()
// ... parse response
return nil, nil
}Rules:
· ✅ Use gofmt (tabs, not spaces) · ✅ Wrap errors with fmt.Errorf("...: %w", err) · ✅ Accept context.Context as first parameter · ✅ Use any instead of interface{} (Go 1.18+) · ✅ Prefer table-driven tests · ✅ No naked returns in functions > 5 lines
🎨 CSS / SCSS
/* ✅ Good */
.wallet-card {
padding: 16px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
transition: var(--transition);
}
.wallet-card:hover {
border-color: var(--border-hover);
}
/* ❌ Bad */
.walletCard{padding:16px;background:#fff;border:1px solid #ccc}Rules:
· ✅ kebab-case for classes · ✅ CSS custom properties for theming · ✅ BEM-like naming for complex components · ✅ Mobile-first media queries · ✅ No !important unless absolutely necessary
📝 Markdown
· ✅ One sentence per line (for cleaner diffs) · ✅ Use fenced code blocks with language tags · ✅ Reference links at bottom for long URLs · ✅ Keep lines under 120 chars (except tables)
🧪 Testing Requirements
Coverage Targets
Module Minimum Coverage Crypto (Rust) 95% Core (TypeScript) 90% Network (Go) 85% Android (Kotlin) 80% Explorer (React) 75%
Test Types
Unit Tests — Fast, isolated, no external dependencies:
@Test
fun `should generate valid seed phrase`() {
val seed = wallet.generateSeed()
assertTrue(seed.split(" ").size == 12)
}Integration Tests — Test module boundaries:
#[test]
fn test_sign_and_verify_roundtrip() {
let keypair = Keypair::generate();
let message = b"hello world";
let sig = sign_transaction(&keypair, message).unwrap();
assert!(verify(&keypair.public, message, &sig));
}UI Tests — Android instrumented tests:
@Test
fun walletScreen_displaysBalance() {
composeTestRule.setContent { WalletScreen() }
composeTestRule.onNodeWithText("Balance").assertIsDisplayed()
}Running Tests
# All tests
npm run test:all
# Per module
cd crypto && cargo test --release
cd core && npm test
cd network && go test -race ./...
cd android && ./gradlew testDebugUnitTest
cd explorer-react && npm test
# Watch mode (where available)
npm test -- --watchTest Requirements for PRs
· ✅ New features must include tests · ✅ Bug fixes must include regression tests · ✅ Refactors must not decrease coverage · ✅ All tests pass before merging
🔀 Pull Request Process
Before Opening a PR
Use this checklist:
☐ I've read the CONTRIBUTING.md guide ☐ My code follows the project's code style ☐ I've added tests for new functionality ☐ All tests pass locally (npm run test:all) ☐ I've run linters (npm run lint) ☐ I've updated documentation if needed ☐ I've updated CHANGELOG.md (if maintained) ☐ My commits follow Conventional Commits ☐ I've rebased on the latest main branch ☐ My branch name follows the naming convention
PR Title Format
Same as commit convention:
feat(explorer): add contract source viewer
fix(rpc): handle WebSocket reconnection
docs(readme): update installation steps
PR Description Template
When you open a PR, fill out this template:
## 📝 Description
Brief description of what this PR does.
## 🎯 Motivation
Why is this change needed? What problem does it solve?
Closes #123
## 🔧 Changes
- Added X feature
- Fixed Y bug
- Refactored Z module
## 📸 Screenshots (if UI changes)
| Before | After |
|--------|-------|
|  |  |
## 🧪 Testing
How has this been tested?
- [ ] Unit tests added
- [ ] Integration tests added
- [ ] Manual testing on Android 13
- [ ] Tested on iOS Safari
## ✅ Checklist
- [ ] Code follows style guide
- [ ] Tests pass locally
- [ ] Documentation updated
- [ ] No new warnings introduced
- [ ] Commits follow conventions
## 📝 Additional Notes
Any additional context.PR Size Guidelines
Size Lines Changed Review Time 🟢 Small < 200 Fast review 🟡 Medium 200–500 Standard review 🔴 Large 500 Split recommended
Prefer small, focused PRs. One feature per PR.
Review Timeline
· 📅 Initial response: within 3 business days · 📅 Full review: within 7 business days · 📅 Merge: after approval + CI passes
If you don't hear back, feel free to ping maintainers in the PR.
👀 Review Guidelines
For Reviewers
· ✅ Be kind and constructive — assume good intentions · ✅ Explain the "why" when requesting changes · ✅ Approve when ready — don't nitpick forever · ✅ Test locally for complex changes · ✅ Check for security implications · ❌ Don't block on style preferences already covered by linters · ❌ Don't request unrelated changes in the same PR
For Authors
· ✅ Respond to every comment — even if just "done" · ✅ Ask for clarification if a comment is unclear · ✅ Push fixes as new commits (don't force-push during review) · ✅ Mark conversations as resolved after addressing · ❌ Don't take feedback personally — it's about the code
Review Labels
Label Meaning status: needs review Ready for reviewer status: in review Being reviewed status: changes requested Author needs to address feedback status: approved Ready to merge status: blocked Waiting on something else
🐛 Reporting Bugs
Before Reporting
- Search existing issues — maybe it's already reported
- Check the docs — maybe it's expected behavior
- Try the latest version — maybe it's already fixed
- Reproduce on a clean install — isolate the issue
Bug Report Template
## 🐛 Bug Description
Clear and concise description of the bug.
## 🔄 Steps to Reproduce
1. Open APZ Wallet
2. Navigate to 'Explorer'
3. Search for '0x123...'
4. See error
## 🎯 Expected Behavior
What you expected to happen.
## 📸 Screenshots
If applicable, add screenshots.
## 🌐 Environment
- **Platform:** Android 13 / iOS 16 / Web (Chrome 120)
- **Device:** Samsung Galaxy S21
- **APZ Wallet Version:** 1.0.0
- **Network:** Mainnet / Testnet
## 📝 Additional Context
Any other context about the problem.
## 🔍 Possible Solution
If you have an idea how to fix it.
## 📋 Logs
Paste relevant logs here
✨ Suggesting Features
Feature Request Template
## ✨ Feature Description
Clear and concise description of the feature.
## 🎯 Problem It Solves
What problem does this feature solve?
## 💡 Proposed Solution
How would you like it to work?
## 🔄 Alternatives Considered
Any alternative solutions?
## 📸 Mockups / Examples
If applicable, add mockups or examples from other apps.
## 🎁 Additional Context
Any other context or screenshots.Feature Request Guidelines
· ✅ Explain the "why" — what problem does it solve? · ✅ Provide use cases — who benefits and how? · ✅ Suggest implementation if you have ideas · ✅ Reference similar features in other wallets · ❌ Don't demand immediate implementation · ❌ Don't open multiple issues for the same feature
🔐 Security Vulnerabilities
How to Report
Email: security@apzchain.org
PGP Key: Download
What to Include
· 🔍 Description of the vulnerability · 🔄 Steps to reproduce · 💥 Potential impact · 🛠️ Suggested fix (if any) · 📛 Your name/handle for credit (optional)
Our Commitment
· ⏱️ Response within 48 hours · 🔧 Fix within 30 days (critical issues: 7 days) · 📢 Coordinated disclosure after fix is released · 🏆 Credit in SECURITY.md (if desired)
Scope
In scope:
· Cryptography implementation · Key management · Transaction signing · RPC communication · Authentication / authorization
Out of scope:
· Social engineering · Physical device access · Third-party dependencies (report to upstream)
📚 Documentation
What to Document
· ✅ Public APIs — every exported function/class · ✅ Complex logic — non-obvious algorithms · ✅ Configuration — env vars, build flags · ✅ Architecture — design decisions in docs/ · ✅ User-facing — features, tutorials
Documentation Style
Code comments:
/**
* Signs a transaction with the given keypair.
*
* @param tx - The transaction to sign
* @param keypair - The keypair to sign with
* @returns The signed transaction
* @throws {CryptoError} If signing fails
*
* @example
* ```ts
* const signed = await signTransaction(tx, keypair);*/ export async function signTransaction(tx: Transaction, keypair: Keypair): Promise { // ... }
**Markdown docs:**
- Use clear headings
- Include examples
- Link to related docs
- Update TOC when adding sections
---
## 🌍 Translation
We currently support **Persian (FA)**, **English (EN)**, and **German (DE)**.
### Adding a New Language
1. Copy the reference file:
```bash
cp docs/assets/js/i18n.js docs/assets/js/i18n.new.js
- Add a new locale block in i18n.js:
const I18N = { en: { /* ... */ }, fa: { /* ... */ }, de: { /* ... */ }, ja: { // ← New language dir: 'ltr', brand: { sub: 'リリースダッシュボード' }, // ... } };
- Update the language switcher in HTML:
<button class="lang-btn" data-lang="ja">日本語</button>
- Update manifest.webmanifest if applicable.
- Test RTL/LTR rendering.
- Submit a PR with title: i18n: add Japanese locale
Translation Guidelines
· ✅ Native speakers preferred — nuance matters · ✅ Keep technical terms in English (e.g., "RPC", "wallet") · ✅ Match the tone of the original (friendly, clear) · ✅ Test in context — not just translation files · ❌ Don't use machine translation without review
🏆 Recognition
Contributors Wall
All contributors are listed on the Contributors page and in our README.
Special Recognition
· 🥇 Core contributors — Long-term impact · 🐛 Bug hunters — Critical fixes · 📚 Doc champions — Documentation improvements · 🌍 Translators — Language expansion · 🎨 Designers — UI/UX improvements · 💰 Sponsors — Financial support
All Contributors Bot
We use all-contributors to recognize every type of contribution. Comment on any PR or issue:
@all-contributors please add @username for code, doc, translation
📄 License
By contributing to APZ Wallet, you agree that your contributions will be licensed under the MIT License.
See LICENSE for full details.
Developer Certificate of Origin (DCO)
By submitting a pull request, you certify that:
· ✅ The contribution was created by you, or · ✅ You have the right to submit it under the project license, or · ✅ The contribution was provided to you under an open-source license that permits submission
You don't need to sign anything — the act of submitting a PR constitutes your agreement.
❓ Questions?
If you have questions, here are your options:
Question Type Best Place 🐛 Bug report GitHub Issues ✨ Feature idea GitHub Discussions 💬 General chat Discord 📧 Private matter hello@apzchain.org 🔐 Security issue security@apzchain.org 📱 Social Twitter / Telegram
🙏 Thank You!
Every contribution matters — no matter how small.
Whether you're fixing a typo, reporting a bug, or adding a major feature, you make APZ Wallet better for everyone.
Happy contributing! 🚀
Built with ❤️ by Khalil Heyrani and contributors worldwide.
For APZ Chain — A transparent, secure, and independent ecosystem.
📥 نحوه استفاده
۱. ذخیره فایل
cd /path/to/APZ_WALLET
nano CONTRIBUTING.md
# محتوای بالا را کپی کنید و ذخیره کنید۲. جایگزینی Placeholderها
این مقادیر را با اطلاعات واقعی جایگزین کنید:
Placeholder جایگزین با apzchain نام کاربری/سازمان GitHub شما APZ_WALLET نام واقعی مخزن conduct@apzchain.org ایمیل Code of Conduct security@apzchain.org ایمیل امنیتی hello@apzchain.org ایمیل عمومی https://discord.gg/apzchain لینک Discord https://t.me/apzchain کانال Telegram https://twitter.com/apzchain اکانت Twitter
۳. ساخت فایلهای مرتبط
فایل CONTRIBUTING.md به این فایلها ارجاع میدهد — آنها را هم بسازید:
# Code of Conduct
touch CODE_OF_CONDUCT.md
# Issue templates
mkdir -p .github/ISSUE_TEMPLATE
touch .github/ISSUE_TEMPLATE/bug_report.md
touch .github/ISSUE_TEMPLATE/feature_request.md
# PR template
touch .github/PULL_REQUEST_TEMPLATE.md۴. اتصال به README
در README.md، این خط را اضافه کنید:
## 🤝 Contributing
We welcome contributions! Please read our [Contributing Guide](CONTRIBUTING.md) before opening a PR.۵. فعالسازی در GitHub
GitHub بهطور خودکار فایل CONTRIBUTING.md را در ریشهی مخزن شناسایی میکند و:
· ✅ لینک "Contributing" را در کنار دکمهی "New Issue" نمایش میدهد · ✅ در هنگام باز کردن PR، لینک به آن را پیشنهاد میدهد · ✅ در Community Profile مخزن امتیاز میگیرد
۶. کامیت و Push
git add CONTRIBUTING.md README.md
git commit -m "docs: add comprehensive contributing guide"
git push origin main🎁 ویژگیهای این CONTRIBUTING.md
ویژگی توضیح ✅ TOC خودکار فهرست مطالب با anchor links ✅ ۱۰ روش مشارکت برای غیر-توسعهدهندگان هم ✅ جدول Prerequisites با لینک دانلود ✅ دستورات per-module برای هر بخش پروژه ✅ Branch Naming ۱۰ prefix با مثال ✅ Conventional Commits با ۱۱ type و مثالهای خوب/بد ✅ Code Style per Language Kotlin, TS, Rust, Go, CSS ✅ Coverage Targets اهداف پوشش تست ✅ PR Template کامل آماده استفاده ✅ Review Guidelines هم برای reviewer هم author ✅ Issue Templates Bug + Feature ✅ Security Section با PGP ✅ Translation Guide برای افزودن زبان جدید ✅ Recognition با all-contributors ✅ DCO رضایت ضمنی
🔧 سفارشیسازی پیشرفته (اختیاری)
افزودن فایل .github/PULL_REQUEST_TEMPLATE.md
<!--
Thanks for submitting a PR! Please fill out this template.
See CONTRIBUTING.md for detailed guidelines.
-->
## 📝 Description
<!-- Brief description -->
## 🎯 Motivation
<!-- Why is this needed? -->
Closes #
## 🔧 Type of Change
- [ ] 🐛 Bug fix
- [ ] ✨ New feature
- [ ] 💥 Breaking change
- [ ] 📚 Documentation
- [ ] 🎨 Style / refactor
- [ ] ⚡ Performance
- [ ] 🧪 Tests
## ✅ Checklist
- [ ] Code follows style guide
- [ ] Tests added/passing
- [ ] Documentation updated
- [ ] No new warnings
- [ ] Commits follow conventionsافزودن .github/ISSUE_TEMPLATE/bug_report.md
---
name: 🐛 Bug Report
about: Report a bug to help us improve
title: '[BUG] '
labels: ['bug', 'needs triage']
assignees: ''
---
## 🐛 Bug Description
<!-- Clear description -->
## 🔄 Steps to Reproduce
1.
2.
3.
## 🎯 Expected Behavior
<!-- What should happen -->
## 📸 Screenshots
<!-- If applicable -->
## 🌐 Environment
- Platform:
- Device:
- Version:
- Network:
## 📋 Logs
### فعالسازی DCO Bot
برای اجبار امضای هر commit، [DCO GitHub App](https://github.com/apps/dco) را نصب کنید.
---