# Glossary

Canonical vocabulary for `template-vertical`. Shared by humans and AI agents — every term means **the same thing** here. Terms specific to this repo's domain (monorepo / Clean Architecture / agent-first workflow / conformance). General programming concepts (DI, retries, errors, etc.) don't belong unless they have a project-specific meaning.

**Rules:**

- One sentence per definition. Define what it **is**, not what it does.
- Pick one canonical term; list aliases under `_Avoid:_`.
- Relationships expressed with bold term names + cardinality.
- Flag ambiguities under "Flagged ambiguities" with a resolution.
- Reference ADRs by ID (`ADR-NNN`); reference paths sparingly (they rot fast).

---

## Packages

**Package**:
A workspace member under `packages/` or `apps/` with its own `package.json` and tag. The atomic unit of dependency, build, and boundary enforcement.
_Avoid:_ module, library, app (unless specifically `apps/`).

**Tag**:
The boundary classification on a package (`app`, `core`, `core-composition`, `feature`, `tooling`). Enforced by ESLint (`eslint-plugin-boundaries`) and Turborepo `boundaries`. See `AGENTS.md` → Boundary Rules.

**Feature** (a.k.a. **feature package**):
A vertical slice owning its Clean Architecture layers + integrations under `packages/<name>/`. Currently: `auth`, `blog`, `media`, `marketing-pages`, `navigation`. **In architecture-refactor conversations (the `improve-codebase-architecture` skill), "module" defaults to "feature" — they're the same unit at the highest level of granularity.**
_Avoid:_ domain, vertical (use "feature" or "vertical feature"). "Module" is acceptable inside the refactor skill specifically, where it abstractly covers "anything with interface + implementation" at any scale (use case, controller, repository port, or full feature).

**Must-have core**:
A core package the template can't run without — `core-shared`, `core-cms`, `core-api`.
_Avoid:_ baseline core, base core.

**Optional core**:
A core package scaffolded on demand via `pnpm turbo gen core-package <name>` — `core-realtime`, `core-events`, `core-trpc`, `core-ui`, `core-audit`. See `docs/architecture/template-tiers.md`.

**Core-composition**:
A tag for packages that compose feature exports — `core-api`, `core-cms`, `core-trpc`. The only packages allowed to import from `@repo/<feature>/api` or `@repo/<feature>/cms` subpaths.

**Tooling package**:
A package providing build/lint/test infrastructure — `core-eslint`, `core-typescript`, `core-testing`. May only depend on other tooling.

**App**:
A runtime entry point under `apps/` — `web-next`, `web-tanstack`, `cms`, `storybook`.

## Clean Architecture layers (per feature)

**Entities layer** (`packages/<feature>/src/entities/`):
Domain models (`models/<x>.ts`) and domain errors (`errors/<domain>.ts` + `errors/common.ts`). No I/O.

**Application layer** (`packages/<feature>/src/application/`):
**Use cases**. Pure orchestration over repository + service ports.

**Infrastructure layer** (`packages/<feature>/src/infrastructure/`):
**Repository** and **service** implementations (real Payload-backed + mock).

**Interface-adapters layer** (`packages/<feature>/src/interface-adapters/`):
**Controllers** — one per use case. Translate `unknown` input → use-case input via Zod `safeParse`; thread the output through a `presenter`.

**Integrations layer** (`packages/<feature>/src/integrations/`):
Vendor-specific glue — `integrations/api/` (tRPC routers), `integrations/cms/` (Payload collections + tasks).

**DI folder** (`packages/<feature>/src/di/`):
**Container**, **symbols**, and the two **binders**. The wiring layer.

## Feature building blocks

**Use case**:
A single business action expressed as a factory: `(deps) => async (input) => output`. Always paired with a Zod `xInputSchema` + (non-void) `xOutputSchema` co-located in the same file. Exports the type alias `I*UseCase = ReturnType<typeof xUseCase>`.
_Avoid:_ command, action, service method.

**Controller**:
The thin adapter from `unknown` input to a use case. One per use case. Co-located top-level `function presenter` for non-void outputs.
_Avoid:_ multi-method controller (forbidden — one verb-noun per file).

**Repository**:
A port for collection-style entity access. Lives in `infrastructure/<x>.repository.{ts,mock.ts,interface.ts}`. Real impls drop the `payload-` prefix; mocks use the `.mock.ts` suffix.

**Service**:
A port for non-collection capabilities (auth, mailer, etc.). Same `.ts` / `.mock.ts` / `.interface.ts` triad as repositories.

**Manifest** (`feature.manifest.ts`):
The per-feature contract declaring `useCases`, `audits`, `publishes`, `consumes`, `requiredCores`, and (when applicable) `requiresConsent: ConsentCategory[]`. Source of truth for the conformance system. Always edited **before** code (manifest-first ordering).

