Contributing
Branch and commit conventions, the fix-forward rule, the security posture, and the PR checklist.
Contributing
HostSSH has a small number of hard conventions. They exist because the platform hosts real customer data — the bar is production-grade, not prototype.
Commits
Conventional commits, lower-case type(scope): imperative subject, often with a trailing context
tag like (Gate A P0):
feat(agent): default HOSTNAME=0.0.0.0 for web apps (G1)
fix(platform): keep cancelled jobs terminal
docs(dev): add the deploy pipeline internals
Types in use: feat, fix, docs, chore, refactor. Scopes in use: agent, control-plane,
platform, deploy, dns, alerts, fleet, migrate, security, backup, firewall,
wp-migrate, guards, planning, ops.
Rules:
- Atomic commits — one logical change each.
- NEVER add
Co-Authored-Byor any AI attribution. This is a hard project rule. - Never commit secrets — no keys, tokens, or credentials. CI runs gitleaks and a hygiene scan.
- Stage explicit paths; don't
git add -A(you'll catchnode_modules,.next, build caches).
Branches
feat/<kebab-name> (e.g. feat/security-hardening-baseline). Branch off main; open a PR into
main. Don't commit or push to main directly.
The fix-forward rule (most important)
Every bug fix lands at the most upstream layer that makes it automatic for every app, plus a regression test, plus a catalog entry:
- Fix in the agent defaults / deploy pipeline / shared template — not on one box or one app.
- Add a
*_test.go/*.test.tsthat fails before your fix and passes after. - Append a row to
planning/BUILD-GUARDS.md. - If it's a class of failure that could reach production, wire it into the checks gate.
A fix that lives on one server is a bug waiting to reappear. See Build guards.
Zero-dependency agent
agent/go.mod has no require block, and it stays that way. The agent is one auditable binary. Use
the standard library, or shell out to system tools (docker, restic, nftables, cloudflared). CI's
license gate rejects forbidden/restricted dependencies in both the agent and the control plane.
Security posture for changes
Some changes are ask-first — get explicit sign-off before implementing:
- Auth / authz changes (RBAC, sessions, WebAuthn, RLS role model).
- Anything that changes live DB ownership/roles (
scripts/setup-db-roles.sql). - Cloudflare tunnel/DNS behavior and other outward-facing infra.
- Destructive operations on a box (wipes, restores over live data) — these are owner-gated and never auto-run from the build loop.
Prove security-sensitive changes adversarially: a feature that touches secrets, tenancy, or the agent↔control-plane channel isn't done until someone tries to break it. See Security model.
Evidence in the PR
A PR carries the proof, not just the claim:
- The verification command output (
go test ./... -race,npm run lint && typecheck && test && build). - For deploy/backup/security changes touching a real box, the captured evidence (curl output, monitor state, snapshot ids) — "evidence or it didn't happen."
- Updated
planning/TODO.mdcheckboxes and, where relevant, the build-guards catalog.
PR checklist
- Conventional commit(s), no AI attribution, atomic, explicit paths staged.
- Fix landed upstream (not per-box) + regression test added.
- Build-guards catalog updated if a bug class was fixed.
- Agent:
gofmt -l .clean,go build/vet/test ./... -racegreen, no new deps. - Control plane:
lint,typecheck,test,buildgreen. - Migrations (if any): next number, appended to
list.ts,list.test.tspasses, no shipped migration edited. - No secrets committed; gitleaks/hygiene clean.
- Security-sensitive change signed off (ask-first list above).
-
planning/TODO.mdupdated. - Verification output pasted into the PR.
The planning source of truth
planning/ is authoritative for what's built and what's next:
MIGRATION-MASTER-PLAN.md— the whole program, sequenced.TODO.md— the task board with acceptance criteria.BUILD-GUARDS.md— the fix-forward catalog.GAP-REGISTER-2026-07-01.md— the audited backlog.
Read the plan before writing code; update it after.