ADR-038 — Evidence artifact nomenclature: Decision Capsule vs Evidence Pack vs Evidence Bundle

Context

The product ships three artifacts that all wear “evidence” branding, and the 2026-07-19 Fable review found the three-way naming split “leaks all the way to a 500” and “confuses navigation” (§8), with the sharpest failure in §1:

The console capsule route /evidence/capsules/:id errored “Unable to load evidence pack … Unknown error” because it called GET /v1/evidence-packs/{id}HTTP 500 — a different, empty store (evidence_packs) than the one the sealed capsule actually lives in (decision_capsules). “Capsule vs pack vs bundle nomenclature leaks all the way to a 500.”

The three artifacts are genuinely different concepts that happen to share the word “evidence” — merging them into one word would be wrong. What was wrong was (a) no settled vocabulary, and (b) one route cross-wired to the wrong store. This ADR settles the vocabulary and records the store contract so the collision cannot recur.

Decision

Keep the three artifacts distinct, with one canonical name, store, and route each. Never cross-wire a route to another artifact’s store.

ArtifactWhat it isOwning module / storeCanonical routeUser-facing name
Decision CapsuleThe sealed, signed (DSSE), content-addressed manifest of one release/gate decision’s evidence references (SBOM / policy / VEX / reachability) + retention. The cryptographic proof unit of a decision. Lifecycle: create → seal → verify → replay → export.EvidenceLocker evidence_locker.decision_capsules (CapsuleEndpoints, ICapsuleRepository)/api/v1/evidence/capsules[/{id}]Decision Capsule
Evidence PackAn Advisory-AI investigation’s claims + evidence items about a vulnerability subject (CVE / finding / component), content-digested and DSSE-signable. Analytical output of Advisory AI — not a decision seal.AdvisoryAI (StellaOps.Evidence.Pack, IEvidencePackStore)/v1/evidence-packs[/{packId}]Advisory Evidence Pack
Evidence BundleAn operator-assembled, downloadable ZIP export aggregating audit artifacts (SBOM / VEX / attestations / policy / vuln) for a subject or time-range. A packaging / export unit.Audit / EvidenceLocker export path/evidence/bundlesEvidence Bundle

Naming contract (binding):

  1. Routes and stores stay 1:1 and never cross-wire. The capsule route reads decision_capsules; the pack route reads the evidence-pack store; the bundle route reads the bundle export. A capsule id resolved against the pack store (the original bug) is forbidden.
  2. Unknown ids return 404, never 500. The capsule read (CapsuleEndpoints.GetCapsuleAsync) answers authoritatively from decision_capsules and returns 404 capsule_not_found for an unknown id.
  3. User-facing copy uses the qualified name — “Decision Capsule”, “Advisory Evidence Pack”, “Evidence Bundle” — at any surface where two of them could be confused. Never a bare “pack” / “capsule” / “bundle” at a collision point.

Status of implementation (what already landed vs. deferred)

Data-path — DONE (the [H] capsule-500 fix):

Deferred (cosmetic, tracked here so it is not lost): the FE component and folder that serve the capsule route are still named EvidencePackViewerComponent / src/Web/StellaOps.Web/src/app/features/evidence-pack/ even though the route is the Decision Capsule route. The user never sees this (route title/breadcrumb say “Decision Capsule”); it is an internal rename only. It is deliberately deferred because a component/folder rename is a high-collision FE refactor best done in a quiet FE pass, not into concurrent multi-agent churn.

Consequences

The slow console list endpoints flagged in the review §12 were fixed alongside this nomenclature ratification: the /console/admin/users list N+1 (per-user role query + fresh DB connection per user → one batched query), the console-dashboard serial upstream fan-out (findings + VEX + run-health now fetched concurrently), and a composite (tenant_id, type, name) index for GET /api/v1/integrations?type=…. Those are engineering fixes, recorded in the sprint/PR — not architectural decisions — and are noted here only so a reader tracing the G8 cross-cutting pass finds them.