**Symbol**:
A DI token in `packages/<feature>/src/di/symbols.ts`. Used by Inversify to identify a binding.

**Binder**:
A function that registers DI bindings — `bindProductionX(ctx)` (real Payload) or `bindDevSeedX(ctx)` (populated mock). Lives at `src/di/bind-production.ts` and `src/di/bind-dev-seed.ts`. Self-asserts conformance at its tail via `assertFeatureConformance(...)`.

**`bindAll()`**:
The app-level DI dispatcher (e.g. `apps/web-next/src/server/bind-production.ts`). Picks each feature's binder by env (`USE_DEV_SEED`, `NODE_ENV`) and threads a single shared `ctx` through them. Idempotent.

**`ctx`** (a.k.a. **bind context**):
The object passed to every binder. Required fields: `tracer`, `logger`, plus `config` for production. Optional fields: `bus`, `queue`, `realtime`, `realtimeRegistry` (only when the corresponding optional cores are scaffolded).

**Dev-seed**:
The populated in-memory mock mode. Lives in `src/__seeds__/dev.ts` per feature, exported as a lazy `buildDev<Entities>()` function. Selected by `USE_DEV_SEED=true` or by default when not in production.

**Public surface**:
A feature's allowed import surface — `.` (contracts: types, errors, schemas, `I*UseCase` aliases, router type), `./ui` (queries, components), `./cms`, `./api`, `./di/bind-production`, `./di/bind-dev-seed`. No deep source paths exist in `exports` maps.

**Anchor**:
A `// <gen:*>` comment marking where a generator injects code (e.g. `<gen:events>`, `<gen:job-symbols>`, `<gen:realtime-handlers>`). A CI guard at `packages/core-eslint/anchors.test.js` keeps them present.

## Architecture refactor vocabulary

Terms used by the `improve-codebase-architecture` skill (`.claude/skills/improve-codebase-architecture/`) when proposing refactors. Distinct from the everyday domain terms above — these are abstractions for reasoning about shape. Both vocabularies are in scope during refactor conversations.

**Module** (refactor sense, **= feature by default**):
The abstract unit a refactor operates on: anything with an interface + implementation. In this repo, **"module" almost always means "feature"** (`packages/<name>/`) since that's our primary unit of organization. At narrower scales it also covers a use case, controller, repository/service port, or binder. Don't introduce "module" as a competing top-level term in domain conversations — the refactor skill is the only place this abstraction is appropriate.
_Avoid:_ using "module" outside the refactor skill (say "feature", "use case", "controller", "package" as appropriate).

**Interface** (refactor sense):
Everything a caller must know to use a module — type signatures, invariants, ordering, error modes, Zod schemas, manifest declarations, DI symbol contract. Strictly broader than the TS `interface` keyword.

**Implementation**:
What's inside a module. Distinct from **adapter**: an adapter is a _role_ (fills a slot at a seam); an implementation is the _substance_ (the code itself).

**Depth**:
Leverage at the interface — behaviour per unit of interface a caller must learn. A **deep module** packs a lot of behaviour behind a small interface; a **shallow module** has an interface nearly as complex as its body. Pure factory-function use cases are usually deep; one-line wrappers and `(x) => x` presenters are usually shallow.

**Seam** _(from Michael Feathers)_:
A place where behaviour can be altered without editing in place — the _location_ of a module's interface. Concrete seams in this repo: `*.interface.ts` files, DI symbols (`*_SYMBOLS.IX*`), `feature.manifest.ts` entries, `// <gen:*>` anchors, the protocol types in `core-shared/di/bind-protocols.ts`.
_Avoid:_ "boundary" — that term is reserved in this repo for ESLint workspace-tag rules (`feature` may depend on `core` + `tooling` only).

**Adapter**:
A concrete thing satisfying an interface at a seam. In this repo a typical port has two or three adapters: real (`<x>.repository.ts`), mock (`<x>.repository.mock.ts`), and sometimes recording (`Recording*` test doubles in `core-testing`).

**Leverage**:
What callers get from depth — more capability per unit of interface they must learn.

**Locality**:
What maintainers get from depth — change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers.

**Deletion test**:
Imagine deleting a module: if complexity vanishes, it was a pass-through; if complexity reappears across N callers, it was earning its keep. The signal for "this module is shallow" is when deletion _just moves_ the complexity rather than reducing it.

**Deepening**:
A refactor that turns shallow modules into deeper ones — merging pass-throughs into the modules that justified them, exposing a smaller interface, or relocating the seam to a more useful place. Subject to the hard constraints in the skill's `SKILL.md` (no ADR violations, no boundary breaks, no manifest drift).

## Conformance system

**Conformance**:
The 5-gate enforcement chain that keeps a feature's manifest and code in sync. Layers:

