# 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//`. 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 ` — `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//api` or `@repo//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//src/entities/`): Domain models (`models/.ts`) and domain errors (`errors/.ts` + `errors/common.ts`). No I/O. **Application layer** (`packages//src/application/`): **Use cases**. Pure orchestration over repository + service ports. **Infrastructure layer** (`packages//src/infrastructure/`): **Repository** and **service** implementations (real Payload-backed + mock). **Interface-adapters layer** (`packages//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//src/integrations/`): Vendor-specific glue — `integrations/api/` (tRPC routers), `integrations/cms/` (Payload collections + tasks). **DI folder** (`packages//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`. _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/.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//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()` 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 `// ` comment marking where a generator injects code (e.g. ``, ``, ``). 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//`) 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, `// ` 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 (`.repository.ts`), mock (`.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 []`. _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/]`. **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 — `(): `. 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//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-.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//src/events/.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//src/events/handlers/on--.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//src/realtime/.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:` | `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//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` 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` 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/-.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. **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` 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-'`. Required when using `strict-dynamic` CSP to permit specific server-rendered inline `