Thank you for your interest in contributing. Bast is a production framework, every contribution is held to a high standard because real applications depend on it. Please read this guide fully before opening a pull request.
- Code of Conduct
- Where to Start
- Development Setup
- Implementation Rules
- Commit Style
- Pull Request Process
- PR Checklist
- Reporting Bugs
- Requesting Features
All contributors are expected to follow our Code of Conduct. Be respectful and constructive.
| Type | Where |
|---|---|
| Bug report | GitHub Issues using the bug template |
| Feature request | GitHub Issues using the feature template |
| Discussion / question | GitHub Discussions |
| Code contribution | Fork → branch → PR against main |
If you want to work on something non-trivial, open an issue first and discuss the approach before writing code. This avoids wasted effort if the direction doesn't fit the framework's philosophy.
# Fork and clone
git clone https://github.com/<your-fork>/bast.git
cd bast
# Verify everything works
go test ./...
# Run benchmarks
go test -bench=. -benchmem -count=3 -run=^$ ./...
# Run fuzz tests (short mode — CI-safe)
go test -fuzz=FuzzRouter_Find -fuzztime=10s ./fuzz/Requirements:
- Go 1.22 or later
- No external tools beyond the Go toolchain
These rules are non-negotiable. PRs that violate them will not be merged.
Write the test first. The test is the spec in code. No new exported symbol ships without a test.
The hot path is: request received → *Ctx acquired → handler called → Response written → *Ctx released.
BenchmarkCtx_AcquireRelease and all BenchmarkRouter_* must remain at 0 allocs/op. Run benchmarks before and after your change:
go test -bench=. -benchmem -count=5 -run=^$ ./... > bench_head.txt
benchstat bench_base.txt bench_head.txtA regression above 5% on BenchmarkApp_* requires justification in the PR description.
Check go.mod before any go get. The dependency list is a contract. Open an issue to discuss a new dependency before adding it.
Both of those files use reflection once at startup. If you think you need reflection elsewhere, you are solving the wrong problem.
Do not add Deadline(), Done(), Err(), or Value() methods to *Ctx. This is structural safety — the compiler prevents accidentally passing a pooled *Ctx to a goroutine.
All methods on Response use value receivers and return a new Response. Never mutate in place.
Every return err in framework code must be:
return fmt.Errorf("bast: <where>: %w", err)Never swallow errors silently.
Initialization order must be explicit. Two App instances in the same process must share no global state (except sync.Pool).
Do not rename types or methods. The spec is the API contract. Deviations require a // DEVIATION: comment with a justification.
Use conventional commits:
feat(ctx): add WithValue for middleware value propagation
fix(router): handle trailing slash in wildcard routes
perf(router): replace param map with pre-allocated [8]Param array
test(basttest): add WithIP option for IP spoofing tests
docs: update BENCH.md with v0.1.1 baselines
chore: bump Go version requirement to 1.23
Types: feat, fix, perf, test, docs, refactor, chore
Keep the subject line under 72 characters. Use the body to explain why, not what — the diff shows the what.
-
Fork the repository and create a branch from
main:git checkout -b feat/my-feature
-
Write tests first. Your PR should include tests before the implementation, or at minimum alongside it.
-
Run the full suite before pushing:
go test ./... go vet ./... -
Check benchmarks if your change touches any hot-path code (router, ctx, middleware pipeline):
go test -bench=. -benchmem -count=3 -run=^$ ./... -
Open the PR against
mainusing the pull request template. -
Address review feedback promptly. PRs with no activity for 30 days will be closed.
PRs that touch the router, Ctx pool, or the request lifecycle will receive extra scrutiny — that code runs on every request for every user.
Before submitting, confirm:
- All existing tests pass:
go test ./... - New behavior has tests
-
go vet ./...is clean - No new allocations on the hot path (benchmarks checked)
- No new external dependencies (or discussed in an issue first)
- No
reflectoutsidedocs.go/config.go - Exported names match the spec
- Errors wrapped with
fmt.Errorf("bast: ...: %w", err) - Commit messages follow the conventional commit style
Open an issue using the Bug Report template. Include:
- Go version (
go version) - OS and architecture
- Minimal reproducible example
- Actual vs expected behavior
Open an issue using the Feature Request template. Include:
- The use case — what problem does it solve?
- How it fits the framework's philosophy (explicit, lean, no magic)
- Whether it belongs in the core or as a companion package
Features that add external dependencies, use reflection on the hot path, or violate the framework's philosophy will not be accepted into core. They may be suitable as companion packages under the bastion-framework org.
By contributing, you agree that your contributions will be licensed under the MIT License.