1. **TypeScript brands** (0s) — `Instrumented`, `Captured`, `Audited` on every wired use case / controller.
2. **ESLint conformance rules** (<1s) — five custom rules in `core-eslint`.
3. **Boot assertion** (~3s) — `assertFeatureConformance(...)` at the tail of every binder.
4. **CI drift gate** (`pnpm conformance`, ~120s) — cross-feature event closure.
5. **Fallow** (`pnpm fallow`, ~30–60s) — whole-codebase dead exports / dupes / complexity / AI-change audit.

**Brand**:
A TypeScript phantom type attached to a wired use case / controller — `Instrumented` (after `withSpan`), `Captured` (after `withCapture`), `Audited` (after `withAudit`). Enforces the wrapper composition at bind time.

**Manifest-first ordering**:
The non-negotiable authoring order for any new use case: **(1) manifest entry → (2) contracts (`xInputSchema`, `xOutputSchema`, `IXUseCase`) → (3) tests (red) → (4) implementation (green)**. The generator scaffolds (1)+(2)+test stubs so new features are conformance-compliant by default.

**Fallow**:
The whole-codebase auditor (`pnpm fallow`) — dead exports, unused files, duplicate code, circular deps, complexity hotspots, AI-change audit drift. The fifth conformance gate. Run `pnpm fallow:audit` before commits.

**Drift**:
Any disagreement between a feature's manifest and its code. The conformance gates are designed to catch drift at the earliest possible latency.

## Coverage

**Coverage band**:
The per-path threshold declared in `feature.manifest.ts` under `coverage.bands` — one entry per Clean Architecture layer (`entities`, `use-cases`, `controllers`) plus a `baseline` for everything else. Single source of truth read by vitest, `assertFeatureConformance`, and `pnpm coverage:diff`. See ADR-020.

**L0 / L1 / L2 / L3**:
The four coverage layers (ADR-020). **L0** = vitest per-layer thresholds (test-time). **L1** = `pnpm coverage:diff` cover-the-diff gate (post-test, CI + dispatch loop). **L2** = `pnpm coverage:aggregate` → committed `coverage/summary.json` (observability). **L3** = `pnpm mutate` Stryker mutation testing on entities + use-cases (on-demand, not default).

**Diff coverage**:
The gate that asserts every changed _executable_ line has execution count > 0 in the merged lcov. Cover-the-diff (modified + new lines both count), not cover-the-new-code. Run via `pnpm coverage:diff [<base-ref>]`.
_Avoid:_ patch coverage, delta coverage (use "diff coverage" canonically).

**Mutation testing**:
A test-quality signal that mutates source code and re-runs tests; surviving mutants mean the test exists + executes the code but doesn't actually assert behavior. Scoped to `entities/` + `application/use-cases/` per feature. Run via `pnpm mutate [--filter @repo/<feature>]`.

**Mutation score**:
The percentage of mutants killed (i.e., caught by tests) out of all mutants generated. Per-feature threshold defaults to 80% (overridable in `feature.manifest.ts` via `coverage.mutationThreshold`).

**`coverage/summary.json`**:
The aggregated per-package + repo-level coverage snapshot, committed on merge to main. Grep-able from git history via `git log -- coverage/summary.json`. Includes timestamp + commit SHA for correlation with deploys.

## Releasing

**Conventional Commits**:
The commit-message spec mandated by this template — `<type>(<scope>): <imperative subject>`. Types: `feat | fix | docs | style | refactor | test | chore | perf | ci | build | revert`. `!` for breaking changes. See CLAUDE.md Key Conventions.

**release-please**:
The Google-maintained automation that reads Conventional Commits, derives semver bumps, and opens a rolling release PR with version bumps + per-package CHANGELOG entries on every push to main. Configured in `release-please-config.json` + `.release-please-manifest.json`. ADR-021.

**Hybrid versioning**:
The template's versioning strategy (ADR-021) — root template (`template-vertical`) + 5 feature packages (`@repo/{auth,blog,media,marketing-pages,navigation}`) version independently from `0.1.0`. Core packages, tooling, and apps are NOT versioned (cascade-effect would invalidate the signal).

**Tag prefix**:
The per-package prefix release-please uses to avoid tag collisions in a monorepo — `template-v0.1.0` for the root, `auth-v0.1.0` / `blog-v0.1.0` / etc. for features.

**Rolling release PR**:
The single PR release-please keeps open on `main` and updates idempotently on every push. Contains all pending version bumps + changelog entries since the last release. Merging it cuts the tags + GitHub releases.

**Bump targeting (by commit-path)**:
How release-please decides which tracked package(s) a commit bumps — by the **files changed**, not the conventional-commit `(scope)`. A commit touching `packages/auth/**` bumps `@repo/auth`; a commit touching `docs/**` or `scripts/**` bumps the root template; a commit touching both bumps both.

