- Tenant isolation is not optional. Every query against a tenant-scoped
table runs inside
session_for_org(...). RLS is forced on every such table. If you can't see how to do something without bypassing RLS, stop and ask. - Idempotency is mandatory for every webhook handler, every Inngest function, every external mutation.
- Every external call has a timeout, a retry, and a circuit breaker.
- All LLM calls go through
apps/api/atlas/llm/. No direct SDK use anywhere else. - Citations are sacred. Refuse rather than hallucinate.
- No customer data in logs. Log IDs, hashes, lengths, timings — never message bodies. The structured logger hashes known PII fields automatically.
- Migrations are forward-only. Use expand-migrate-contract across two releases for destructive changes.
- No secrets in code or commits. Secrets live in Railway/Vercel env stores; per-row customer secrets are envelope-encrypted via KMS.
- Type-safe end to end.
mypy --strictin Python,tsc --strictin TS. - Tests are not optional. Every PR includes them.
- Don't call OpenAI/Anthropic from route handlers — go through
atlas/llm/. - Don't
SELECT *in production queries. - Don't trust webhook payloads without signature verification.
- Don't embed user input directly in LLM system prompts — use
<context>/<question>delimiters. - Don't use floats for money — integer USD micros only.
- Don't introduce a new dependency without a written justification in the PR.
- Target ≤ 400 LOC diff.
- Conventional Commits (
feat:,fix:,chore:,docs:, etc.). - Fill out the PR template (what / why / how tested / risks / rollout).
- At least one reviewer. Security-sensitive paths require two (see
CODEOWNERS). - Eval run is required for changes under
apps/api/atlas/query/orapps/api/atlas/ingestion/.
- Python 3.12, async-first, Pydantic v2, SQLAlchemy 2.0 async.
- Lint + format:
uv run ruff check . && uv run ruff format . - Types:
uv run mypy --strict atlas - Tests:
uv run pytest -q
- TS 5.4+,
tsc --strict, ESLint + Prettier. - React functional components only.
- TanStack Query for server state; Zustand for UI state.
- No
any, no// @ts-ignorewithout inline justification.
- Look at the data model first. Bad migrations are forever.
- Read every SQL query against tenant tables. Confirm it runs through
session_for_org. - Run the change locally if you can't reason about it from the diff.
- Be kind. Critique the code, not the author.