docs(tooling): add sub-processor discriminated union to ADR-022 and traces

Amends ADR-022 §9 with the `is-sub-processor` / `processes-pii` discriminated
union spec, including the five conditional fields required when a library is a
true GDPR sub-processor. Updates the evaluate-library skill to prompt for these
fields during every trace authoring pass and adds the updated frontmatter
template. Backfills all nine existing library-decision traces with the new
fields; payload gets `processes-pii: true` (self-hosted CMS that stores user
data); all pure in-process libraries get `false / false`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 18:44:09 +00:00
parent 8486037f20
commit 98d96d2e19
12 changed files with 176 additions and 1 deletions

View File

@@ -196,6 +196,52 @@ Every existing runtime dependency in feature- and core-tier packages
ADR-002, ADR-014, ADR-017 are cited via the `adr:` frontmatter field;
verification-command output is captured at backfill time.
### 9. Sub-processor discriminated union (amendment: 2026-05-18)
Every trace carries two top-level frontmatter fields classifying the library
from a GDPR sub-processor perspective:
```yaml
is-sub-processor: false # boolean — true when the vendor receives personal data on the operator's behalf
processes-pii: false # boolean — true when the library processes PII in-process (even without transmitting it)
```
When `is-sub-processor: true`, five additional fields are **required**:
```yaml
data-sent: "<what personal data the library transmits to the vendor>"
region: "<vendor data region, e.g. eu-west-1>"
dpa-signed: true | false
sccs-required: true | false
contact: "<vendor DPO or privacy contact email/URL>"
```
**Discriminated-union rules:**
| `is-sub-processor` | `processes-pii` | Conditional fields required? |
| ------------------ | --------------- | --------------------------------------------------------------------------------- |
| `false` | `false` | No pure library, no data involvement |
| `false` | `true` | No in-process only, no vendor data flow |
| `true` | `true` | Yes all five conditional fields required |
| `true` | `false` | Technically possible but very unusual; still requires all five conditional fields |
**Baseline for backfill:** pure in-process libraries (no network calls to
vendor-controlled endpoints) get `is-sub-processor: false` + `processes-pii: false`.
Self-hosted software that stores PII but transmits nothing to the vendor (e.g.
`payload`) gets `is-sub-processor: false` + `processes-pii: true`.
These fields are the machine surface consumed by `scripts/emit-sub-processors.mjs`
(see Story 06 of the compliance-manifests-pii-retention-subprocessors epic). A
trace missing `is-sub-processor` is treated as `false` by the generator for
backward-compatibility; all new traces authored after this amendment must include
both fields. The `evaluate-library` skill 7) prompts for these fields
unconditionally and writes the conditional block only when `is-sub-processor: true`.
The weekly `dpa-signed` staleness check in CI (ADR-023 cross-reference) should
flag any `dpa-signed: true` traces where the DPA has not been revalidated within
the prior 365 days. Implementation of that cron is deferred to the CI security
hardening work.
## Alternatives considered
- **No policy, keep relying on instinct.** Rejected. The 2026-05-14 OpenAPI

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: adr-002
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: true
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: adr-002
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: Apache-2.0
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -6,6 +6,9 @@ decision: approved
date: 2026-05-14
deciders: [Danijel Martinek]
adr: null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
filter-results:
license: MIT
types: native

View File

@@ -7,6 +7,14 @@ date: <YYYY-MM-DD>
deciders: [<author>, ...]
adr: adr-NNN | null
lastRevalidated: null
is-sub-processor: false
processes-pii: false
# include the block below only when is-sub-processor: true
# data-sent: "<description>"
# region: "<eu | eu-west-1 | ...>"
# dpa-signed: false
# sccs-required: false
# contact: "<url or email>"
filter-results:
license: <SPDX id>
types: native | "@types/<x>" | none