**Pre-1.0 bump policy**:
While each tracked package is `<1.0.0`: `feat:` bumps patch, `feat!:` bumps minor (NOT major). Configured via `bump-patch-for-minor-pre-major: true`. Once a package crosses 1.0.0, standard semver kicks in.

**`Release-As:` trailer**:
A commit-body trailer (`Release-As: 0.5.0`) that overrides release-please's auto-derived bump for the package(s) whose paths the commit touches. Used for manual semver corrections or explicitly crossing 1.0.0.

**CHANGELOG.md**:
A per-package, release-please-managed changelog (one at repo root for the template; one at `packages/<feature>/CHANGELOG.md` for each feature). Do not edit manually — release-please regenerates from commit history.

**SBOM** (Software Bill of Materials):
A machine-readable inventory of all direct and transitive package dependencies attached as a JSON file to each GitHub release. Generated in CycloneDX JSON format via `@cyclonedx/cyclonedx-npm` in the `release-please.yml` CI workflow (runs only when a release is actually cut). Named `sbom-<tag>.cdx.json` and uploaded as a GitHub release asset. Enables downstream supply-chain scanning and NTIA minimum-elements compliance. Not committed to the repository.
_Avoid:_ confusing SBOM (a release asset produced by CI) with library traces (developer-authored, per-decision records in `docs/library-decisions/`).

## Cross-feature mechanisms

**Event bus** (`IEventBus`):
The vendor-neutral cross-feature pub/sub interface in `@repo/core-events`. Two implementations: `InMemoryEventBus` (dev/test, synchronous) and `PayloadJobsEventBus` (production, durable via Payload tasks). Selected by `bindAll()`. See ADR-015.
_Use when:_ feature A's success must trigger feature B's reaction. **Don't use for in-feature flow control** — that's a direct use-case call (rule E0).

**Event descriptor**:
A `defineEvent(...)` declaration with a `name` (wire format) + Zod payload schema. Lives at `packages/<feature>/src/events/<event>.event.ts`. Publishers re-export from the feature root; consumers do **not**.

**Event handler**:
A consumer's reaction to a published event. Lives at `packages/<feature>/src/events/handlers/on-<publisher>-<event>.handler.ts`. **Always private** — never re-exported (rule E1, enforced by `no-handler-reexport`).

**Job queue** (`IJobQueue`):
The vendor-neutral deferred-work interface in `@repo/core-shared/jobs/`. Two implementations: `InMemoryJobQueue` (dev/test, `setImmediate`) and `PayloadJobQueue` (production). Feature packages enqueue via `IJobQueue` only — direct `payload.jobs.queue()` is ESLint-blocked (rule J0).

**Realtime channel descriptor**:
A `defineRealtimeChannel(...)` declaration in `packages/<feature>/src/realtime/<channel>.channel.ts`. Re-exported from the feature root. Carries a Zod payload schema + a **scope**.

**Channel scope**:
A channel's subscription rule — `public` | `authenticated` | `role:<name>` | `user-scoped`. See ADR-016.

**Broadcaster** (`IRealtimeBroadcaster`):
The server-side push interface in `@repo/core-realtime`. Use cases call `broadcaster.broadcast(channel, payload)` after the success path.

**Realtime handler**:
A consumer's reaction to an inbound client message on a channel. Lives at `packages/<feature>/src/realtime/handlers/*.handler.ts`. **Always private** — never re-exported (rule R1, enforced by `no-realtime-handler-reexport`).

**Audit log**:
A DPA-compliant record of a use case's side effects. Emitted via `auditLog.record(...)`; declared in the manifest's `audits:` array. See ADR-018.

## Instrumentation

**Tracer** (`ITracer`):
The span interface in `@repo/core-shared/instrumentation/`. Three impls: `NoopTracer`, `OtelTracer`, `RecordingTracer` (test-only, from `core-testing`).

**Logger** (`ILogger`):
The capture interface. Same three-impl shape as `ITracer`. Used for exception reporting and structured logs.

**Metrics** (`IMetrics`):
The counter/gauge/histogram interface. Same three-impl shape.

**Analytics** (`IAnalytics`):
The product-analytics interface, lives in `@repo/core-analytics` (optional core, scaffolded via `pnpm turbo gen core-package analytics`). Three methods: `track(event, properties?, user?)`, `identify(user)`, `pageView(path, properties?)`. Same three-impl shape as `ITracer`/`ILogger`/`IMetrics`. Used for funnel/cohort/retention analysis; structurally distinct from `IAuditLog` (which is compliance-driven) and from `IEventBus` (which is cross-feature action routing). Server-only by manifest gate; consumer wires React provider for client-side via `@repo/core-analytics/react`.
_Avoid:_ confusing analytics events with cross-feature events (bus) or audit events (compliance) — they're three orthogonal capture channels.

