Skip to content
Foxx Cyberfoxxcyber/docs

The Rulebook

The non-negotiable invariants every AI coding session must follow before it writes a line — and why each one is machine-checkable, not just written down.

Every Foxx Cyber repository carries a CLAUDE.md — a file the AI assistant is instructed to read before touching code. It isn't aspirational. It's the contract, and the rules that matter most are enforced by machines that don't get tired.

The rules below are the actual invariants from HLE-AIO, our reference application. Other products carry the same shape adapted to their stack.

The non-negotiable invariants

  1. Tenant scoping on every query. A tenant identifier (for HLE-AIO, a household ID) is never accepted from the client. Every scoped query — including the WHERE clause of every UPDATE/DELETE by id — carries the server-derived scope. This is the single most important rule in the codebase, and it exists because a cross-tenant data-exposure bug happened once, early on. It is now guarded by a regression test and a CI check.
  2. Auth gate first. Server functions compose auth / admin / tenant middleware from one place. There is no unauthenticated server function outside login, first-run setup, and the health check.
  3. Parameterized SQL only. Queries use tagged-template parameterization. User input is never interpolated into a query string. No raw string-built SQL anywhere in the codebase.
  4. Validation at the boundary. Every server function validates its input against a schema before the handler runs, so malformed or hostile input never reaches business logic.
  5. Migrations are append-only. Editing an already-applied migration is treated as drift and is a hard startup error. You write a new migration instead — the schema's history stays truthful.
  6. Audit the security-relevant events. Anything touching login, sessions, passwords, user or tenant administration, backups, or destructive deletes is written to an append-only audit log.
  7. No rule suppressions, ever. No eslint-disable, no @ts-ignore, no @ts-expect-error, no @ts-nocheck, no explicit any to dodge the type checker. This rule exists because I watched an AI assistant almost ship suppressions to make a warning go away. That's exactly how unreviewed code sneaks past the gates — so it's banned, and the ban is enforced in CI.

Rules 1–4 are the ones that prevent the classic AI-generated-code failures: broken multi-tenant isolation, missing authorization, and injection. They are stated as invariants precisely because an AI assistant, left to pattern-match, will occasionally produce a handler that looks right and quietly omits one of them. The rule makes the omission a violation instead of a judgment call.

Why "written down" isn't enough

A CLAUDE.md sentence is a good start, but prose can be forgotten between sessions and can't fail a build. So wherever a rule can be turned into a machine check, it is:

RuleHow it's enforced by a machine
No rule suppressionsCI greps every change for the forbidden tokens; a match fails the build
Parameterized SQL onlySame diff-grep gate flags raw SQL string-building
No unsafe HTML sinksDiff-grep flags dangerouslySetInnerHTML
Tenant scopingRegression test reproducing the original cross-tenant bug + invariant tests over the query layer
Migrations append-onlyChecksum drift detection aborts startup
Type safetytsc --noEmit in CI, no suppressions permitted to pass it

The principle: a lint rule beats a CLAUDE.md sentence, and a CI job beats both. The written rule teaches the intent; the machine check makes backsliding impossible.

The pre-flight every change runs

Before any change is declared complete, the assistant runs — and I verify the output of — the project's full pre-flight. For HLE-AIO that's a single command:

bun run typecheck && bun run lint && bun run check && bun run test

"It should work" is not an acceptable answer. The verification has to be actual, and the output has to be read. When the pre-flight and the CI guardrails both pass on a change I've read and understood, it can land — and not before.

Every security fix gets a regression test

When a bug crosses a security boundary — auth, tenancy, injection — the fix isn't done until there's a test that fails on the pre-fix code. That test is the only thing that reliably prevents the same class of bug from shipping twice, in this codebase or the next one the AI works in.

Last updated August 19, 2026