chore(work): decompose compliance-manifests epic
Generated 1 epic + 8 stories under docs/work/epics/ from the approved PRD docs/work/prds/compliance-manifests-pii-retention-subprocessors.prd.md. Stories cover type primitives, ESLint rule, ADR-022 amendment, retention purge job, template backfill, three generator scripts, pre-commit + CI integration, and docs/compliance/ reference files. Ready for `pnpm work dispatch --execute` to begin implementation.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"updated_at": "2026-05-18T17:55:38.797Z",
|
||||
"updated_at": "2026-05-18T18:06:16.046Z",
|
||||
"epics": {
|
||||
"binder-wrap-helper": {
|
||||
"status": "done",
|
||||
@@ -142,6 +142,97 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"compliance-manifests-pii-retention-subprocessors": {
|
||||
"status": "in-progress",
|
||||
"title": "Declarative compliance manifests (PII + retention + sub-processors) — Epic A of ADR-025",
|
||||
"prd": "docs/work/prds/compliance-manifests-pii-retention-subprocessors.prd.md",
|
||||
"stories": {
|
||||
"01-pii-retention-type-primitives": {
|
||||
"status": "in-progress",
|
||||
"title": "PII and retention type primitives in core-shared",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [],
|
||||
"blocks": []
|
||||
},
|
||||
"02-eslint-rule-pii-declaration-complete": {
|
||||
"status": "todo",
|
||||
"title": "Add pii-declaration-must-be-complete ESLint rule to core-eslint",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"01-pii-retention-type-primitives"
|
||||
],
|
||||
"blocks": [
|
||||
"05-backfill-template-collections"
|
||||
]
|
||||
},
|
||||
"03-adr-022-amendment-and-evaluate-library-skill": {
|
||||
"status": "todo",
|
||||
"title": "ADR-022 amendment for sub-processor fields and evaluate-library skill update",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"01-pii-retention-type-primitives"
|
||||
],
|
||||
"blocks": []
|
||||
},
|
||||
"04-retention-purge-job": {
|
||||
"status": "todo",
|
||||
"title": "Background retention purge job in core-shared",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"01-pii-retention-type-primitives"
|
||||
],
|
||||
"blocks": []
|
||||
},
|
||||
"05-backfill-template-collections": {
|
||||
"status": "todo",
|
||||
"title": "Backfill existing template Payload collections with PII and retention metadata",
|
||||
"ac_total": 5,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [],
|
||||
"blocks": [
|
||||
"06-compliance-generator-scripts"
|
||||
]
|
||||
},
|
||||
"06-compliance-generator-scripts": {
|
||||
"status": "todo",
|
||||
"title": "Compliance generator scripts (emit-data-map, emit-retention-policy, emit-sub-processors, emit-all)",
|
||||
"ac_total": 4,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"01-pii-retention-type-primitives",
|
||||
"05-backfill-template-collections"
|
||||
],
|
||||
"blocks": [
|
||||
"07-pre-commit-and-ci-integration",
|
||||
"08-docs-compliance-reference-files"
|
||||
]
|
||||
},
|
||||
"07-pre-commit-and-ci-integration": {
|
||||
"status": "todo",
|
||||
"title": "Pre-commit hook and CI integration for compliance drift detection",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"06-compliance-generator-scripts"
|
||||
],
|
||||
"blocks": []
|
||||
},
|
||||
"08-docs-compliance-reference-files": {
|
||||
"status": "todo",
|
||||
"title": "docs/compliance reference example files and README",
|
||||
"ac_total": 1,
|
||||
"ac_completed": 0,
|
||||
"depends_on": [
|
||||
"06-compliance-generator-scripts"
|
||||
],
|
||||
"blocks": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"library-evaluation-policy": {
|
||||
"status": "done",
|
||||
"title": "Library evaluation policy — skill, traces, enforcement stack",
|
||||
@@ -345,7 +436,68 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ready": [],
|
||||
"blocked": [],
|
||||
"ready": [
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "01-pii-retention-type-primitives",
|
||||
"title": "PII and retention type primitives in core-shared"
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "05-backfill-template-collections",
|
||||
"title": "Backfill existing template Payload collections with PII and retention metadata"
|
||||
}
|
||||
],
|
||||
"blocked": [
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "02-eslint-rule-pii-declaration-complete",
|
||||
"title": "Add pii-declaration-must-be-complete ESLint rule to core-eslint",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/01-pii-retention-type-primitives"
|
||||
]
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "03-adr-022-amendment-and-evaluate-library-skill",
|
||||
"title": "ADR-022 amendment for sub-processor fields and evaluate-library skill update",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/01-pii-retention-type-primitives"
|
||||
]
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "04-retention-purge-job",
|
||||
"title": "Background retention purge job in core-shared",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/01-pii-retention-type-primitives"
|
||||
]
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "06-compliance-generator-scripts",
|
||||
"title": "Compliance generator scripts (emit-data-map, emit-retention-policy, emit-sub-processors, emit-all)",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/01-pii-retention-type-primitives",
|
||||
"compliance-manifests-pii-retention-subprocessors/05-backfill-template-collections"
|
||||
]
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "07-pre-commit-and-ci-integration",
|
||||
"title": "Pre-commit hook and CI integration for compliance drift detection",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/06-compliance-generator-scripts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"epic": "compliance-manifests-pii-retention-subprocessors",
|
||||
"story": "08-docs-compliance-reference-files",
|
||||
"title": "docs/compliance reference example files and README",
|
||||
"waiting_on": [
|
||||
"compliance-manifests-pii-retention-subprocessors/06-compliance-generator-scripts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"needs_prd_ship": []
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: 01-pii-retention-type-primitives
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: PII and retention type primitives in core-shared
|
||||
type: technical-story
|
||||
status: in-progress
|
||||
feature: core-shared
|
||||
depends-on: []
|
||||
blocks:
|
||||
[
|
||||
02-eslint-rule-pii-declaration-complete,
|
||||
03-adr-022-amendment-and-evaluate-library-skill,
|
||||
04-retention-purge-job,
|
||||
05-backfill-template-collections,
|
||||
06-compliance-generator-scripts,
|
||||
]
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Produce the TypeScript type primitives (`PiiCategory`, `DataProcessingPurpose`, `RetentionAction`, `RetentionTrigger`, `FieldRetention`, `FieldPii`, `CollectionRetention`, `PurgeSchedule`, `PAYLOAD_AUTH_PII_DEFAULTS`) in `core-shared/payload/` plus the ambient module declaration that extends Payload's `Field` and `CollectionConfig` custom fields to be typed. These are the "manifest" for the whole epic — everything else depends on them existing and compiling.
|
||||
|
||||
## Why
|
||||
|
||||
All downstream stories need the type contracts before they can compile. Landing these first means every subsequent story gets full TypeScript coverage on Payload config files, and the ESLint rule has a known schema to validate against.
|
||||
|
||||
## Done when
|
||||
|
||||
- `packages/core-shared/src/payload/pii-types.ts` exports `PiiCategory`, `DataProcessingPurpose`, `RetentionTrigger`, `RetentionAction`, `FieldRetention`, `FieldPii`, and `PAYLOAD_AUTH_PII_DEFAULTS` (with `null` for credential fields: `password`, `salt`, `hash`, `resetPasswordToken`, `resetPasswordExpiration`, `loginAttempts`, `lockUntil`, `apiKey`, `apiKeyIndex`).
|
||||
- `packages/core-shared/src/payload/retention-types.ts` exports `PurgeSchedule` and `CollectionRetention`.
|
||||
- `packages/core-shared/src/payload/payload-custom-ambient.d.ts` augments the `payload` module to type `Field.custom.pii?: FieldPii` and `CollectionConfig.custom.retention?: CollectionRetention` / `CollectionConfig.custom.authPii?: Record<string, FieldPii | null>`.
|
||||
- Both modules are re-exported from the `core-shared` barrel (or a `payload` sub-barrel).
|
||||
- Vitest tests cover: `@ts-expect-error` on malformed `FieldPii` (missing required fields), `PAYLOAD_AUTH_PII_DEFAULTS` structure (credential fields are `null`, `email` is non-null with correct shape).
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `packages/core-shared/src/payload/pii-types.ts`
|
||||
- `packages/core-shared/src/payload/retention-types.ts`
|
||||
- `packages/core-shared/src/payload/payload-custom-ambient.d.ts`
|
||||
- Vitest tests for both type files.
|
||||
- Barrel export additions.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- ESLint rule (Story 02).
|
||||
- Retention purge job (Story 04).
|
||||
- Collection backfill (Story 05).
|
||||
- Generator scripts (Story 06).
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `pii-types.ts`, `retention-types.ts`, and `payload-custom-ambient.d.ts` to `packages/core-shared/src/payload/` — complete type contracts per the PRD, ambient Payload module augmentation, `PAYLOAD_AUTH_PII_DEFAULTS` constant with `null` for credential fields, vitest tests verifying shape and defaults, barrel exports — all gates pass on this commit.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
id: 02-eslint-rule-pii-declaration-complete
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: Add pii-declaration-must-be-complete ESLint rule to core-eslint
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: core-eslint
|
||||
depends-on: [01-pii-retention-type-primitives]
|
||||
blocks: [05-backfill-template-collections]
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Add the `conformance/pii-declaration-must-be-complete` rule to `@repo/core-eslint` at warn severity. The rule detects `custom: { pii: { ... } }` blocks in Payload collection/field TypeScript files and warns when any required sub-field (`category`, `purpose`, `exportable`, `restrictable`) is missing.
|
||||
|
||||
## Why
|
||||
|
||||
Provides sub-second editor and CI feedback when a developer partially declares a `custom.pii` block. Without this rule, a missing `exportable: false` could silently survive into `compliance/data-map.yml` and appear incorrectly in an audit report.
|
||||
|
||||
## Done when
|
||||
|
||||
- `packages/core-eslint/rules/pii-declaration-must-be-complete.js` exists and passes RuleTester fixtures.
|
||||
- Fixtures cover: complete `custom.pii` → no warning; `category` missing → warn; `purpose` missing → warn; `exportable` missing → warn; `restrictable` missing → warn; non-pii `custom` block → no-op; malformed/non-object `custom.pii` → no-op.
|
||||
- Rule registered in `plugin.js` and `base.js` at `"warn"` severity.
|
||||
- ESLint rule count in `docs/guides/conformance-quickref.md` and `CLAUDE.md` updated from 7 to 8.
|
||||
- `pnpm lint` exercises the rule; all gates pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `packages/core-eslint/rules/pii-declaration-must-be-complete.js` + RuleTester test file.
|
||||
- `packages/core-eslint/plugin.js` + `packages/core-eslint/base.js` — rule registration at warn.
|
||||
- `docs/guides/conformance-quickref.md` + `CLAUDE.md` conformance rule count bump.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Auto-fix path — warn only, no `--fix`.
|
||||
- Migration of existing collection files — that is Story 05's job.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `pii-declaration-must-be-complete.js` rule to `@repo/core-eslint` — AST rule detecting incomplete `custom.pii` blocks in Payload config files, RuleTester fixtures (complete passes, each missing required field warns, non-pii custom block is no-op), register in `plugin.js` + `base.js` at `"warn"`, update conformance rule count in `conformance-quickref.md` and `CLAUDE.md` (7 → 8) — all gates pass on this commit.
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
id: 03-adr-022-amendment-and-evaluate-library-skill
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: ADR-022 amendment for sub-processor fields and evaluate-library skill update
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: tooling
|
||||
depends-on: [01-pii-retention-type-primitives]
|
||||
blocks: []
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Amend ADR-022 to add the discriminated-union sub-processor fields to every library trace frontmatter (`is-sub-processor`, `processes-pii`, and conditionally `data-sent`, `region`, `dpa-signed`, `sccs-required`, `contact`). Update `.claude/skills/evaluate-library/SKILL.md` to prompt for these new fields during trace authoring. Backfill existing `docs/library-decisions/*.md` traces so they comply with the amended schema.
|
||||
|
||||
## Why
|
||||
|
||||
Without the skill update, a developer running `/evaluate-library` today produces a trace missing the sub-processor fields, causing `emit-sub-processors.mjs` (Story 06) to silently skip it. Making the skill ask the questions in one pass prevents traces that require a later backfill amendment.
|
||||
|
||||
## Done when
|
||||
|
||||
- `docs/decisions/ADR-022.md` documents the discriminated-union sub-processor frontmatter specification: `is-sub-processor: boolean`, `processes-pii: boolean`, and the 5 conditional required fields when `is-sub-processor: true`.
|
||||
- `.claude/skills/evaluate-library/SKILL.md` updated with two new prompts ("is this library a sub-processor?" / "does it process PII in-process?"), conditional prompt for the 5 required sub-processor fields, and an updated trace frontmatter template.
|
||||
- All existing `docs/library-decisions/*.md` traces gain `is-sub-processor` + `processes-pii` fields (with `false` / `false` as the baseline for non-sub-processors, or correct values where applicable).
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `docs/decisions/ADR-022.md` — sub-processor discriminated union specification.
|
||||
- `.claude/skills/evaluate-library/SKILL.md` — new prompts + updated trace template.
|
||||
- All existing `docs/library-decisions/*.md` traces — `is-sub-processor` + `processes-pii` field additions.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- `emit-sub-processors.mjs` generator implementation (Story 06).
|
||||
- Weekly `dpa-signed` staleness check in CI — that is an ADR-023 cross-reference; document it, but do not implement the cron here.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Amend `docs/decisions/ADR-022.md` with the sub-processor discriminated union frontmatter spec, update `.claude/skills/evaluate-library/SKILL.md` with new prompts and trace template, and backfill all existing `docs/library-decisions/*.md` traces with `is-sub-processor` + `processes-pii` fields — all gates pass on this commit.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
id: 04-retention-purge-job
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: Background retention purge job in core-shared
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: core-shared
|
||||
depends-on: [01-pii-retention-type-primitives]
|
||||
blocks: []
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Add `core-shared/payload/retention-purge/retention-purge.job.ts` — a module that walks every Payload collection's `custom.retention.purgeSchedule`, registers a per-collection scheduled job via `IJobQueue`, queries rows whose active-retention period has elapsed, then either pseudonymizes or hard-deletes each row while emitting one `IAuditLog.record(...)` entry per row. Optional `auditLog` is skipped gracefully when `core-audit` is not wired.
|
||||
|
||||
## Why
|
||||
|
||||
Retention without automated purge is a compliance statement with no enforcement. The job makes `custom.retention` actionable: declarations in code become real deletes on schedule.
|
||||
|
||||
## Done when
|
||||
|
||||
- `packages/core-shared/src/payload/retention-purge/retention-purge.job.ts` exists; receives `IJobQueue` + `SanitizedConfig` (+ optional `IAuditLog`) via constructor/factory.
|
||||
- At registration time, one scheduled job is created per collection that declares `custom.retention.purgeSchedule`.
|
||||
- Job body queries by `createdAt` (trigger `from-creation`) or `updatedAt` (trigger `from-last-access`), applies `pseudonymize` (NULL PII fields) or `hard-delete` (Payload cascade delete) per `postDeletion.action`.
|
||||
- Each processed row emits `auditLog.record({ action: "DELETE", subject: row.id, actor: "system", reason: "retention-policy" })`; when `auditLog` is undefined the emission is silently skipped.
|
||||
- Unit tests with an in-memory Payload mock cover: schedule registration per collection, row matching per trigger type, audit emission, pseudonymize vs hard-delete branches, and graceful auditLog skip.
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `packages/core-shared/src/payload/retention-purge/retention-purge.job.ts` + sibling unit test.
|
||||
- Uses existing `IJobQueue` from `core-shared/jobs` and `IAuditLog` from `core-audit` (optional injection).
|
||||
|
||||
## Out of scope
|
||||
|
||||
- App-side boot wiring — the module is the deliverable; consumers integrate it into their `bindAll()`.
|
||||
- `lastAccessedAt` field hook for true "from-last-access" tracking (deferred; see PRD Q2).
|
||||
- Advisory lock for concurrent purge guard (deferred; see PRD Q4).
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `retention-purge.job.ts` + unit tests to `packages/core-shared/src/payload/retention-purge/` — walks `custom.retention.purgeSchedule` per collection, registers scheduled jobs via `IJobQueue`, executes pseudonymize or hard-delete per `postDeletion.action`, emits optional audit entry per row, unit tests cover all branches including graceful auditLog skip — all gates pass on this commit.
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
id: 05-backfill-template-collections
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: Backfill existing template Payload collections with PII and retention metadata
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: auth
|
||||
depends-on:
|
||||
[01-pii-retention-type-primitives, 02-eslint-rule-pii-declaration-complete]
|
||||
blocks: [06-compliance-generator-scripts]
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Add `custom.pii` + `custom.retention` to `auth.users` (full PII tagging), and `custom.retention` to the five remaining template collections (`blog.articles`, `marketing-pages.site-settings`, `marketing-pages.pages`, `media.media`, `navigation.header`), plus `custom.pii` on `media.media.uploadedBy` if the field exists. Each feature's collection file lands as its own commit.
|
||||
|
||||
## Why
|
||||
|
||||
The generators (Story 06) walk Payload configs to produce `compliance/*.yml`. Without backfill, the retention-policy generator warns every collection is missing `purgeSchedule`, and `data-map.yml` has no entries. The backfill also validates that the type primitives from Story 01 compile correctly in real collection files.
|
||||
|
||||
## Done when
|
||||
|
||||
- `auth.users`: `displayName` tagged `{ category: "identification-username", purpose: ["service-delivery"], exportable: true, restrictable: true }`. `custom.retention`: `postDeletion: { duration: "P30D", trigger: "after-deletion", action: "hard-delete" }`, `purgeSchedule: "daily"`. `PAYLOAD_AUTH_PII_DEFAULTS` covers `email`/`password`/`salt`/`hash` automatically — no `custom.authPii` override needed.
|
||||
- `blog.articles`: `custom.retention` with `purgeSchedule` declared.
|
||||
- `marketing-pages.site-settings` + `marketing-pages.pages`: `custom.retention` with `purgeSchedule` declared.
|
||||
- `media.media`: `custom.retention` with `purgeSchedule`; `uploadedBy` tagged `{ category: "identification-username", ... }` if the field exists in the collection.
|
||||
- `navigation.header`: `custom.retention` with `purgeSchedule` declared.
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass after each individual commit.
|
||||
|
||||
## In scope
|
||||
|
||||
- Payload collection config files within: `packages/auth/`, `packages/blog/`, `packages/marketing-pages/`, `packages/media/`, `packages/navigation/`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- PII tags on fields not clearly identified as PII in the PRD (template default is conservative).
|
||||
- Custom `authPii` overrides — not needed unless non-default auth fields are present.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `custom.pii` (`displayName` as `identification-username`) + `custom.retention` (daily purge, 30-day post-deletion hard-delete) to `auth` feature's Payload users collection — `PAYLOAD_AUTH_PII_DEFAULTS` covers email/credentials — all gates pass on this commit.
|
||||
- [ ] Add `custom.retention` to `blog` feature's articles collection — all gates pass on this commit.
|
||||
- [ ] Add `custom.retention` to `marketing-pages` feature's site-settings and pages collections — all gates pass on this commit.
|
||||
- [ ] Add `custom.retention` (and `custom.pii` on `uploadedBy` if the field exists) to `media` feature's media collection — all gates pass on this commit.
|
||||
- [ ] Add `custom.retention` to `navigation` feature's header collection — all gates pass on this commit.
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: 06-compliance-generator-scripts
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: Compliance generator scripts (emit-data-map, emit-retention-policy, emit-sub-processors, emit-all)
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: tooling
|
||||
depends-on: [01-pii-retention-type-primitives, 05-backfill-template-collections]
|
||||
blocks: [07-pre-commit-and-ci-integration, 08-docs-compliance-reference-files]
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Add four ESM scripts under `scripts/compliance/` and wire them as `pnpm compliance:*` package scripts in root `package.json`. Each emitter walks the relevant source (Payload collections or library traces), produces deterministic YAML, supports `--check` (diff against committed file, exit non-zero on mismatch) and `--print` (stdout) modes, and ships with unit tests. The final task commits the initial generated `compliance/*.yml` artifacts.
|
||||
|
||||
## Why
|
||||
|
||||
The generators are the runtime bridge between source declarations (Payload configs, ADR-022 library traces) and audit evidence (`compliance/*.yml`). Without them, the pre-commit hook and CI integration (Story 07) have nothing to invoke, and `compliance/` stays empty.
|
||||
|
||||
## Done when
|
||||
|
||||
- `scripts/compliance/emit-data-map.mjs`: walks Payload collections, applies `PAYLOAD_AUTH_PII_DEFAULTS` + `custom.authPii` overrides, emits deterministic `compliance/data-map.yml`, supports `--check` / `--print`; unit tests cover happy path, `--check` match, `--check` mismatch (readable diff), empty-collections, auth-defaults applied, and `authPii` override applied.
|
||||
- `scripts/compliance/emit-retention-policy.mjs`: walks collections, validates `purgeSchedule` present per collection (exit non-zero + hint if missing), emits `compliance/retention-policy.yml`, supports `--check` / `--print`; unit tests cover required fields validation and diff modes.
|
||||
- `scripts/compliance/emit-sub-processors.mjs`: walks `docs/library-decisions/*.md`, filters `is-sub-processor: true`, merges `compliance/sub-processors.manual.yml` (if present, with `source: manual` flag), emits sorted `compliance/sub-processors.yml`, supports `--check` / `--print`; unit tests cover discriminated-union parsing, absent manual file graceful skip, and merge.
|
||||
- `scripts/compliance/emit-all.mjs`: orchestrates all three in `--check` mode, exits non-zero if any generator fails.
|
||||
- Root `package.json` gains scripts: `compliance:data-map`, `compliance:retention-policy`, `compliance:sub-processors`, `compliance:emit-all`.
|
||||
- Initial `compliance/data-map.yml`, `compliance/retention-policy.yml`, `compliance/sub-processors.yml` generated and committed.
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `scripts/compliance/emit-data-map.mjs` + tests.
|
||||
- `scripts/compliance/emit-retention-policy.mjs` + tests.
|
||||
- `scripts/compliance/emit-sub-processors.mjs` + tests.
|
||||
- `scripts/compliance/emit-all.mjs`.
|
||||
- Root `package.json` script entries.
|
||||
- Initial `compliance/*.yml` files committed.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Pre-commit hook wiring (Story 07).
|
||||
- CI integration (Story 07).
|
||||
- `compliance/sub-processors.manual.yml` — consumer-authored; generator handles its absence gracefully.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `scripts/compliance/emit-data-map.mjs` + unit tests + `compliance:data-map` root package script — walks Payload collections, applies auth PII defaults and `authPii` overrides, deterministic YAML output, `--check` and `--print` modes — all gates pass on this commit.
|
||||
- [ ] Add `scripts/compliance/emit-retention-policy.mjs` + unit tests + `compliance:retention-policy` root package script — validates `purgeSchedule` on every collection, deterministic YAML output, `--check` and `--print` modes — all gates pass on this commit.
|
||||
- [ ] Add `scripts/compliance/emit-sub-processors.mjs` + unit tests + `compliance:sub-processors` root package script — parses `is-sub-processor` discriminated union from library traces, merges manual entries with `source: manual` flag, sorted deterministic YAML output, `--check` and `--print` modes — all gates pass on this commit.
|
||||
- [ ] Add `scripts/compliance/emit-all.mjs` orchestrator + `compliance:emit-all` root package script, run `pnpm compliance:emit-all` to produce and commit initial `compliance/data-map.yml`, `compliance/retention-policy.yml`, and `compliance/sub-processors.yml` — all gates pass on this commit.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: 07-pre-commit-and-ci-integration
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: Pre-commit hook and CI integration for compliance drift detection
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: tooling
|
||||
depends-on: [06-compliance-generator-scripts]
|
||||
blocks: []
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Wire `pnpm compliance:emit-all` into the pre-commit hook (conditional — only when staged files are Payload configs or library traces) and add `pnpm compliance:emit-all --check` as a hard-fail step in the CI validate job, positioned after `pnpm conformance` and before `pnpm coverage:diff`.
|
||||
|
||||
## Why
|
||||
|
||||
The generators alone don't prevent drift — a developer could edit a Payload config and never regenerate. The pre-commit hook auto-regenerates and auto-stages `compliance/*.yml`; CI catches any slip-through on the PR. Together they form the E3 and E5 latency layers for compliance drift.
|
||||
|
||||
## Done when
|
||||
|
||||
- `.husky/pre-commit` gains a conditional step that: checks whether any staged file matches `packages/*/src/integrations/cms/**/*.ts`, `docs/library-decisions/*.md`, or `compliance/*.yml`; if so, runs `pnpm compliance:emit-all` and `git add compliance/`. Non-matching commits incur only the ~10ms detection cost.
|
||||
- `.github/workflows/ci.yml` validate job gains a `Compliance manifest drift check` step running `pnpm compliance:emit-all --check`, positioned after `pnpm conformance`. CI failure message includes the fix command (`pnpm compliance:emit-all`).
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `.husky/pre-commit` — conditional compliance regeneration step.
|
||||
- `.github/workflows/ci.yml` — validate job `compliance:emit-all --check` step.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Generator scripts themselves (Story 06).
|
||||
- The `--no-verify` bypass — repo policy already prohibits it; CI re-checks provide the safety net.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add conditional `pnpm compliance:emit-all` step to `.husky/pre-commit` (staged-file pattern guard matching Payload configs, library traces, and `compliance/*.yml`; auto-stages generated files via `git add compliance/`) and add `pnpm compliance:emit-all --check` hard-fail step to `.github/workflows/ci.yml` validate job with failure message pointing to the fix command — all gates pass on this commit.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
id: 08-docs-compliance-reference-files
|
||||
epic: compliance-manifests-pii-retention-subprocessors
|
||||
title: docs/compliance reference example files and README
|
||||
type: technical-story
|
||||
status: todo
|
||||
feature: docs
|
||||
depends-on: [06-compliance-generator-scripts]
|
||||
blocks: []
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Add `docs/compliance/data-map.example.yml`, `docs/compliance/retention-policy.example.yml`, `docs/compliance/sub-processors.example.yml`, and `docs/compliance/README.md` explaining the `docs/compliance/` (templates / examples) vs root `compliance/` (live generated artifacts) split and how to operate the generators.
|
||||
|
||||
## Why
|
||||
|
||||
Without documentation, a downstream consumer editing `compliance/*.yml` manually won't understand which files are generated vs hand-authored, what fields each entry requires, or how to run the generators. The `docs/compliance/` folder becomes the canonical onboarding reference for the compliance module.
|
||||
|
||||
## Done when
|
||||
|
||||
- `docs/compliance/data-map.example.yml` shows a complete data-map entry with every field (`category`, `purpose`, `exportable`, `restrictable`, optional `retention`) populated and annotated.
|
||||
- `docs/compliance/retention-policy.example.yml` shows a complete retention-policy entry (`activeRetention`, `postDeletion`, `purgeSchedule`, optional `coldArchive`).
|
||||
- `docs/compliance/sub-processors.example.yml` shows both a trace-backed entry (`is-sub-processor: true` with all conditional fields) and a `source: manual` hand-authored entry.
|
||||
- `docs/compliance/README.md` explains: what each YAML file contains, how they are generated, the `docs/compliance/` (examples) vs `compliance/` (live) split, when and how to author `compliance/sub-processors.manual.yml`, and how to run `pnpm compliance:emit-all`.
|
||||
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
|
||||
|
||||
## In scope
|
||||
|
||||
- `docs/compliance/data-map.example.yml`
|
||||
- `docs/compliance/retention-policy.example.yml`
|
||||
- `docs/compliance/sub-processors.example.yml`
|
||||
- `docs/compliance/README.md`
|
||||
|
||||
## Out of scope
|
||||
|
||||
- `compliance/sub-processors.manual.yml` — consumer-authored artifact; not shipped by the template.
|
||||
- Runbooks, privacy policies, pre-launch checklist — Epic D territory.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Add `docs/compliance/data-map.example.yml`, `docs/compliance/retention-policy.example.yml`, `docs/compliance/sub-processors.example.yml`, and `docs/compliance/README.md` explaining the docs/compliance (templates) vs compliance/ (live artifacts) split, generator usage, and manual sub-processor entry authoring — all gates pass on this commit.
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
id: compliance-manifests-pii-retention-subprocessors
|
||||
prd: docs/work/prds/compliance-manifests-pii-retention-subprocessors.prd.md
|
||||
title: Declarative compliance manifests (PII + retention + sub-processors) — Epic A of ADR-025
|
||||
type: epic
|
||||
status: in-progress
|
||||
features:
|
||||
[core-shared, core-eslint, auth, blog, media, marketing-pages, navigation]
|
||||
created: 2026-05-18T17:52:09Z
|
||||
updated: 2026-05-18T18:06:15.725Z
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Ship the declarative compliance manifests + generators so downstream consumers get a complete, automatically-validated PII inventory, retention policy, and sub-processor record by editing source-of-truth Payload configs and ADR-022 library traces. Drift detection runs in pre-commit + CI; the consumer's `compliance/` directory becomes audit evidence.
|
||||
|
||||
## Stories
|
||||
|
||||
- [ ] [01 — PII and retention type primitives in core-shared](01-pii-retention-type-primitives/_story.md)
|
||||
- [ ] [02 — ESLint rule pii-declaration-must-be-complete](02-eslint-rule-pii-declaration-complete/_story.md)
|
||||
- [ ] [03 — ADR-022 amendment and evaluate-library skill update](03-adr-022-amendment-and-evaluate-library-skill/_story.md)
|
||||
- [ ] [04 — Background retention purge job in core-shared](04-retention-purge-job/_story.md)
|
||||
- [ ] [05 — Backfill existing template collections](05-backfill-template-collections/_story.md)
|
||||
- [ ] [06 — Compliance generator scripts](06-compliance-generator-scripts/_story.md)
|
||||
- [ ] [07 — Pre-commit hook and CI integration](07-pre-commit-and-ci-integration/_story.md)
|
||||
- [ ] [08 — docs/compliance reference files and README](08-docs-compliance-reference-files/_story.md)
|
||||
Reference in New Issue
Block a user