--- id: compliance-docs-scaffolds title: Compliance docs scaffolds — Epic D of ADR-025 type: prd status: approved author: danijel created: 2026-05-20T09:18:39Z updated: 2026-05-20T09:34:30.184Z --- ## Problem Epics A–C shipped the compliance _machinery_: PII manifests + retention + sub-processor generators (A), DSR + consent + cookie banner (B), security headers + rate-limit + SBOM (C). A consumer adopting the template now has the code-enforced ~80% of the DPA/GDPR playbook. But three documentation gaps remain, each of which hurts a real reader: - **No human-authored policy artifacts.** A DPA auditor or a customer doing GDPR due diligence expects `incident-runbook.md`, `dsr-procedure.md`, `backup-policy.md`, `password-policy.md`, `device-policy.md`, `onboarding.md`, `offboarding.md` — organizational policy documents the code can't generate. Every consumer writes these from a blank page, usually badly, usually late. - **No single launch gate.** There's no answer to "are we compliant enough to ship to a paying customer?" The playbook §19 is a generic checklist; nothing maps it to _this template's_ concrete features (`pnpm compliance:emit-all --check`, `core-audit`, DSR endpoints) or flags which obligations are the consumer's own. - **No compliance map.** After 4 epics, compliance docs sprawl across `docs/compliance/`, `docs/guides/` (8+ files), `docs/decisions/` (6 ADRs), and root `compliance/`. A new agent, auditor, or engineer has no entry point answering "how is compliance structured here?" A fourth, smaller gap: `docs/guides/operator-checklist.md` has sat untracked since the ADR-022/023 work and is now stale — it predates ADR-024 (analytics) and ADR-025 (the compliance epics). The pre-launch checklist needs to cross-reference it, so it must be landed and refreshed. ADR-025 settled the strategy: fill-in templates under `docs/compliance/`, a pre-launch checklist, the `docs/compliance/` vs root `compliance/` split documented. This PRD is the implementation seed for Epic D — the final epic of ADR-025. ## Goal Ship the compliance documentation layer so a downstream consumer gets: (1) seven copy-and-fill policy templates, (2) a template-tailored pre-launch compliance checklist that maps every playbook obligation to its template mechanism or flags it consumer/infra-scope, (3) a single `compliance-overview.md` hub mapping the 22 playbook sections to their covering ADR/guide/template. Pure documentation — no code, no manifests, no conformance rules. ## In scope ### Fill-in policy templates — `docs/compliance/templates/` Seven Markdown templates, copy-to-`compliance/`-and-fill. Two tiers: - **Anchored** (reference real Epic A/B/C features): - `incident-runbook.template.md` — breach detection → triage → containment → notification (GDPR Art. 33 72h / typical DPA 24h) → post-mortem. Cross-references the audit channel (ADR-018), Sentry alerting (ADR-014), the security-headers + rate-limit surfaces (Epic C). - `dsr-procedure.template.md` — how a data subject request is received, validated, fulfilled, and recorded. Cross-references the DSR endpoints + `core-dsr` interfaces (Epic B), the audit `CONSENT_*`/`RESTRICT` actions, the `compliance/data-map.yml` artifact (Epic A). - **Skeleton** (org-policy structure, heavy `[FILL IN:]`, "policy not code-enforced by the template" banner): - `backup-policy.template.md` - `password-policy.template.md` — banner explicitly cross-references ADR-025's deferral of MFA + password policy + lockout (product-shaped, not built) - `device-policy.template.md` - `onboarding.template.md` - `offboarding.template.md` All templates use the `[FILL IN: ]` marker convention — self-documenting, greppable, collision-free. ### Pre-launch compliance checklist — `docs/guides/pre-launch-compliance-checklist.md` A two-column status table. Column 1 = playbook obligation (drawn from playbook §19 + the 22 sections). Column 2 = one of: - **Shipped by template** — with the concrete verification command (e.g. `pnpm compliance:emit-all --check`, `pnpm conformance`, securityheaders.com scan) - **Consumer responsibility** — the consumer must do this (fill a policy template, wire a vendor) - **Infra responsibility** — deploy/infra-layer (EU region pinning, TLS at edge, backups) The table operationalizes ADR-025's three-way coverage split (template-shaped / deferred / consumer-scope) into a checkable launch gate. ### Compliance overview hub — `docs/guides/compliance-overview.md` The single entry point. Maps each of the 22 playbook sections to the ADR / guide / template / epic that covers it. Includes the "what's deferred / what's consumer-scope" summary. Links one-directionally out to every compliance guide, ADR, and template. Added to CLAUDE.md "Read First". ### Operator checklist — land + refresh `docs/guides/operator-checklist.md` The existing untracked `operator-checklist.md` is committed and refreshed to current state: - Add ADR-024 operator actions (analytics backend wiring is consumer-scope; note it) - Add ADR-025 operator actions: the `compliance/` directory as committed audit evidence, the compliance drift CI gate + pre-commit hook, retention purge job scheduling, the `compliance/sub-processors.manual.yml` hand-authored file - Keep the existing ADR-022/023 content (push to remote, GitHub Apps, branch protection, weekly cadence) ### Doc wiring (one-directional) - `CLAUDE.md` "Read First" — add `compliance-overview.md` pointer - `docs/compliance/README.md` — add a "Policy templates" section pointing at `templates/` and explaining the copy-to-`compliance/` workflow + the `[FILL IN:]` convention + the `grep -rn '\[FILL IN:' compliance/` verification one-liner - `docs/glossary.md` — new entries: `pre-launch compliance checklist`, `compliance overview`, `fill-in template`, `[FILL IN:] marker` - Existing compliance guides (`dsr.md`, `consent.md`, `security-headers.md`, `rate-limiting.md`, `audit-and-compliance.md`, `ci-security.md`) — **not touched**; the overview links to them one-directionally ## Out of scope - **Any code, manifest field, ESLint rule, brand, generator, or conformance change** — Epic D is pure documentation - **Rewriting the existing compliance guides** — `dsr.md`, `consent.md`, etc. stay as-is; the overview links to them, they don't link back - **A machine-checkable "no `[FILL IN:]` left in `compliance/`" lint/CI gate** — the marker convention is chosen to _allow_ a future check, but Epic D ships docs only; the gate is a deferred follow-up - **Generating `compliance/*.md` filled artifacts** — the template ships `docs/compliance/templates/*.template.md`; the consumer copies and fills. The template never ships filled policy docs (it has no real org data) - **DPIA / RoPA / SCC / Privacy Policy / ToS / DPA document templates** — legal-instrument artifacts; consumer + legal counsel author them. The overview _names_ them as consumer-scope but Epic D ships no template for them - **Enforcing the password policy the `password-policy.template.md` documents** — MFA + password rules + lockout are ADR-025 deferrals; the template documents the policy shape, not the enforcement - **Broadening `docs/compliance/README.md` into the hub** — the README stays scoped to generator schema reference; the hub is the separate `compliance-overview.md` - **Multi-language / localized policy templates** — English only - **The Epic D docs covering Epic D itself** — no meta-documentation ## Constraints - **ADR-025** — Epic D is the fourth and final epic; strategy settled there. The `docs/compliance/` vs root `compliance/` split is canonical. - **ADR-018, ADR-014, ADR-017, ADR-022, ADR-023, ADR-024** — the overview + anchored templates cross-reference these; references must be accurate to shipped state. - **No conformance surface** — Epic D adds no manifest field, no ESLint rule, no brand. Conformance ESLint rule count stays **13** (`pii-declaration-must-be-complete`, `no-undeclared-consent-check`, `no-undeclared-rate-limit` landed in Epics A–C). Any rule-count reference in Epic D docs must say 13. - **Sequencing** — Epic D lands after Epics A, B, C so the anchored templates + checklist + overview reference shipped features, not planned ones. If a referenced feature is still in flight at decompose time, the story for that doc waits. - **`[FILL IN:]` convention** — every placeholder uses `[FILL IN: ]`. No bare `{{ }}`, no italic-only markers. - **Skeleton banner** — the 5 skeleton templates carry a banner stating the policy is organizational and not code-enforced by the template. `password-policy.template.md`'s banner cross-references ADR-025's MFA/password deferral by ADR number. - **One-directional links** — Epic D touches `CLAUDE.md`, `docs/compliance/README.md`, `docs/glossary.md` + new files only. Existing guides are not edited. - **Conventional Commits** — every story = one `docs:` or `chore(docs):` commit. - **No `--no-verify`** — pre-commit gates run; the compliance drift gate (`emit-all --check`) must still pass (Epic D changes no collections, so it will). ## Success criteria - `docs/compliance/templates/` contains 7 `*.template.md` files; each anchored one cross-references at least one real ADR + one real `pnpm` command or shipped interface; each skeleton one carries the "not code-enforced" banner. - `grep -rn '\[FILL IN:' docs/compliance/templates/` returns matches in every template (proves the convention is used); the same grep against a hypothetical filled copy in `compliance/` would return empty. - `docs/guides/pre-launch-compliance-checklist.md` is a two-column table; every "Shipped by template" row names a runnable verification command; every consumer/infra row is explicitly labelled. - `docs/guides/compliance-overview.md` maps all 22 playbook sections; every row points at a real ADR / guide / template / epic; the file is listed in CLAUDE.md "Read First". - `docs/guides/operator-checklist.md` is tracked in git (no longer untracked) and contains sections for ADR-024 + ADR-025 operator actions. - `docs/compliance/README.md` has a "Policy templates" section. - `docs/glossary.md` has the 4 new entries. - `pnpm lint && pnpm typecheck && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm compliance:emit-all --check` all green (Epic D touches no code, so these are unaffected — the criterion is "didn't break anything"). - No broken internal doc links — every `[text](path)` in the new files resolves to an existing file. ## User stories 1. As a **downstream consumer preparing for a DPA audit**, I want seven copy-and-fill policy templates so I produce the required organizational documents without starting from a blank page. 2. As a **downstream consumer**, I want every placeholder marked `[FILL IN: ]` so I (or an agent) can `grep` for unfilled spots and never ship a half-filled runbook. 3. As a **downstream consumer filling `password-policy.template.md`**, I want a banner telling me the template doesn't enforce these rules in code so I don't assume MFA/lockout is wired. 4. As a **launching team**, I want a pre-launch checklist that tells me, per obligation, whether the template handled it (and how to verify) or whether it's on me. 5. As a **compliance officer**, I want the checklist's "Shipped by template" rows to name a runnable command so I can produce verification evidence on demand. 6. As an **auditor or new engineer**, I want a single `compliance-overview.md` mapping the 22 playbook sections to where each is covered so I don't reverse-engineer the structure from scattered files. 7. As an **AI agent** asked "is feature X compliant?", I want `compliance-overview.md` in CLAUDE.md "Read First" so I start from the map, not from grep. 8. As a **template operator**, I want `operator-checklist.md` committed and current so the steps I follow reflect ADR-024 + ADR-025, not just the older ADR-022/023 state. 9. As a **downstream consumer reading the incident runbook**, I want it to reference the actual audit channel + Sentry alerting so the breach procedure uses the template's real observability surface. 10. As a **downstream consumer reading the DSR procedure**, I want it to reference the actual `/api/gdpr/*` endpoints + `core-dsr` interfaces so the procedure matches the shipped code. 11. As a **template author**, I want the existing `docs/compliance/README.md` to stay scoped to generator schema and the new `compliance-overview.md` to be the hub, so neither doc tries to be both. 12. As a **template maintainer**, I want Epic D to touch only CLAUDE.md + README + glossary + new files so the change has a small, reviewable blast radius. ## Implementation decisions ### Module surface Epic D creates **no packages and modifies no code**. It is entirely under `docs/`. **New files:** - `docs/guides/compliance-overview.md` — the hub - `docs/guides/pre-launch-compliance-checklist.md` — the two-column launch gate - `docs/compliance/templates/incident-runbook.template.md` — anchored - `docs/compliance/templates/dsr-procedure.template.md` — anchored - `docs/compliance/templates/backup-policy.template.md` — skeleton - `docs/compliance/templates/password-policy.template.md` — skeleton - `docs/compliance/templates/device-policy.template.md` — skeleton - `docs/compliance/templates/onboarding.template.md` — skeleton - `docs/compliance/templates/offboarding.template.md` — skeleton **Modified files:** - `docs/guides/operator-checklist.md` — landed from untracked + refreshed for ADR-024/025 - `CLAUDE.md` — "Read First" gains `compliance-overview.md` - `docs/compliance/README.md` — gains a "Policy templates" section - `docs/glossary.md` — 4 new entries ### Marker convention `[FILL IN: ]` — fixed `[FILL IN:` prefix (greppable), free-text description inside (self-documenting), `]` close. Example: `Notify [FILL IN: data protection officer name + email] within [FILL IN: hours — GDPR Art. 33 caps at 72] of a confirmed breach.` The README documents the convention and the verification one-liner `grep -rn '\[FILL IN:' compliance/`. ### Template tiers **Anchored** (`incident-runbook`, `dsr-procedure`): structured around real template features. Each names specific ADRs, `pnpm` commands, interfaces, endpoints. They still contain `[FILL IN:]` markers for genuinely org-specific values (on-call contacts, escalation names, SLA targets) but the _procedure skeleton_ is template-substantive. **Skeleton** (`backup-policy`, `password-policy`, `device-policy`, `onboarding`, `offboarding`): mostly `[FILL IN:]`. Each opens with a banner: > **This is an organizational policy template.** The template scaffolds the document structure; it does **not** enforce these rules in code. Fill every `[FILL IN:]` marker and have the policy reviewed by whoever owns compliance. `password-policy.template.md`'s banner adds: a sentence pointing at ADR-025's explicit deferral of MFA + password policy + lockout, so a reader understands the template has no code backing the password rules they're about to write. ### Pre-launch checklist shape Two-column Markdown table. Rows grouped by playbook section (Infrastructure, Data, Application, Secrets, Sub-Processors, Logging, Breach, DSR, Backup, SDLC, Workforce, Legal, Documentation). Column 2 values are one of three labelled kinds with the verification command inline for the "Shipped by template" kind. The checklist links to `compliance-overview.md` (the map) and to the relevant templates (the consumer-action artifacts). ### Compliance overview shape A section-by-section map of the 22 playbook sections. For each: a one-line statement of the obligation, then the covering artifact(s) — ADR number, guide path, template path, or epic. A closing summary restates ADR-025's deferrals (RBAC, MFA, breach-detection, GDPR Art. 22) and the consumer/infra-scope items (EU region, TLS, MDM, legal instruments). ### Operator checklist refresh Landing the existing untracked file as the starting point, then adding two sections: - **ADR-024 (analytics)** — analytics backend is consumer-chosen + consumer-wired; operator action is "decide whether to wire an analytics vendor; if so, run it through `/evaluate-library`." - **ADR-025 (compliance)** — `compliance/*.yml` are committed audit evidence; the compliance drift gate runs in pre-commit + CI; the retention purge job schedules per `custom.retention`; `compliance/sub-processors.manual.yml` is hand-authored for non-npm vendors. The existing ADR-022/023 content (remote push, GitHub Apps, branch protection, weekly Renovate/Socket cadence) is preserved. ### No conformance surface Epic D adds no manifest field, no ESLint rule, no brand, no generator. The conformance rule count stays 13. The compliance drift CI gate is unaffected (no collections change). ## Testing decisions Epic D is documentation — "testing" means verification, not unit tests: - **Link integrity** — every relative Markdown link in the new files resolves to an existing file. Verified by a link-check pass during the documentation story (manual `grep` of `](` targets, or a one-off script; no permanent CI gate added). - **Marker presence** — `grep -rn '\[FILL IN:' docs/compliance/templates/` returns hits in all 7 templates. - **ADR/command accuracy** — every ADR number, `pnpm` command, interface name, and endpoint path referenced in the anchored templates + overview + checklist is cross-checked against shipped state at authoring time (Epics A–C are landed by the time Epic D dispatches). - **Gate pass-through** — `pnpm lint && pnpm typecheck && pnpm test && pnpm conformance && pnpm compliance:emit-all --check` stay green; Epic D touches no code, so the criterion is "no regression." - **No new test files** — there is no code to test. No repository contract suite, no use-case unit tests, no Playwright specs. - **Prior art to mirror** — `docs/compliance/README.md` (existing, Epic A) for the annotated-doc voice; `docs/guides/ci-security.md` + `docs/guides/audit-and-compliance.md` for guide structure + the "What X requires / How the template handles it" framing; `docs/guides/operator-checklist.md` (the untracked file itself) for the checklist voice. ## Open questions - **Q1: Should the pre-launch checklist live in `docs/guides/` or `docs/compliance/`?** — Recommended: `docs/guides/`. It's a how-to/runbook (the consumer _runs_ it), and `docs/compliance/` is now reserved for generator schema + `templates/`. Keeps the "guides = how-to" / "compliance = schema + templates" split clean. - **Q2: Should the 7 templates carry a `status: template` frontmatter field so a future lint can distinguish unfilled from filled?** — Recommended: yes, minimal frontmatter (`status: template` + `playbook-section: `). Cheap, and it enables the deferred "no unfilled template in `compliance/`" check without committing to building that check now. - **Q3: Does `compliance-overview.md` duplicate ADR-025's content?** — Recommended: no — ADR-025 is the _decision record_ (why this strategy); the overview is the _navigational map_ (where each thing lives). The overview links to ADR-025 rather than restating its rationale. - **Q4: Should Epic D add a CI link-check for docs?** — Recommended: no, deferred. A docs link-checker is a reasonable future addition but it's a CI/tooling change, not a docs deliverable; bundling it into a pure-docs epic widens scope. Note it in "Out of scope (deferred)." - **Q5: Refresh `operator-checklist.md` content fully, or land-then-refresh in two commits?** — Recommended: two stories — story 1 lands the file verbatim as `chore(docs)`, story 2 refreshes it as `docs(compliance)`. Keeps the "what existed" vs "what changed" diff legible for review. ## Out of scope (deferred) - **CI link-checker for docs** — reasonable future tooling PRD; not a pure-docs deliverable (see Q4) - **A `no-unfilled-template` check** — verifying `compliance/*.md` has no `[FILL IN:]` left; the marker convention + Q2 frontmatter enable it, but building the check is deferred - **DPIA / RoPA / SCC / Privacy Policy / ToS / DPA templates** — legal instruments; consumer + counsel author them - **Localized (non-English) policy templates** - **Auto-generating filled policy docs from template config** — the template has no org data; filling is inherently a consumer action - **A compliance dashboard / status page** — the pre-launch checklist is static Markdown; a live dashboard is out of scope ## Further notes - **Builds on:** ADR-025 (strategy umbrella — Epic D is its fourth epic), Epic A PRD (`compliance-manifests-pii-retention-subprocessors` — the overview + checklist reference its generators + `compliance/*.yml`), Epic B PRD (`dsr-consent-and-cookie-banner` — the `dsr-procedure` template references its endpoints + interfaces), Epic C PRD (`security-headers-rate-limit-sbom` — the `incident-runbook` + checklist reference its headers + rate-limit + SBOM). - **Closes:** ADR-025. With Epic D, all four epics of the EU compliance baseline are decomposed; the template's compliance coverage reaches the ~80% ADR-025 targeted, with the remaining ~20% explicitly documented as deferred or consumer/infra-scope in `compliance-overview.md`. - **Sequencing:** Epic D dispatches last. Within Epic D: (1) land `operator-checklist.md` verbatim, (2) refresh it, (3) write the 7 templates (anchored first — they need the most cross-referencing), (4) write the pre-launch checklist, (5) write `compliance-overview.md`, (6) wire CLAUDE.md + README + glossary. The overview is written near-last so it can link to the finished templates + checklist. - **Stakeholders:** downstream consumers preparing for audits (primary beneficiary — get policy templates + launch gate), auditors + compliance officers (get the overview map + verifiable checklist), template operators (get a current operator checklist), AI agents (get `compliance-overview.md` as a Read-First entry point), template authors (small reviewable blast radius — docs only). - **PII note:** Epic D ships no code and stores no data — no PII surface, no `custom.pii` changes, no DSR interaction. The `password-policy` deferral note is the only place Epic D references unbuilt behavior, and it does so explicitly to prevent a false enforcement assumption.