**`withSpan`** / **`withCapture`** / **`withAudit`** / **`withAnalytics`** / **`withConsent`** / **`withRateLimit`**:
The six wrapper composers applied at DI bind time. Composition is nested with `withSpan` outermost; each layer attaches a brand: `withSpan` → `Instrumented`, `withCapture` → `Captured`, `withAudit` → `Audited` (when manifest declares `audits`), `withAnalytics` → `Analyzed` (when manifest declares `analyticsEvents`), `withConsent` → `ConsentChecked` (when manifest declares `requiresConsent`), `withRateLimit` → `RateLimited` (when manifest declares `rateLimit`). See ADR-025 for the compliance-baseline channels.

**SubjectLink**:
A field-level declaration in a Payload collection's `custom.subject` array that maps a relationship field to a data subject. Carries `field` (Payload field name), `kind` (`"self"` | `"owner"` | `"reference"`), optional `target` (auth-collection slug), and optional `role` (semantic label). The DSR cascade walks these at runtime to determine which rows to include in Art. 15 exports and which rows to erase or redact on Art. 17 requests. See `docs/compliance/subject-linkage.example.md`.
_Avoid:_ confusing `kind: "self"` (the subject's own account row) with `kind: "owner"` (rows the subject authored/owns) — both are treated as owned data for DSR purposes, but `"self"` targets the auth-collection record itself.

**DeletionCertificate**:
The immutable proof-of-erasure record returned by `IDataDelete.deleteSubjectData(subjectId, mode)`. Carries `subjectId` (or `"erased-{hash}"` after the ID itself is purged), `mode` (`"soft"` | `"cascade-hard"`), `timestamp` (ISO 8601), `reason`, `affected` (per-collection summary of `collection`, `rowsAffected`, `action`, and `fields` NULLed), and `auditEntryId` linking to the immutable audit log entry. GDPR Art. 17 compliance artifact — store permanently, never mutate. See `docs/guides/dsr.md`.
_Avoid:_ generating a `DeletionCertificate` manually — it is emitted only by the production `IDataDelete` implementation to ensure correctness.

**DSR** (`@repo/core-dsr`):
The Data Subject Rights handler — optional core package providing four interfaces that operate on user data in response to GDPR Arts. 15–18 requests. `IDataExport` (Art. 15 access + Art. 20 portability), `IDataDelete` (Art. 17 erasure cascade), `IDataRectify` (Art. 16), `IProcessingRestriction` (Art. 18). Sibling to `core-audit` — audit _records_ access, DSR _acts_ on the underlying data. Walks Payload collections at runtime using field-level `custom.pii` tags. See ADR-025.
_Avoid:_ confusing DSR with audit; audit is the immutable journal, DSR is the mutator.

**Consent** (`@repo/core-consent`):
The runtime gate for granular consent categories (essential/functional/analytics/marketing). Optional core package providing `IConsent` interface (`isGranted`/`grant`/`withdraw`/`getCategories`) + `ConsentChecked` brand + `requiresConsent: [...]` manifest field + `no-undeclared-consent-check` ESLint rule. Cookie banner UI ships as atomic component in `core-ui`. See ADR-025.

**UserConsentState**:
A per-category consent record returned by `IConsent.getCategories()`. Carries `category` (`ConsentCategory`), `state` (`"granted"` | `"denied"` | `"pending"`), optional `grantedAt` and `withdrawnAt` ISO 8601 timestamps, `bannerVersion`, `policyVersion`, and `method` (how the category was consented — e.g., `"banner-accept"`, `"signup-migration"`). The element type of the `getCategories()` return value; used for compliance audits and cookie-versioning migration-on-read logic.

**ConsentChecked**:
The phantom-type brand `ConsentChecked<F>` attached by `withConsent(consent, factory(deps))` at DI bind time. Signals that the wrapped use case's `requiresConsent` categories will be checked before execution. TypeScript rejects binding an unwrapped factory to a `ConsentChecked`-typed DI symbol when the manifest declares `requiresConsent`. The boot assertion (`assertFeatureConformance`) verifies the brand is present at runtime. See `withConsent` in `@repo/core-consent`.
_Avoid:_ applying `withConsent` in test files — tests inject mocks directly into the factory and do not go through the DI wrappers.

**Rate-limit** (`core-shared/rate-limit`):
Fourth conformance channel after audit/analytics/consent. `IRateLimit` interface (`consume`/`reset`) + `withRateLimit` wrapper + `RateLimited` brand + `rateLimit: { window, budget }` manifest field. Default budgets in manifest, runtime overrides via `ctx.rateLimit` config. Consumer wires Redis/Upstash impl. See ADR-025.

**`IRateLimit`**:
The vendor-neutral rate-limit interface in `@repo/core-shared/rate-limit/`. Two methods: `consume(budgetName, key, weight?)` → `RateLimitDecision` (fields: `allowed: boolean`, `remaining: number`, `resetAt: Date`) and `reset(budgetName, key)`. Two implementations: `InMemoryRateLimit` (dev/test) and a consumer-wired production backend (Redis/Upstash). Feature packages receive it via `ctx.rateLimit` at DI bind time; declared in the manifest's `rateLimit` field.

**`RateLimited`**:
The phantom-type brand `RateLimited<F>` attached by `withRateLimit(rateLimit, fn)` at DI bind time. Signals that the wrapped use case's declared `RateLimitBudget[]` entries will be enforced before execution. TypeScript rejects binding an unwrapped factory to a `RateLimited`-typed DI symbol when the manifest declares `rateLimit`. The boot assertion verifies the brand at runtime.
_Avoid:_ applying `withRateLimit` in test files — tests inject mocks directly and do not go through the DI wrappers.

**`withRateLimit`**:
The wrapper composer that attaches the `RateLimited` brand at DI bind time. Signature: `withRateLimit(rateLimit: IRateLimit, fn)`. Part of the six-wrapper composition chain — see the combined `withSpan / withCapture / …` entry above. Outermost position is `withSpan`; `withRateLimit` sits between `withAnalytics` and the inner factory.

**PII inventory**:
Personal-data declaration at the Payload field level via `custom.pii = { category, purpose, retention, exportable, restrictable }`. Generator emits `compliance/data-map.yml`. DSR cascade walks this at runtime. See ADR-025.

**Retention policy**:
Per-Payload-collection retention via `custom.retention = { activeRetention, postDeletion, purgeSchedule, hardDeleteAfter }`. Generator emits `compliance/retention-policy.yml`. Background purge job in `core-shared/jobs` reads this at boot. Per-PII-field retention overrides apply (more-specific wins). See ADR-025.

**Sub-processor**:
External service that processes personal data on behalf of the controller (Stripe, SendGrid, PostHog, etc.). Declared via extended ADR-022 library traces — `docs/library-decisions/<date>-<pkg>.md` frontmatter gains `is-sub-processor`, `processes-pii`, `data-sent`, `region`, `dpa-signed`, `sccs-required`, `contact` fields. Generator emits `compliance/sub-processors.yml` from traces filtered to `is-sub-processor: true`. See ADR-025.

**`docs/compliance/` vs `compliance/`**:
Split locations for compliance artifacts. `docs/compliance/` (template-shipped) holds FILL-IN TEMPLATES (`.template.md` runbooks, `.example.yml` references). Root `compliance/` (consumer-created) holds LIVE ARTIFACTS (`data-map.yml`, `retention-policy.yml`, `sub-processors.yml` from generators + consumer-authored filled runbooks). Audit evidence lives in `compliance/`. See ADR-025.

**Fill-in template**:
A `.template.md` file under `docs/compliance/templates/` containing placeholder markers (`[FILL IN:]`) that a project team copies to `compliance/` and completes with project-specific values before launch.

**`[FILL IN:] marker`**:
The literal string `[FILL IN:]` used in fill-in templates to mark every placeholder that requires a project-specific value; machine-detectable via `grep -rn '\[FILL IN:' compliance/` to audit completion status.

**Pre-launch compliance checklist**:
The operational checklist at `docs/guides/pre-launch-compliance-checklist.md` enumerating the GDPR and security controls that must be verified before going live with a production workload — covers data mapping, retention policy, DSR readiness, consent UI, sub-processor contracts, and security headers.

**Compliance overview**:
The hub document at `docs/guides/compliance-overview.md` that maps the full GDPR compliance surface of the template — explains where each artifact lives, which generator or guide produces it, and how the pieces connect (PII inventory, retention, DSR, audit, consent, sub-processors, policy templates, and the pre-launch checklist).

**Span**:
A traced unit of work. Emitted by `tracer.startSpan(...)` (inline in repos) or `withSpan(...)` (composed for use cases + controllers).

**Capture**:
The act of recording an exception once. Guarded by the non-enumerable `__sentryReported` flag so a bubbled error surfaces exactly once.

**PII scrub**:
The server-side scrubbing of email/passwords/tokens/cookies/auth/IPs at the OTel processor layer (`PiiScrubSpanProcessor` + `PiiScrubLogRecordProcessor`) before any exporter sees the data. `sendDefaultPii: false` everywhere, CI grep-enforced. See ADR-017 §7.

**Rule 0**:
The `bindAll()` decision that selects OTel+Sentry instrumentation when a DSN env var is present, otherwise the Noop chain. Orthogonal to `USE_DEV_SEED` / `NODE_ENV` (those control repo bindings, not instrumentation).

## Security

**`SecurityHeadersConfig`**:
The TypeScript type accepted by `buildSecurityHeaders()`. Fields: `mode` (`"prod"` | `"dev"`), optional `nonce` (per-request CSP nonce string), and optional allowlist arrays `allowedConnectOrigins`, `allowedImgOrigins`, `allowedFontOrigins` (absolute URLs). Lives at `@repo/core-shared/security`.

**`buildSecurityHeaders()`**:
The pure function in `@repo/core-shared/security` that accepts a `SecurityHeadersConfig` and returns a `Record<string, string>` of HTTP security headers: `Strict-Transport-Security`, `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`, and `Content-Security-Policy`. In `"prod"` mode the CSP uses `strict-dynamic` + nonce; in `"dev"` mode it relaxes to `unsafe-inline`/`unsafe-eval` to allow HMR tooling.

**`nonce`** (CSP context):
A per-request cryptographically random token (typically 16+ bytes, base64-encoded) threaded into the `Content-Security-Policy` header's `script-src` directive as `'nonce-<value>'`. Required when using `strict-dynamic` CSP to permit specific server-rendered inline `<script>` tags (e.g. Next.js bootstrap chunk, Sentry SDK loader) without `unsafe-inline`. Passed to `buildSecurityHeaders({ nonce })` and set as the `nonce` attribute on matching `<script>` elements.
_Avoid:_ reusing the same nonce across requests — it must be regenerated per HTTP response to preserve the security guarantee.

## Workflow

**PRD**:
The top-level requirements doc at `docs/work/prds/<date>-<slug>.prd.md`. Status flows `draft → in-review → approved → shipped` (`pnpm work prd-ship` auto-flips on epic completion). `pnpm work decompose` refuses to run on `draft`.
_Avoid:_ spec (in this template the **ADR** is the durable design record; PRDs are the implementation seed).

**Epic**:
A large body of work, one folder under `docs/work/epics/<epic-slug>/` with `_epic.md`. Decomposed from a PRD.

**Story**:
One use case or one technical capability, one folder under `<epic>/<story-slug>/` with `_story.md`. Type metadata: `user-story` or `technical-story`.

**Task**:
One vertical slice = one PR = one commit. File `<slug>.task.md` under the story folder.

**Slice** (a.k.a. **vertical slice**):
A change that exercises every Clean Architecture layer end-to-end for one capability — manifest entry + contracts + tests + impl + DI wiring + integration. The unit of a task.

**Sandcastle**:
The agent dispatch orchestrator (https://github.com/mattpocock/sandcastle). Invoked via `pnpm work dispatch --execute`. See ADR-019.

**`_state.json`**:
The orchestrator-managed derived index at `docs/work/_system/_state.json`. Regenerated from markdown via `pnpm work rebuild-state`. Committed.

**Generator**:
A `pnpm turbo gen <kind>` invocation. Generator-first is **non-negotiable** — agents always prefer the generator over hand-rolled scaffolding. Available kinds: `feature`, `event`, `job`, `realtime`, `core-package`, `core-ui-component`.

**Slice = task = PR = commit**:
The shipping rhythm. One vertical slice closes one task, becomes one PR, lands as one commit.

**Library trace**:
A per-decision artifact at `docs/library-decisions/<YYYY-MM-DD>-<package-name>.md` recording the outcome of the `evaluate-library` skill against a candidate third-party dependency. Frontmatter is the machine surface (tier, decision, filter-results enum); headings are the human surface (one per filter + one per prompt). Both `decision: approved` and `decision: rejected` traces are first-class — the rejection record is the value, since it stops future agents from re-evaluating the same library. Required for any new runtime dep in a `feature`- or `core`-tagged package; the pre-commit hook blocks the commit if the trace is missing.

**Pre-shipped trace**:
A library trace emitted by `pnpm turbo gen core-package <name>` for each direct runtime dep of a pre-curated optional core. Pre-approved by the template's ADRs (015 events / 016 realtime / 018 audit). Generated alongside the core's frozen snapshot so optional cores satisfy the library-evaluation policy by default.

**Trace revalidation**:
The weekly + on-demand CI job (`.github/workflows/trace-revalidation-weekly.yml`) that re-runs every approved trace's `verification-commands` block and detects drift in license / maintenance / CVE / EU-residency / Socket-risk signals that don't show up as version bumps. Two-tier divergence action: **soft divergence** appends to a rolling dashboard issue; **hard divergence** (license changed, named-consumer gone, critical CVE disclosed, EU residency flipped, Socket-flagged) opens a per-dep issue labeled `library-policy/re-evaluation` for the dispatch loop to pick up. Never auto-edits the trace — the re-walk needs the `evaluate-library` skill, not a mechanical edit. Records the most-recent successful pass in the trace's `last-revalidated` frontmatter field (separate from the original adoption `date`).

**Major-bump re-evaluation**:
The Renovate-triggered re-walk of `evaluate-library` when a runtime dep's major version bumps (semver-major, distinct from minor/patch). Updates the existing trace in-place (refreshes `version`, `filter-results`, `verification-commands`, `last-revalidated`), preserves the original `date`. Catches license / maintenance / transitive-surface changes that semver-encodes as "breaking." Minor + patch bumps do not trigger re-evaluation.

## Modes

**Production mode**:
`NODE_ENV=production` (and `USE_DEV_SEED` unset) → `bindAll()` wires Payload-backed repositories + `PayloadJobsEventBus` + `PayloadJobQueue`.

**Dev-seed mode**:
`USE_DEV_SEED=true` (or default fallback when not in production) → `bindAll()` wires populated mocks + `InMemoryEventBus` + `InMemoryJobQueue`. Developer default so `pnpm dev` boots without Payload running.

## Relationships

- A **PRD** decomposes into one or more **Epics**.
- An **Epic** contains one or more **Stories**.
- A **Story** is implemented by one or more **Tasks**, each a **Slice**.
- A **Use case** is declared in a **Manifest** before it has code (manifest-first ordering).
- A **Use case** has exactly one **Controller**.
- A **Controller** has at most one **`presenter`** (omitted for void outputs).
- A **Feature** owns its **Repositories**, **Services**, **Use cases**, **Controllers**, **Events**, **Jobs**, **Channels**, and **DI Container**.
- **Cross-feature reactions** travel through the **Event bus**; **in-feature reactions** are direct use-case calls.
- An **Event descriptor** is public; its **Event handler** is always private.
- A **Channel descriptor** is public; its **Realtime handler** is always private.
- **Brands** are attached only at **DI bind time**, by **`withSpan` / `withCapture` / `withAudit`**.
- **Conformance** asserts the **Manifest** and code agree, at five latency tiers.
- A **Coverage band** in the **Manifest** is read by Vitest (L0), `assertFeatureConformance` (boot), and `pnpm coverage:diff` (L1) — one decision, three enforcers.
- **Mutation testing** is the third dimension of test quality, after "test file exists" (ESLint structural) and "test executes the code" (L0/L1 coverage).

## Flagged ambiguities

- **"feature"** — always a vertical feature package; never a CMS-collection field or a generic capability.
- **"service"** — a DI-injected port (e.g. `IAuthenticationService`); not a Kubernetes service, Payload collection, or generic "service object".
- **"handler"** — qualify by context: **event handler** (cross-feature) | **realtime handler** (inbound socket message) | **task handler** (Payload job).
- **"schema"** — qualify: **Zod schema** (input/output contracts) | **Payload collection schema** (CMS field definitions).
- **"config"** — qualify: **Payload config** | **Next config** | **Vitest config** | **TS config**.
- **"bind"** — DI binding (`bind<I>(SYMBOL).toDynamicValue(...)`); not a `Function.prototype.bind`.
- **"spec"** — avoid in this template. Durable design records are **ADRs** (`docs/decisions/adr-NNN-*.md`); implementation seeds are **PRDs** (`docs/work/prds/*.prd.md`). Never use "spec" to refer to a Jest spec file either.
- **"controller"** — one verb-noun pair per file; never a multi-method MVC controller.
- **"module"** — qualify by context: **package** (workspace member under `packages/` or `apps/`) | **Node ESM/CJS module** (file-level import semantics) | **refactor-vocabulary "module"** (in the `improve-codebase-architecture` skill, defaults to **feature** — i.e., a `packages/<name>/`; can also mean a narrower unit like a use case or controller when the refactor scope is that narrow). Default: prefer "feature" for the common case; "package" for the workspace-member shell; "module" only inside refactor conversations.
- **"seam"** — refactor-vocabulary only (where a module's interface lives). Not a synonym for **boundary** (ESLint workspace-tag rule) or **scope** (Conventional Commits parenthetical).
- **"adapter"** — refactor-vocabulary only (a concrete thing satisfying an interface at a seam). Not a synonym for **port** (the interface itself) or **service** (a DI-injected port for non-collection capabilities).
- **"coverage"** — qualify when ambiguous: **L0 coverage** (per-layer thresholds, test-time) | **diff coverage / L1** (cover-the-diff gate) | **aggregate coverage / L2** (committed summary.json) | **mutation coverage / L3** (Stryker mutation score, not line coverage).

## Cross-references

- Architecture: `docs/architecture/overview.md`, `docs/architecture/vertical-feature-spec.md`, `docs/architecture/agent-first-workflow-and-conformance.md`
- ADRs: `docs/decisions/adr-NNN-<slug>.md`
- Workflow: `docs/work/README.md`, `AGENTS.md` § "Agent-driven development"
- Guides: `docs/guides/runbook.md`, `docs/guides/conformance-quickref.md`, `docs/guides/tdd-workflow.md`
