Auditor Handbook
On this page
Purpose
This page is the canonical entry point for auditors. It does not duplicate the operational documents — it links to them and tells the auditor which document satisfies which requirement. Issue #264.
For the day-to-day operator perspective, start at Security Operations & Runbooks. For framework control mappings, start at ATO Readiness or NIST 800-53 Mapping.
One-page artefact map
| Auditor request | Document | Source |
|---|---|---|
NIST SP 800-53 Rev. 5 control mapping |
237 lines, full Rev. 5 control catalogue traced to Canopy components |
|
IRS Publication 1075 compliance matrix (Federal Tax Information) |
Per-control mapping for FTI handling in canopy-tanf, canopy-medicaid |
|
HIPAA compliance summary (Protected Health Information) |
Per-control mapping for PHI handling in canopy-medicaid, canopy-chip |
|
IEVS / SSA SOLQ-BENDEX authorisation |
Authorisation matrix at |
|
Data-flow diagrams (PII / FTI / IEVS / signing) |
4 Mermaid diagrams: PII (SSN), FTI, IEVS, determination signing |
|
Encryption inventory (rest + transit) |
Per-data-class table: AES-256-GCM (SSN field-level), TLS 1.3 (transit), ECDSA P-256 (signing — integrity, not confidentiality), SHA-256 (audit hash chain — integrity) |
|
Access control / RBAC model |
Real role names from |
|
Incident response procedure |
Security Operations §Incident Response + Incident Response Runbook |
6-phase procedure (DETECT, CLASSIFY, CONTAIN, ERADICATE, RECOVER, NOTIFY) |
Key rotation runbook (signing + encryption + JWKS) |
Security Operations §Key Rotation + Signing Key Rotation Runbook |
ECDSA P-256, Keycloak JWKS, AES-256-GCM |
Breach notification chain (federal + state) |
Per-data-class deadlines: IRS (FTI ≤ 24 h), CMS (HIPAA per HHS rule), state breach notification law |
|
Data retention policy |
Per-data-class retention: FTI audit logs 7 yr floor (Pub 1075 AU-11); HIPAA audit logs 6 yr (45 CFR §164.530(j)); audit retention is a per-jurisdiction ruleset value bounded below by the federal floor — becoming a general config-driven retention + legal-hold lifecycle under ADR-041 (#1303, superseding the ADR-014 chain-v2 §C7 mechanism) |
|
ADR catalogue (architectural decisions) |
ADR-001 through ADR-015 in nav.adoc |
Each ADR carries a Status / Context / Decision / Consequences block |
Federal program requirements |
SNAP, TANF, Medicaid, CHIP, CAPS, WIC mandatory fields traced to source regulations |
|
Gap analysis (what’s not yet ATO-ready) |
Per-control gap with target deadline |
What’s in scope for an audit today
-
SNAP only (UAT target: September 2026). TANF, Medicaid, CHIP, CAPS, WIC services are implemented but not part of the September UAT scope. Audit-readiness for those programs follows the same model — ATO mapping under
ato-readiness.adoc, Pub 1075 / HIPAA matrices already cover their data classes. -
Federal data classes: FTI (TANF + Medicaid only, ADR-004), HIPAA PHI (Medicaid only), IEVS (canopy-verification, scoped to SNAP under 7 USC §2025(e)), SSA SOLQ-BENDEX (canopy-verification, SSA CMA pending).
-
Production deployment posture: not yet — Canopy ships as open-source reference; jurisdictions deploy and obtain their own ATO. Georgia DHS pursues ATO via the path documented in
ato-readiness.adoc.
Hash-chain audit (FTI + general events)
Superseded by ADR-041 (epic &74). The FTI-special hash chain and the chain-v2 machinery documented in this section are being retired for a general configurable structured-logging facility + jurisdiction-owned per-field redaction, with tamper-evidence + retention of the exported audit copy delegated to the deployment logging facility. This section describes the currently-live mechanism; retirement (including the citation-for-hearing redesign and the chain-verification endpoints below) is gated behind a proven replacement and tracked as #1304. Read it as the outgoing design until that cutover lands.
Two append-only hash chains underpin tamper-evidence:
-
audit_eventsin canopy-security — every event published on thecanopy.eventsexchange persists withprevious_hash/event_hashSHA-256 columns. -
fti_audit_login canopy-tanf and canopy-medicaid — Pub 1075 §9 reportable. Same hash-chain mechanism, serialised per database on the constantcanopy.fti_chainadvisory lock (#1245 — the pre-#1245 caller-derived lock could fork the chain). See ADR-014.
Reading chain-verification status (#1205, ADR-014 Amendment 9)
Chain verification is served by the unified /v1/security/chain/* namespace
(the old GET /v1/security/verify-chain and POST /v1/security/fti/chain-verify
are deleted; full endpoint reference:
canopy-security API). What an auditor needs:
-
Status —
GET /v1/security/chain/status?family={audit|fti}[&service=]returns one of SIX states:healthy,verifying(HTTP 200) orunknown,stale,error,breached(HTTP 503 — the SAME typed body, so a consumer reading only the status code fails closed). Onlyhealthymeans "verified, at head, anchored, fresh";verifyingmeans coverage is advancing but incomplete/unanchored; everything on the 503 side means treat the chain as unverified (unknown), no longer fresh (stale), environmentally broken (error), or integrity-breached (breached— Pub 1075 §9 reportable). The body’sreasons[]enumerates every firing input; onbreachedit carries the incident id + exact position. -
Manual verification —
POST /v1/security/chain/verifyenqueues a durable job (202 +job_id+ poll URL; 409 if one is already active for the target); pollGET /v1/security/chain/verify-jobs/{id}throughqueued → running → done|error. Manual runs never alter the status machine — a manual pass is evidence, not a reset. -
Attestation —
GET /v1/security/chain/attest?event_id=…&family=…attests ONE event:attested: trueonly when the row is found, belongs to the ACTIVE topology, and sits within BOTH the verified-through cursor AND the trusted (verifier-checked, externally anchored) manifest tip, with the family in an attestable state. This is the input behind "Cite for hearing" — no attestation, no citation (502). -
A breach LATCHES. Once
breached, the state persists — a clean scheduled pass never clears it. Resolution is the documented manual runbook only (evidence inspection under the incident-admin credential → ticket → manual revalidation job → guarded SQL resolve with the actor recorded fromsession_user): Security Operations §chain-v2 Incident-Resolution Runbook.
Dormancy (until the #1279 cutover): the background verifiers ship
disabled (CANOPY_SECURITY__CHAIN_V2_VERIFY_ENABLED=false) and their database
roles are NOLOGIN, so GET /v1/security/chain/status reports unknown →
503 by design (the #1245 fail-closed posture, preserved by status code)
and verify/attest return 503 verifier_unavailable. An auditor MUST NOT
read the dormant unknown as intact. The FTI chains are audited through the
SAME flow (#1206 MR-3; the legacy GET /v1/security/fti/chain-status is
deleted): GET /v1/security/chain/status?family=fti&service=canopy-tanf (or
canopy-medicaid) + GET /v1/security/chain/attest with the same target.
One FTI-only reason exists: breached with legacy_breach_latched is the
#1245 latched-breach posture riding the unified endpoint — a v1 chain-break
finding that stays visible (sticky, Pub 1075 §9 reportable) even while the
family is dormant, retiring with the v1 evidence table at #1279. The worker
portal degrades accordingly: chain badges show "Unable to verify chain", and
"Cite for hearing" refuses to issue (502).
CI / build-time enforcement
Auditors should know that several compliance properties are gated at build time, not only at runtime:
| Gate | Enforces |
|---|---|
|
FTI / IEVS / SSA SOLQ-BENDEX field names cannot appear in unauthorised services. Authorisation matrix at |
|
Hardcoded |
|
Jurisdiction values cannot leak outside the ruleset mechanism (#1226): the Georgia benefits helpline in any form anywhere in |
|
A federal/statutory universe in canopy-reporting must arrive as one of the two blessed completeness types — |
|
Every |
|
Every plan Status row uses the canonical vocabulary (Not started / In progress / Done / Deferred / Blocked / N/A). Surfaces drift between Status tables and code state. |
Contacts
-
Security operations: see
security-operations.adoc§Incident Response — escalation chain. -
Compliance questions: file a GitLab issue with label
type::complianceand the appropriatecompliance::scoped label (pub-1075,hipaa,cma,ievs,wcag-21-aa). -
Federal partner notifications: see
security-operations.adoc§Breach Notification Chain.