Implementation seed for ADR-025 Epic D, the final epic: seven fill-in policy templates under docs/compliance/templates/ (2 anchored, 5 skeleton with not-code-enforced banner), a two-column pre-launch compliance checklist mapping playbook obligations to template mechanisms, a compliance-overview.md hub, and a landed + refreshed operator-checklist.md. Pure docs — no code, no conformance changes. Status: approved — ready for pnpm work decompose.
224 lines
22 KiB
Markdown
224 lines
22 KiB
Markdown
---
|
||
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: <description>]` 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: <description>]`. 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: <description>]` 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: <description>]` — 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: <n>`). 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.
|