Security engineering handbook

The handbook we ship against, made public

Every rule below is enforced in CI, in code review, in our release train, or in our on-call. Where a rule is automated, the surface that enforces it is linked. Where it is cultural, we say so.

Sections

12

Reviewed quarterly by Security

Automated rules

142

CI-enforced, blocking

Reviewer requirement

2-person

Security tag adds Security reviewer

Key rotation cadence

90 / 180 d

Data / signing keys

01

Threat modelling, not posture marketing

Every new surface is threat-modelled in writing before code. We use STRIDE plus a money-movement extension; the document lives next to the code.

  • STRIDE table per surface, with assumed attacker and assumed insider scenarios.
  • Money-movement features add an explicit dishonest-operator row; no exceptions.
  • Threat model is reviewed by Security partner on /decision-rights and refreshed each major version.
Enforced on /regulatory-map
02

Identity, before anything

WebAuthn is the floor for every human in the production path. Service identity is workload-bound, short-lived, and never copied.

  • Customer admins, employees, contractors: WebAuthn or hardware key. No SMS, no TOTP for privileged roles.
  • Service-to-service identity is mTLS + SPIFFE-style workload attestation; tokens expire in minutes, not days.
  • Just-in-time access for all privileged paths via /access-paths; standing access is audited weekly.
Enforced on /access-paths
03

Tenant isolation as a load-bearing property

We treat cross-tenant access as physically impossible, not policy-forbidden. The design fails closed when the tenant context is missing.

  • Per-tenant data encryption keys in HSM; cross-tenant decrypt is impossible by construction.
  • Postgres RLS + a defence-in-depth proxy that rejects queries lacking tenant context.
  • Synthetic adversary tenants run continuously and page on-call on any drift; see /tenant-isolation.
Enforced on /tenant-isolation
04

Cryptography we can defend

We use boring, well-vetted primitives. We do not invent. Key rotation is a calendar event, not a project.

  • Ed25519 for signing, ChaCha20-Poly1305 for AEAD, HKDF-SHA256 for derivation. No homegrown KDFs.
  • Customer data keys rotated every 90 days, audit-trail signing keys every 180 days; see /key-rotation.
  • JWKS endpoint publishes current and next public keys 30 days before rotation.
Enforced on /key-rotation
05

Secrets do not live in repos

Every secret has a vault, a rotation cadence, and an owner. There are zero plaintext secrets in source, CI, or container images.

  • Secrets brokered at runtime from KMS-backed vault; CI gets short-lived workload identities, not API keys.
  • Pre-commit and pre-merge scanners block secret-shaped strings; verified positives auto-revoke and page.
  • Annual secrets review reconciles every vault entry to a named owner and a documented use.
06

Supply chain, end to end

We assume the supply chain is hostile until proven otherwise. SLSA L3 build provenance, signed artifacts, reproducible where possible.

  • Hermetic builds in isolated environments; artifacts signed and verified at deploy.
  • SBOM emitted for every release, diffed automatically; new critical CVEs block /release-train.
  • Third-party scripts banned on customer-facing surfaces; first-party telemetry only.
Enforced on /supply-chain
07

Code review that catches things

Two-person review is the floor. Money-movement and authZ changes require a Security reviewer with the relevant role on /decision-rights.

  • No self-merge to protected branches. No bypass for managers. No exceptions.
  • Security-tagged paths require a reviewer from the Security group; AuthZ changes require the Security partner.
  • Reviewers verify tests changed alongside code; review without tests is rejected.
08

Tests are the contract

If a behaviour is not covered by a test, it is not a behaviour. Policy is tested; pacing is tested; isolation is tested.

  • Unit, integration, contract, policy, isolation, performance — all required in CI.
  • Mutation testing runs nightly on security-critical packages; minimum kill score enforced.
  • Customer-reported defects are converted into regression tests before fix lands.
Enforced on /policy-tests
09

Deploy like you mean it

No manual production deploys. Canary, watchdogs, auto-rollback. Releases are calm; surprises are loud.

  • Every release runs the 41-item DRR on /deployment-readiness.
  • Canary 1% → 10% → 50% → 100% with watchdogs at each stage; auto-rollback on SLI burn.
  • Major versions pre-announced 30 days on /change-notice-policy.
Enforced on /release-train
10

Observability, not surveillance

We log enough to debug at 3 a.m. and not a byte more. PII is hashed or dropped at the edge.

  • Structured logs with stable schemas; PII allow-list enforced by linter.
  • Traces propagate across service boundaries; every customer-visible error has a request ID.
  • Logs are tenant-scoped; cross-tenant query is impossible from operator tooling.
11

Incident response, drilled

We rehearse the worst day. Roles are named in advance, runbooks are versioned, and the bridge starts in under 15 minutes.

  • Quarterly tabletop with named customers; see /tabletops.
  • Annual full-failover DR drill; see /dr-drills.
  • Blameless PIR within 72 hours, published count-only on /transparency for customer-visible events.
Enforced on /breach-notification
12

Vulnerability handling

A clear front door, fair timelines, predictable disclosure. We pay for what helps; we publish what is fixed.

  • Public bounty on /security/bug-bounty; safe-harbour language matches recognised industry norms.
  • SLA: triage in 1 business day; remediation 7 / 30 / 90 days by severity.
  • Fixed-and-validated issues summarised on /security-bulletins.
Enforced on /security/bug-bounty