Contributing
Thank you for your interest in contributing to Rack Gateway! This guide covers everything you need to know to submit quality contributions.
Getting Started
Section titled “Getting Started”-
Fork the repository
Fork docspring/rack-gateway on GitHub.
-
Clone your fork
Terminal window git clone https://github.com/YOUR_USERNAME/rack-gateway.gitcd rack-gateway -
Set up development environment
Follow the Local Setup guide.
-
Create a branch
Terminal window git checkout -b feature/your-feature-name
Development Workflow
Section titled “Development Workflow”Before You Code
Section titled “Before You Code”- Check existing issues - See if your feature/bug is already being worked on
- Open an issue - For significant changes, discuss the approach first
- Keep scope small - Focused PRs are easier to review
While Coding
Section titled “While Coding”# Make your changes, then verify:
# 1. Run linting (with auto-fix)task lint:fix
# 2. Run the tests for what you changedtask go:test:unittask web:testtask web:e2e -- --grep "the flow you changed"Never bypass the git hooks (--no-verify): the pre-commit hook formats, lints, and checks duplication and file
lengths.
Before Submitting
Section titled “Before Submitting”- CI passes - CI runs the full suite (
task ci) on every push, and a PR merges only when it’s green - Code is formatted - Run
task lint:fix - Commit messages are clear - Follow commit conventions below
- Documentation is updated - For new features or changes
Code Standards
Section titled “Code Standards”Go Code
Section titled “Go Code”- Follow Effective Go guidelines
- Use
gofmtandgoimports(handled bytask lint:fix) - Maximum line length: 120 characters
- Maximum function length: 100 lines and 50 statements, and cognitive complexity 15
- No
panic,time.Sleeporfmt.Print*outside CLI output: return errors, use contexts with timeouts, and log - No
//nolintcomments: fix the code. The only exceptions are//nolint:lllon struct tag lines gofmt can’t break, and gosec exceptions that name the rule and the reason (// #nosec G402 -- racks have no public CA chain)
Naming
Section titled “Naming”// Good: Clear, descriptive namesfunc CreateUserSession(user *User) (*Session, error)func ValidateAPIToken(token string) (*Token, error)
// Bad: Unclear abbreviationsfunc CrtUsrSess(u *User) (*Session, error)Error Handling
Section titled “Error Handling”// Good: Wrap errors with contextif err := db.Query(query); err != nil { return fmt.Errorf("failed to fetch user %s: %w", userID, err)}
// Bad: Generic error messagesif err := db.Query(query); err != nil { return err}Comments
Section titled “Comments”// Good: Explain WHY, not WHAT// UseRoundRobin distributes load across servers to prevent// any single server from being overwhelmed during peak traffic.func UseRoundRobin() LoadBalancer { ... }
// Bad: Restating the code// GetUser gets a userfunc GetUser(id string) *User { ... }TypeScript/React Code
Section titled “TypeScript/React Code”- Use Biome for formatting and linting;
// biome-ignorecomments aren’t allowed - Prefer functional components with hooks
- Use TypeScript strict mode
- Use the generated API client in
web/src/api/(task generateafter changing Go handlers)
Component Structure
Section titled “Component Structure”// Good: Clear component organizationinterface Props { user: User; onLogout: () => void;}
export function UserMenu({ user, onLogout }: Props) { const [isOpen, setIsOpen] = useState(false);
return ( <div className="user-menu"> {/* Component content */} </div> );}Error Handling
Section titled “Error Handling”// Good: Use React Query for data fetching with error handlingconst { data, error, isLoading } = useQuery({ queryKey: ['user', userId], queryFn: () => fetchUser(userId),});
if (error) { return <ErrorMessage error={error} />;}File Limits
Section titled “File Limits”| File Type | Max Lines |
|---|---|
| Go code files | 500 lines |
| Go test files | 1000 lines |
| TypeScript/TSX code | 500 lines |
| TypeScript test files | 1000 lines |
If a file approaches these limits, refactor into smaller modules. Production code may not duplicate 10 or more
lines (task duplication).
Commit Conventions
Section titled “Commit Conventions”Format
Section titled “Format”type(scope): short description
Longer description if needed.| Type | Description |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation only |
style | Formatting, no code change |
refactor | Code restructuring |
test | Adding/updating tests |
chore | Maintenance tasks |
Examples
Section titled “Examples”feat(auth): add WebAuthn support for passwordless login
fix(proxy): handle timeout errors gracefully
docs(readme): update installation instructions
refactor(rbac): extract permission checking to separate modulePull Request Guidelines
Section titled “Pull Request Guidelines”PR Title
Section titled “PR Title”Use the same format as commit messages:
feat(auth): add WebAuthn supportPR Description
Section titled “PR Description”Include:
- Summary - What does this PR do?
- Motivation - Why is this change needed?
- Testing - How was this tested?
- Screenshots - For UI changes
PR Template
Section titled “PR Template”## SummaryBrief description of what this PR does.
## MotivationWhy is this change needed?
## Changes- Change 1- Change 2
## Testing- [ ] Unit tests added/updated- [ ] Integration tests pass- [ ] E2E tests pass- [ ] Manual testing completed
## Screenshots (if applicable)Review Process
Section titled “Review Process”- Automated checks - CI must pass
- Code review - At least one maintainer approval
- Documentation - Updates if needed
- Merge - A maintainer merges once CI is green
Security Guidelines
Section titled “Security Guidelines”Reporting Vulnerabilities
Section titled “Reporting Vulnerabilities”Report them privately: report a vulnerability on GitHub, or email security@docspring.com. See the security policy.
Secure Coding Practices
Section titled “Secure Coding Practices”-
Input Validation
- Validate all user input
- Use parameterized queries (never string concatenation)
- Sanitize output for XSS prevention
-
Authentication
- Never log sensitive data (tokens, passwords)
- Use constant-time comparison for secrets
- Implement rate limiting on auth endpoints
-
Dependencies
- Keep dependencies updated
- Review security advisories
- Run
task go:sec:vuln(govulncheck) andtask sec:js(bun auditof the web, docs and mock OAuth packages); CI fails on any high or critical advisory
Testing Requirements
Section titled “Testing Requirements”Coverage Expectations
Section titled “Coverage Expectations”- New features must include tests
- Bug fixes should include regression tests
- Aim for meaningful coverage, not just line coverage
Test Types
Section titled “Test Types”| Change Type | Required Tests |
|---|---|
| New API endpoint | Unit + Integration + E2E |
| Bug fix | Regression test |
| UI component | Unit test + E2E (if user-facing) |
| Refactoring | Existing tests must pass |
Documentation
Section titled “Documentation”When to Update Docs
Section titled “When to Update Docs”- New features
- Changed behavior
- New configuration options
- API changes
Documentation Location
Section titled “Documentation Location”| Content | Location |
|---|---|
| API docs | OpenAPI spec in Go handlers |
| User guides | docs/src/content/docs/ |
| Code docs | Inline comments |
| Architecture | docs/src/content/docs/concepts/ |
Getting Help
Section titled “Getting Help”Resources
Section titled “Resources”Communication
Section titled “Communication”- GitHub Issues - Bug reports, feature requests, questions
- Pull Requests - Code review, feedback
License
Section titled “License”Rack Gateway is licensed under the Apache License 2.0 (LICENSE). By contributing, you agree that your
contributions are licensed under it.
Thank you for contributing to Rack Gateway!