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>
142 lines
5.0 KiB
Markdown
142 lines
5.0 KiB
Markdown
---
|
|
package: <name>
|
|
version: "<semver range>"
|
|
tier: app | feature | core
|
|
decision: approved | rejected
|
|
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
|
|
maintenance: active | dormant | abandoned
|
|
boundary-fit: pass | fail
|
|
shadow-check: pass | fail | "shadows <x>"
|
|
eu-residency: ok | n/a | self-hostable | fail
|
|
cve-scan: clean | "<advisory-id>" | fail
|
|
named-consumer: pass | fail
|
|
socketRisk: clean | flagged | <arbitrary-string>
|
|
verification-commands:
|
|
- <literal command that produced each filter result>
|
|
accepted-cves: []
|
|
---
|
|
|
|
## Filter: license
|
|
|
|
<!-- Result: <SPDX id> -->
|
|
|
|
Allowed licences: MIT, Apache-2.0, BSD-\*, ISC, MPL-2.0. Record the SPDX
|
|
identifier from `package.json` or `npx license-checker`. Anything outside the
|
|
allowlist is an automatic reject.
|
|
|
|
## Filter: types
|
|
|
|
<!-- Result: native | @types/<x> | none -->
|
|
|
|
Confirm TypeScript types are available (`native` = ships its own `.d.ts`;
|
|
`@types/<x>` = community types package exists; `none` = no types → auto-reject).
|
|
|
|
## Filter: maintenance
|
|
|
|
<!-- Result: active | dormant | abandoned -->
|
|
|
|
Check last release date and recent PR/issue activity. `active` = last release
|
|
< 18 months AND activity < 12 months. `dormant` = stable but not actively
|
|
developed (acceptable for finished libraries). `abandoned` = auto-reject.
|
|
|
|
## Filter: boundary-fit
|
|
|
|
<!-- Result: pass | fail -->
|
|
|
|
Confirm the dependency does not violate ESLint boundary-tag rules for the
|
|
target tier (ADR-006, ADR-010, ADR-017). E.g., a Sentry SDK added to a feature
|
|
package is an auto-reject because ADR-017 §4 reserves vendor SDKs for core.
|
|
|
|
## Filter: shadow-check
|
|
|
|
<!-- Result: pass | fail | "shadows <x>" -->
|
|
|
|
Check whether this library duplicates a must-have already locked in the
|
|
workspace (e.g., proposing `valibot` when `zod` is locked, `tsyringe` when
|
|
Inversify is locked by ADR-002). A parallel adoption is `shadows <x>` and an
|
|
auto-reject; a replacement requires a dedicated ADR.
|
|
|
|
## Filter: eu-residency
|
|
|
|
<!-- Result: ok | n/a | self-hostable | fail -->
|
|
|
|
If the library transmits user data, telemetry, or business state to a
|
|
vendor-controlled endpoint by default, the vendor must offer an EU data region.
|
|
Self-hostable packages and build-time-only tools are `n/a`.
|
|
|
|
## Filter: cve-scan
|
|
|
|
<!-- Result: clean | "<advisory-id>" | fail -->
|
|
|
|
Run `pnpm audit --audit-level=moderate`. `clean` = no advisories at adoption
|
|
time. Record any accepted advisory IDs in the `accepted-cves` frontmatter field
|
|
and explain the risk acceptance here.
|
|
|
|
## Filter: named-consumer
|
|
|
|
<!-- Result: pass | fail -->
|
|
|
|
Answer: "Who calls this code path today, or who is blocked waiting for it?"
|
|
Hypothetical future callers are not consumers. This filter is the direct
|
|
response to the 2026-05-14 OpenAPI near-miss (ADR-022 §Context).
|
|
|
|
## Filter: socketRisk
|
|
|
|
<!-- Result: clean | flagged | <arbitrary-string> -->
|
|
|
|
Run `socket npm:report <package>` (or check socket.dev) for supply-chain
|
|
risk signals. `clean` = no issues detected. `flagged` = one or more high- or
|
|
critical-severity signals (requires explicit risk-acceptance note here before
|
|
approval). An arbitrary string records the specific risk label returned by the
|
|
Socket CLI (e.g. `"obfuscated-code"`, `"install-script"`). The `lastRevalidated`
|
|
frontmatter field is set to the ISO date of the most recent re-run.
|
|
|
|
## Field: lastRevalidated
|
|
|
|
<!-- Value: YYYY-MM-DD | null -->
|
|
|
|
ISO 8601 date of the last time the Socket supply-chain scan (and any other
|
|
time-sensitive filter) was re-run against the current installed version.
|
|
`null` = never revalidated since initial adoption (acceptable for fresh traces).
|
|
Updated automatically by the weekly revalidation cron (Story 05).
|
|
|
|
## Prompt: replaces
|
|
|
|
<!-- Required: answer in either direction with justification -->
|
|
|
|
What existing library or approach does this replace? New-and-old running in
|
|
parallel is a smell — name the thing being retired and its retirement plan, or
|
|
explain why parallel adoption is intentional and time-bounded.
|
|
|
|
## Prompt: migration-cost-out
|
|
|
|
<!-- Required: mechanical | hard | impossible + justification -->
|
|
|
|
What does ripping this back out look like 18 months from now? Is the removal
|
|
mechanical (swap one package, update call sites), hard (scattered integration
|
|
points, data format dependencies), or impossible (vendor lock-in, protocol
|
|
coupling)? Higher migration cost raises the bar for adoption.
|
|
|
|
## Prompt: alternatives-considered
|
|
|
|
<!-- Required: minimum two named alternatives, or "none with explanation" -->
|
|
|
|
Name at least two alternatives evaluated before choosing this library. For
|
|
`core`-tier adoptions, this section is also duplicated into the companion ADR.
|
|
If no alternatives exist, explain why (e.g., the library is the de-facto
|
|
standard with no viable substitutes).
|