This guide covers commit message format, code style, and the PR submission process.
All commits must follow Conventional Commits format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Commit Types
feat: New feature
fix: Bug fix
docs: Documentation changes
style: Code style changes (formatting, no logic changes)
refactor: Code refactoring (no behavior changes)
perf: Performance improvements
test: Adding or updating tests
build: Build system or dependency changes
ci: CI/CD configuration changes
chore: Maintenance tasks
revert: Revert a previous commit
Examples
feat(policy): add support for CEL expressions in bot matching
fix: resolve event loop thrashing in proof-of-work solver
docs: update installation guide for Go 1.24
refactor(store)!: change Store interface to return errors
BREAKING CHANGE: Store.Get now returns ([]byte, error) instead of []byte
Commit Rules
- Keep descriptions concise
- Use imperative mood (“add feature” not “added feature”)
- Use lowercase for descriptions
- No trailing period
- Add
! after type/scope for breaking changes
- Use
BREAKING CHANGE: in footer for breaking changes
- Reference issues/PRs in footer when applicable
Signed Commits (REQUIRED)
ALL commits MUST be signed with --signoff. This is mandatory and enforced by commitlint.
Sign Your Commits
Every commit must include a Signed-off-by line:
git commit --signoff -m "feat: add new feature"
Or use the -s shorthand:
git commit -s -m "fix: resolve race condition"
AI Agent Attribution
If you’re using an AI coding tool, you must disclose it in the commit footer:
feat: implement rate limiting for challenge requests
Assisted-by: Claude 4.5 Sonnet via OpenCode
Signed-off-by: Your Name <[email protected]>
Format:
Assisted-by: [Model Name] via [Tool Name]
Automatic Signoff
Configure Git to sign off commits automatically:
git config --local commit.gpgsign true
Or use a Git hook (see .husky/commit-msg in the repository).
Code Style
Anubis follows Go standard library idioms:
- Formatting: Use
goimports (run npm run format)
- Package aliases: Only when names collide
- Naming:
PublicFunctionsAndTypes in PascalCase
privateFunctionsAndTypes in camelCase
- Acronyms stay uppercase (
URL, HTTP, IP, DNS)
- Errors:
- Sentinel errors as package-level
Err prefixed variables
- Wrap with
fmt.Errorf("package: context: %w", err)
- Use
errors.Is for validation
- Logging:
- Use
log/slog for structured logging
- Pass loggers as function arguments
- Prefer
slog.Debug unless users need to see the message
- Configuration:
- Use both
json and yaml struct tags
- Use pointer values for optional fields
- Validate with
Valid() error methods
- Tests:
- Use table-driven tests
- Use
t.Helper() in helper functions
- Use
t.Cleanup() for teardown
- Prefer same-package tests over
_test packages
JavaScript/TypeScript
- Source in
web/js/
- Built with esbuild
- Uses Preact (not React)
- Use
const by default
- Keep functions small
- No linter config - rely on code review
Templ Templates
.templ files in web/ generate Go code
- Run
npm run assets after modifying
- Keep logic in Go, not templates
- Templates receive typed Go parameters
Pull Request Process
Before Submitting
-
Build assets:
-
Run tests:
npm run test
npm run test:integration
-
Run linting:
-
Format code:
-
Update CHANGELOG:
Add your changes to
[Unreleased] in docs/docs/CHANGELOG.md
PR Checklist
Creating the PR
-
Push your branch:
git push origin feature/my-feature
-
Open PR on GitHub
-
Fill out template (see
.github/PULL_REQUEST_TEMPLATE.md)
-
Request review
PR Review
Anubis is security software - code reviews are strict:
- Security implications are carefully evaluated
- Test coverage is required
- Adversarial inputs are considered
- Breaking changes require discussion
Security Considerations
Anubis is security software. All contributions must consider adversarial scenarios.
Security-First Principles
- Input validation: Validate all external input
- Error handling: Don’t leak internal state in error messages
- Rate limiting: Consider DoS scenarios
- Cryptography: Use standard library crypto packages
- Dependencies: Minimize external dependencies
Reporting Security Issues
See SECURITY.md for the security policy and reporting process.
Key Conventions
Configuration
- YAML-based policy files
- Config structs validate via
Valid() error returning sentinel errors
- See
lib/config/ for examples
Store Interface
lib/store.Interface abstracts key-value storage
- Implementations in
lib/store/
- Always handle errors from Store operations
Environment Variables
- Parsed from flags via
flagenv
- Use
.env files locally (loaded by godotenv/autoload)
- NEVER commit
.env files
Asset Building
- JS/CSS assets embed into Go binary
- Always run
npm run assets before go test or go build
- Generated files are committed to the repo
CEL Expressions
- Policy rules support Common Expression Language
- See
lib/policy/expressions/ for implementation
- Use for advanced bot matching rules
Project Layout
Key directories:
cmd/anubis/ - Main entrypoint
lib/*/ - Public library code (no API stability guarantees)
internal/*/ - Private implementation code
test/*/ - Smoke tests
web/ - Frontend templates
xess/ - CSS framework
Getting Help