Evidence consolidation — S0 target design (SPRINT_20260722_011 EVD-1)
Status: S0 DRAFT for review (2026-08-03). Verification base: the sprint’s recorded dig rounds (12/17 internals, EVL-4 owner approval), the live migration baselines (tables re-enumerated from
src/this pass), and the 2026-08-03 build-boundary register. Sections marked ⚠ carry explicit remaining-verification notes. Update 2026-08-03: all ⚠ marks are CLOSED (second pass, verified againstsrc//live) — see §2.1, §2.3, §4, §5.
1. Current → target shape
| Current | Target | |
|---|---|---|
| Deployables | attestor, attestor-tileproxy, tsa (openssl infra container — no .NET, no DB), evidence-locker-web + -worker (role containers of one image) | evidence-web + evidence-worker; tileproxy + TSA as role/infra containers of the family (§4 topology) |
| Source | src/Attestor/StellaOps.Attestor.*, src/EvidenceLocker/StellaOps.EvidenceLocker* | `src/Evidence/StellaOps.Evidence.WebService |
| DAL | Attestor.Persistence (Attestor.TrustVerdict DELETED 2026-08-03, §2.3), EvidenceLocker migrations in TWO homes (§2.4 hazard) | StellaOps.Evidence.Persistence.Consolidated(see the name-collision note below), fresh 001_* baseline, database stellaops_evidence, env STELLAOPS_POSTGRES_EVIDENCE_CONNECTION fail-closed |
Name collision, D-EVD3-14 (2026-08-10, EVD-3 Stage B). The D12 target DAL name this table and
docs/architecture/database-ownership-matrix.md§5.2 both originally specified —StellaOps.Evidence.Persistence— is already taken bysrc/__Libraries/StellaOps.Evidence.Persistence, an unrelated shared library that owns a differentevidenceschema (generic evidence records, EF Core, once migrated centrally by platform-web’sEvidenceMigrationModulePlugin— deleted with the plugin mechanism on 2026-09-14, SPRINT_20260722_021 PLT-4) and is compiled byPlatform.Database. Two projects cannot share an assembly name, so the merged DAL takes the.Consolidatedsuffix, following Notify / Timeline / ReleaseOrchestrator / Integrations / CredentialStore. The twoevidenceschemas never meet: that library’s lives in the shared platform database, the family’s lives instellaops_evidenceand holds only the migration ledger pair. | Excluded | Signer (key-custody boundary, non-negotiable) — consumed only through its client contract | unchanged |
2. Table inventory + dispositions (P13)
Re-enumerated from the live baselines this pass.
2.1 attestor (9 tables)
| Table | Purpose | P13 class | Disposition |
|---|---|---|---|
entries, local_transparency_entries | attestation entries + local transparency log | evidence/append | carry |
verdict_ledger (live home confirmed 2026-08-03: attestor schema) | hash-chained (prev_hash→verdict_hash; rekor uuid, policy bundle hash, signer keyid per row) | evidence/append | CARRY with the EVD-9 chain gate — S9 recomputes chain linkage across moved rows before revocation |
rekor_submission_queue, transparency_exchange_batches | submission/exchange queues | operational | carry (queue semantics onto P6 where re-authored) |
external_transparency_targets, external_transparency_mirror_receipts | mirror config + receipts | operational/evidence | carry |
identity_watchlist, identity_alert_dedup | identity watch machinery | operational | carry — readers VERIFIED (2026-08-03): in-family only (PostgresWatchlistRepository, WatchlistEndpoints, alert-dedup store); the CLI consumes via POST /api/v1/watchlist (API-mediated, no cross-DB); Notifier consumes the alert EVENT contract, not the tables |
bulk_verification_jobs | verification job rows | operational | redesign onto the family’s job substrate — semantics VERIFIED (2026-08-03): single-writer claim is SOUND (FOR UPDATE SKIP LOCKED oldest-queued acquire, status CHECK, partial index on active states) but there is NO input-hash dedup (id PK only, no unique constraint on request identity) — resubmitting the same bulk request creates a second job; the re-authoring adds the DC-13 non-terminal same-input dedup the Policy queue proved |
2.2 proofchain (8 tables + 1 materialized view)
dsse_envelopes, spines, graph_nodes, graph_edges, rekor_entries, sbom_entries, trust_anchors, predicate_type_registry — the proof-chain spine. All evidence/append or registry class; carry. The EVD-9 gate covers spines linkage too (round 17).
Corrected 2026-08-10 (EVD-3 Stage B, measured). This section said “9 tables” and included
audit_log. There is no such table: the collapsed legacy baseline CREATEs it (mig061/001) and then DROPs it (mig061/004 — superseded bytimeline.unified_audit_events), so the converged shape has eight. Reproducing it in the fresh baseline would have resurrected a table the estate deliberately retired. The section also omittedproofchain.artifact_canonical_records, a materialized view (the Evidence Thread read projection,REFRESH … CONCURRENTLY-able via its unique index), which does carry. Both facts come from applying the legacy chains to a throwaway instance and dumping the result, not from re-reading the migration files.§2.1 above is titled “9 tables” while listing ten; ten is right, and the fresh baseline pins the exact set per schema (10 + 8 + 13).
2.3 vex.trust_verdicts (Attestor.TrustVerdict) — RESOLVED: DEAD WIRING (2026-08-03)
The mis-homing is only ON PAPER. StellaOps.Attestor.TrustVerdict has zero production consumers: no host references the project, nothing calls its registration extensions, and vex.trust_verdicts does not exist in the live database (its 001_create_trust_verdicts.sql — which would CREATE SCHEMA vex from an Attestor library — never ran anywhere). The library is a complete unshipped feature (service, OCI attacher, metrics, canonicalizer, RLS’d migration). OWNER RULING (2026-08-03, review item A7): DELETE (“ok, delete it”) — the library, its tests, and its never-applied migration are removed outright; no park, no adoption. Dead-wiring find #6 for the program.
EXECUTED 2026-08-03 (commit 38dd5fa): zero-consumer claim re-verified independently before deletion, then src/Attestor/__Libraries/StellaOps.Attestor.TrustVerdict/, its test project, and an orphan src/Attestor/__Tests/StellaOps.Attestor.TrustVerdict.Tests/TrustVerdictIntegrationTests.cs (a file with no .csproj — it never compiled) were removed, along with the entries in src/StellaOps.sln and src/Attestor/StellaOps.Attestor.sln. 83 files, 6 618 deletions, zero insertions. StellaOps.Attestor.WebService builds clean afterwards, and the build-boundary report regenerates byte-identical — the library was never a boundary participant. vex.trust_verdicts therefore cannot enter the fresh S3 baseline; nothing to park or adopt.
2.4 evidence_locker (13 tables; TWO migration homes — baseline hazard, RESOLVED)
StellaOps.EvidenceLocker/Migrations/ AND …Infrastructure/Db/Migrations/ both define verdict_attestations — live evidence 2026-08-03: the live DB holds ONE evidence_locker.verdict_attestations whose 16 columns MATCH the root Migrations/ home’s definition (verdict_id…rekor_log_index+timestamps); the fresh baseline adopts that shape and the duplicate definition dies with the collapse.
Resolved 2026-08-10 (EVD-3 Stage B) — the hazard is narrower than “two homes” suggests. The root home,
src/EvidenceLocker/StellaOps.EvidenceLocker/Migrations/001_CreateVerdictAttestations.sql, is not an embedded resource of any project —StellaOps.EvidenceLocker.csprojdeclares noEmbeddedResourceforMigrations\*.sql, only<Compile Remove>entries — and no code references it by name. It has therefore never applied anywhere, so this was one live definition and one dead file rather than a genuine double-definition race. The fresh baseline carries the Infrastructure shape (16 columns, verified) and the dead file dies with the collapse as planned.
| Table | Purpose | P13 class | Disposition |
|---|---|---|---|
evidence_bundles, evidence_bundle_signatures, evidence_artifacts, evidence_packs, evidence_pack_artifacts, evidence_gate_artifacts | bundle/pack/artifact families (bulk bytes in object storage; relational footprint ~1.6 MB) | evidence | carry |
evidence_holds | legal holds — bundle-scoped (bundle_id, case_id, expires_at, released_at) | legal-hold (overrides EVERYTHING) | carry; the merged baseline’s P13 headers MUST encode that an unreleased hold blocks every cleanup path — including the SCR-4 tenant-deleted cascade (this family registers the hold-aware ITenantLifecycleHandler; holds WITHHOLD disposal and say so in the report) |
regulatory_retention_records, regulatory_audit_events, regulatory_artifact_ledger | regulatory machinery | audit/evidence | carry byte-exact |
decision_capsules, legacy_pii_capsules | capsule stores (PII-bearing legacy set) | evidence (PII-flagged) | carry; PII class recorded (actor-identity minimization already keeps new capsules opaque) |
verdict_attestations | verdict↔attestation links | evidence | carry (single definition, §2.4 hazard) |
3. Build-boundary dispositions (2026-08-03 register)
- Family-internal after the merge:
attestor-tileproxy → attestor,evidence-locker-web → attestor— die by consolidation. → signer(from attestor, tileproxy, evidence-locker): stays a boundary — Signer is excluded by custody rule; the seam becomes the Signer client contract only (closed-graph verified), never implementation.attestor → concelier— hub repoint (003 consumer family; SourceIntel was flagged genuinely contract-shaped in the 003 survey — candidate closed-SDK classification).attestor → scanner— DC-15-class read seam with 017.- Inbound (callers compiling THIS family — the merge must publish ONE closed Evidence client/contracts SDK): Policy (
EvidenceLocker.Core+ Attestor assemblies), ExportCenter (compiles the EvidenceLocker SERVICE project), VexLens/Findings (Attestor assemblies), SbomService (attestorfamily pin, 5 projects). The closed-SDK surface is the S0 deliverable that unblocks those programs’ repoints.
Reality note (2026-08-05, EVD-3 D-EVD3-1). The sentence above described the closed Evidence SDK as though it existed. It did not:
src/EvidenceLockerhad no client/contracts project of any kind, and ExportCenter reached the TLPT evidence-pack records andCapsuleManifestCanonicalizerby referencingStellaOps.EvidenceLocker.csproj— the SERVICE. Sprint 025 OK-4 (D-OK4-5) hit this as a hard blocker and left the OfflineKit hosts unwired rather than import the edge. The SDK now exists assrc/EvidenceLocker/__Libraries/StellaOps.EvidenceLocker.Contracts(EVD-3 Stage A) and carries the wire manifests plus the canonicalisation rule only. Treat “closed Evidence SDK” in this document as the SINGULAR final surface the merge converges on; the locker-side contracts project is its first, live instalment, not the whole of it — the attestor-side carriers are classified separately in the ownership manifest.
4. Role topology (EVD-1 decision input)
Recommendation: one family, four run shapes — evidence-web (API: attestor + locker surfaces), evidence-worker (queues: rekor submission, bulk verification, locker export/pack jobs), evidence-tileproxy (existing proxy, unchanged runtime role), tsa (unchanged openssl infra container; compose grouping + docs ownership only). Availability argument: the web/worker split preserves today’s locker worker isolation; tileproxy stays a stateless edge; nothing gains a new single point of failure. Tileproxy config surface VERIFIED (2026-08-03): env prefix TILE_PROXY__tile_proxy__* (an idiosyncratic double-nested binding — the rename must carry or alias this exact surface: UpstreamUrl/Origin/Sync/Cache keys), tile cache on a mode-1777 tmpfs (rebuildable — stateless confirmed), cert volume + attestor-tileproxy.stella-ops.local alias; runs LIVE today alongside all five siblings.
4.1 Timestamp Assurance proposal (2026-08-19; not an owner ruling)
Owner-decision register item 14 asked for a separate sprint/information pack for the 22 orphaned Doctor Timestamping checks. The source-grounded recommendation is to place a Timestamp Assurance subsystem inside this Evidence family, split between evidence-web (authenticated API plus 17 installation-scoped doctor-check/v1 checks) and evidence-worker (scheduled probes, five tenant-scoped evidence checks, and re-timestamp work). This is proposed and unimplemented; it does not alter the approved EVD topology or claim owner acceptance.
The proposal creates no deployable or database. The OpenSSL tsa remains the database-less infrastructure role described above, and its private key stays in the operator-controlled tsa-data custody boundary; neither Evidence host mounts it. Signer remains excluded and separate. OfflineKit transports a versioned content-addressed trust bundle while Evidence owns semantic validation and retained evidence, avoiding the current Doctor plugin’s P19-invalid direct AirGap.Importer reference. The existing Evidence doctor checks (database identity, append-only, forced RLS, verdict-chain linkage, and legal-hold integrity) do not overlap timestamp issuance, token/trust/revocation posture, or time correlation.
Full source census, the row-by-row 22 → 17 installation + 5 tenant map, security/retention model, and first safe implementation slice: Timestamp Assurance design. Executable proposal: SPRINT_20260819_001.
4.2 EVD-5 source-composition checkpoint (2026-08-22)
The target hosts are no longer idle skeletons. evidence-web composes the two application layers extracted at EVD-4 without referencing either predecessor host project. Every compatibility connection key is assigned from the already fail-closed STELLAOPS_POSTGRES_EVIDENCE_CONNECTION resolution, so the carried repositories cannot select a legacy/shared database. The target composition suppresses Attestor.Persistence startup migrations, the private EvidenceLocker migration runner and every background loop in the web role; only StellaOps.Evidence.Persistence.Consolidated converges the database. The extracted endpoint mappers now accept a route prefix, and the target maps the manifest’s nine passthrough families natively at /api/evidence/v1/**, including a target alias on the proof controller.
evidence-worker has likewise stopped running the idle EvidenceQueueWorker. It composes the Attestor Rekor retry, bulk verification and configured transparency-sync workers plus the Locker retention and legacy-PII audit loops against the same one database, without either predecessor migration authority. A real-host test asserts representative target routes, proves those loops are absent from the web role, proves they are present in the worker role, and proves the Locker legacy migration host is absent from both. The focused composition tests are 2/2 and the full adjacent Evidence host project is 23/23; both target roles and all three touched predecessor roles build.
The six gateway-rewritten Locker groups (score, snapshot, UUID retrieval, QA assurance cases, verify, hold) have now been extracted into the owner application surface. The predecessor maps them at their unchanged /evidence/** paths; evidence-web maps the same methods, policies, endpoint names and prefix-aware resource links beneath /api/evidence/v1/evidence/**. Focused route-inventory and unauthenticated-behaviour tests pin the target surface.
This closes only the API-surface gap. The EVD-9 preflight remains NO-GO and the target is not cutover-ready.
The setup-owned default region and the tenant slug-to-UUID source path are now closed. The target requires Catalog:Replication:Tenants:Enabled=true, auto-migrates catalog_replica and eventing inside stellaops_evidence, and replaces only its carried IEvidenceLockerTenantResolver with an adapter over ReplicaStellaOpsTenantResolver. Exact active slugs resolve locally; suspended, tombstoned and measured-unknown slugs return no tenant; an unreadable or never-converged replica throws CatalogReplicaUnavailableException rather than manufacturing an absence. The live EvidenceLocker predecessor and its resolver remain unchanged. The complete Evidence web test project passed 32/32; after pinning the target database name and migration-table assertions, the final host-composition slice passed 11/11 with a clean 0-warning / 0-error build.
The still-open blocker categories are:
- Direct callers still need their recorded census and window repoints. Section 4.3 records the initial two-reader census and the completed Platform and CLI source repoints, so no foreign direct SQL reader remains. The broader direct-HTTP caller receipt is still required.
- Build-boundary conformance reports exactly four unpinned merge pairs:
evidence-webandevidence-workereach reach bothattestorandevidence-lockerimplementation. The union is 17 predecessor implementation projects: 13 Attestor projects in the web closure (12 in the worker closure) and four EvidenceLocker projects (three in the worker closure). Those same projects are still compiled by the three supported predecessor hosts. Therefore none of the obvious bookkeeping changes is a seam: re-homing/reclassifying only the libraries reverses the violation onto the predecessor hosts, rewriting both predecessor families toevidencechanges 16 current pins owned across the estate, and four temporary pins hide rather than remove the dependency.check-evidence-p19-transition.ps1accepts only the exact current pre-state or the complete EVD-10 post-state and rejects every mixture. The owner must choose the transition model: the recommended reviewed EVD-9/EVD-10 atomic source re-home + predecessor-host retirement, or an explicitly accepted temporary source-duplication model with a non-vacuous parity guard. No such duplication is authorized today. - Target image/runtime configuration and authorized/unauthorized plus store/retrieve forcing are still absent. Both tracked Authority Standard descriptors and their focused conformance test now define
stellaops-evidence-webwith exact default tenant,stellaopsaudience,client_credentials, and onlycatalog:replicate platform:doctor:register. The source prerequisite does not reconcile a running Authority or install a secret: the staged compose overlay remains fail-closed on an explicitly supplied client ID and operator-owned secret. EVD-9 must reconcile the live row, prove the exact token/feed claim set, and capture a durable local-replica checkpoint before forcing or enabling Doctor registration. - The complete EVD-9 operator runbook is recorded with ordered backup/copy/parity/hash-chain/repoint/revoke, rollback, soak and forcing steps. It still needs an approved rehearsal/window and the source-ownership decision above.
No boundary report/register, route table, compose activation, database or live container changes are implied by this design state.
4.3 Direct-SQL reader census and owner seams (2026-08-23)
A production-source scan outside src/Attestor, src/EvidenceLocker, src/Evidence, test trees and obsoleted trees initially found exactly two foreign direct-SQL readers of the three carried schemas. SPRINT_20260722_021 PLT-1A closed Platform’s row and SPRINT_20260722_026 CM-5 closed the CLI row; the same current-source scan now finds zero foreign direct-SQL consumers:
| Consumer | Current source state | Owner API seam | Remaining owner work |
|---|---|---|---|
| Platform | CLOSED 2026-08-23 (PLT-1A): PostgresLegacyCapsuleErasureRefusalSource and the silent no-refusal binding are deleted; Platform has no evidence_locker.* SQL | POST /api/v1/evidence/legacy-capsule-erasure-refusals/{actorRef} on the predecessor and POST /api/evidence/v1/evidence/legacy-capsule-erasure-refusals/{actorRef} on the target; request/response live in the closed StellaOps.EvidenceLocker.Contracts graph | Complete: authenticated tenant-bound envelope with only evidence:create, exact partial/completed projection, canonical target precedence, and fail-closed one-host behavior are source-tested. Live EVD-9 route/config change remains separate. |
CLI (CliLocalTransparencyRekorClient) | CLOSED 2026-08-23 (CM-5): no attestor.local_transparency_entries, NpgsqlDataSource, or selectable local connection string remains in production CLI source | predecessor GET /api/v1/rekor/entries/{uuid} and target GET /api/evidence/v1/rekor/entries/{uuid} return the owner-computed inclusion proof and checkpoint | Complete: attest:read bearer authentication, canonical target precedence, composition fail-closed, one-host behavior, and independent payload/Merkle verification are source-tested. Live EVD-9 route/config proof remains separate; Rekor-v2 is not used as a fallback. |
The Platform consumer now uses the seam that invokes the existing owner-side ILegacyCapsuleErasureRefusalService, including its refusal audit, instead of reproducing its joins or retention mapping. Producer tests pin the exact method, evidence:create policy, envelope tenant/request mapping, response projection, and anonymous denial; Platform tests verify the signed tenant envelope, both exact route prefixes, canonical precedence, response parity, and fail-closed no-retry/no-SQL behavior. The predecessor maps the same contract so Platform can leave SQL before the database move. The CLI now selects the same predecessor/target owner family at composition and verifies its proof locally, so only the broader direct-HTTP caller census/repoint remains an EVD-9 caller blocker.
That database-authority closure is deliberately narrower than P19 closure. A source and ownership re-census found that two of the production CLI’s seven direct Attestor references are already legal closed SDKs (StellaOps.Attestation and StellaOps.Attestor.Envelope), while five entered the Attestor service-family implementation. StellaOps.Attestor.TrustRepo was a dead edge: no CLI source named one of its types, its lone namespace import was stale, and suppressing the direct reference left no transitive path to the project. The reference and import are removed. Of the four remaining implementation edges, StellaOps.Attestor.Timestamping had a one-project closure and only served the attest sign --timestamp path, whose transport method unconditionally threw the recorded “No RFC-3161 TSA client is configured” failure. The CLI now preserves that exact exit-2/no-output failure locally and no longer compiles the unused implementation. The surviving StellaOps.Attestor.Oci edge is a legal producer-owned closed client SDK by measured shape rather than name: exactly five source files, one direct Attestor.Envelope reference, one logging-abstraction package, and a four-project closure containing only that same-producer SDK plus neutral Cryptography and Localization foundations. Registry transport is supplied by the CLI through IOciRegistryClient; the SDK owns no HTTP client, host, persistence, migration, background worker or DI composition. Executable conformance pins that exact surface and classification without changing OCI, registry or DSSE behavior. The two real implementation edges that remain are StellaOps.Attestor.StandardPredicates and StellaOps.Attestor.Core; each still requires its own behavior-owner split or seam.
4.4 Direct-HTTP caller census and cutover dispositions (2026-08-24)
The EVD-9 HTTP census is now a measured source artifact rather than a placeholder. The scan covers production C# outside tests and src/__Obsoleted, the canonical compose file, the standalone Scanner, ReleaseOrchestrator and Tester compose files, both generated and pinned release-bundle compose surfaces, and Platform’s development launch profile. It combines predecessor-host/config-key searches with typed HttpClient registration and route-literal tracing, because a caller can be direct without spelling the default hostname in its own source. EvidenceDirectHttpCallerConformanceTests pins the exact production source files and compose keys that still spell either predecessor binding, against the census in §4.5; a new binding fails closed, while a removed binding forces its census row into §4.5.3 in the same change.
Gateway translations are not counted as application callers: their complete disposition is the fifteen-to-one EVD-5 route manifest. Front-door consumers such as CLI BackendOperationsClient therefore ride that manifest rather than becoming direct-host rows. Browser routes are owned by EVD-6. Public Sigstore/Rekor URLs are also outside this census unless a supported configuration points that client at the StellaOps Attestor origin.
Configured production and target-internal callers
Accepted 2026-09-12: the caller acceptance and final role receipt close the dispositions below. Final roles run ebbd7814e4; receipt-specific limits remain explicit, including controlled invalid writer requests and conditional timestamp trust.
| ID | Caller and current direct route | Current configuration/state | July owner and required disposition |
|---|---|---|---|
EVD-HTTP-00 | Composed Attestor VerdictController -> Locker POST/GET verdicts | LIVE VERIFIED 2026-09-12. The consolidated named client owns /api/evidence/v1/; the controller uses relative verdicts paths and stores through the Evidence owner. | Sprint 011 EVD-5. Base-path regression tests and architecture conformance are joined by the real Policy verdict create and authenticated owner readback receipt. |
EVD-HTTP-01 | Platform erasure refusal -> POST /api/evidence/v1/evidence/legacy-capsule-erasure-refusals/{actorRef} | EVD-5 resolves only the canonical Evidence origin; predecessor options are ignored. Signed, tenant-bound identity envelope retained. | Sprint 011 complete: adjacent tests and the signed, tenant-bound Platform live owner receipt pass. |
EVD-HTTP-02 | Scanner scan attestation -> POST /api/evidence/v1/rekor/entries | EVD-5 changes typed path and default/configured origin together. Existing service token handler retained. | Sprint 011; actual anchored report assembly is verified with controlled findings, without claiming a new scan-analysis job. |
EVD-HTTP-03 | Retired Excititor remote Attestor client | Host and source runtime withdrawn by the vulnerability consolidation; no supported compose binding remains. | Excluded after successor-aware source/DI/deployed-DLL census of active Vulnerabilities Web/Worker, not predecessor absence alone. |
EVD-HTTP-04 | Retired Excititor Rekor verifier | Same withdrawn host as EVD-HTTP-03; no Rekor-v2 client is retargeted. | Excluded with EVD-HTTP-03. |
EVD-HTTP-05 | Policy verdict -> fixed controller route POST /internal/api/v1/attestations/verdict | Enabled in canonical/release compose with a signed service identity envelope. The controller route is fixed and is composed unchanged by evidence-web; only the origin changes. | Sprint 011 acceptance closes the configured origin and real Policy verdict publication plus the EVD-HTTP-00 durable-store hop. |
EVD-HTTP-06 | ReleaseOrchestrator scan gate -> GET /api/evidence/v1/attestations?subject=...&type=... | EVD-5 changes typed path and default origin. Advisory/blocking semantics unchanged. | Sprint 011 complete: adjacent gate tests and deployed client route acceptance are retained in the caller receipt. |
EVD-HTTP-07 | ReleaseOrchestrator provenance resolver -> GET /api/evidence/v1/attestations?subject=... | EVD-5 changes typed path and default origin. Present/absent/unavailable distinctions retained. | Sprint 011 complete: adjacent outcome tests and live provenance query/verification are retained in the caller receipt. |
EVD-HTTP-08 | ReleaseOrchestrator deployment anchoring -> POST /api/evidence/v1/rekor/entries | EVD-5 changes typed path and default origin; tenant-bound service-token identity retained. | Sprint 011 caller/route gate: deployed production writer plus existing identity propagates canonical owner rejection of an intentionally invalid DSSE payload; positive typed-client specs pass. No deployment exercise is claimed. |
EVD-HTTP-09 | ReleaseOrchestrator evidence seal -> POST /api/evidence/v1/evidence/snapshot | EVD-5 changes typed path and configured origin together. | Sprint 011 caller/route gate: deployed production writer plus existing identity propagates canonical owner validation failure for controlled invalid metadata; positive typed-client specs pass. No promotion or approval is fabricated. |
EVD-HTTP-10 | Findings Ledger VEX override anchoring -> POST /api/evidence/v1/rekor/entries | EVD-5 changes typed path and source default; existing signing/service-token adapter retained. | Sprint 011 complete: real Findings override anchoring is retained in the caller receipt. |
EVD-HTTP-11 | ExportCenter -> POST /api/evidence/v1/evidence/snapshot, POST /api/evidence/v1/evidence/capsules/tlpt-packs | EVD-5 selects both native owner routes. Unused read/distribution clients were already deleted by EVD-DEL-1. | Sprint 011; real snapshot publication plus typed positive TLPT specs and live owner validation propagation. No TLPT exercise or white-team approval is claimed. |
Supported tools, optional roles and measured non-callers
| ID | Surface | Classification and disposition |
|---|---|---|
EVD-HTTP-12 | CLI CliLocalTransparencyRekorClient | EVD-5 accepts only the canonical Evidence owner; authenticated GET and local Merkle verification retained. Predecessor configuration cannot select a route. |
EVD-HTTP-13 | CLI EvidenceCommandGroup and verdict-backed replay | EVD-5 uses canonical bundle export/status/download and portable by-release routes with operator identity. Status requires --bundle; no global export-status route exists. Verdict-backed replay authenticates one canonical Evidence lookup without a predecessor retry. Unsupported card export is withdrawn because no owner endpoint exists. Archive/card structure checks now return unverified, never cryptographic success. Source tests and final live native-content acceptance pass: exported bytes contain the five native files; the existing crypto verify command validates the original signature and rejects tampered input/wrong trust. Replay-engine execution remains outside this caller cutover. |
EVD-HTTP-14 | Optional Tester compose | EVD-5 repoints snapshot, bundle export/status/download and evidence-pack reads to native owner routes, with bearer/tenant forwarding preserved. The final real fixture flow created exactly one new snapshot after cold trust matched, then verified native export/status/download parity. |
EVD-HTTP-15 | Doctor Compliance, EvidenceLocker and ServiceGraph plugins | On-demand/configured, not bound by current compose. The checks can call Attestor /api/v1/signing/status, Locker /api/v1/evidence/{audit-readiness,export/capabilities,metrics,integrity-check}, /v1/attestations/sample, and Attestor /health. Sprint 009 owns replacement checks; EVD-9 records that no running host has these old origins configured, or includes their tested repoint. |
EVD-HTTP-16 | Scanner BuildX plugin | Caller-supplied tool origin. --attestor / STELLAOPS_ATTESTOR_URL is optional and posts to exactly the URI the operator supplies. Sprint 017 must update operator guidance/descriptor semantics; no service-compose repoint exists. |
EVD-HTTP-17 | Timeline HttpUnifiedAuditEventProvider | NO CALL. The old Locker default and helper remain, but GetEventsAsync is explicitly neutered after DEPRECATE-002 and returns an empty set; no legacy helper is invoked. Delete under its deprecation owner rather than treating the literal as live traffic. |
EVD-HTTP-18 | Findings FixChainAttestationClient | UNWIRED. Production source has no IFixChainAttestationClient registration. Sprint 010 either deletes it with its owning island or adds an owner seam; it is excluded from live EVD-9 traffic. |
EVD-HTTP-19 | JobEngine BundleRotationJob | NOT AN HTTP CALLER. Only the IAttestorBundleClient port and scheduler exist; there is no production client implementation or DI binding. Sprint 012 owns the dormant feature. |
EVD-HTTP-20 | Provcache HttpChunkFetcher | UNWIRED generic library. It has relative /api/v1/evidence/{proofRoot}/... reads but no production AddProvcache consumer outside its own library. It is excluded unless a window preflight finds a dynamically loaded consumer. |
The 2026-09-12 consumer acceptance receipt records all 21 dispositions, controlled retained records, and exact limits. The writer rows certify this caller/route cutover, not a new deployment, promotion or TLPT exercise. Final native five-file archive acceptance passed after cold-start public trust verification, with identical API/CLI/Tester/cache bytes and successful original-signature verification plus tampered-payload and wrong-trust refusals. The package is a signed-reference archive; it does not embed referenced material bytes or certify timestamp/checkpoint signatures.
The supported compose binding inventory is enumerated per key in §4.5.2, and the production-source literal inventory in §4.5.4. A prose count used to stand here instead, and it went stale on its own: it still read ten assignments including a Findings one on 2026-09-01, five days after SPRINT_20260722_010 FND-10 retired that binding. Arithmetic in a sentence is not a census, so the inventory is now a table the conformance test reads. These bindings are configuration witnesses, not additional callers. The route-source and overlay predecessor URLs remain governed by the separate EVD-5 swap checker.
EVD-9’s caller-repoints.tsv must contain all EVD-HTTP-* IDs above. An active/configured row needs a target route and forcing receipt; a supported-but-stopped/on-demand/dormant row needs a named owner exclusion with the command/config evidence that makes it non-calling. “No old hostname in docker ps” is insufficient for a source-default or operator-invoked caller, and a zero direct-SQL count does not close any row in this section.
4.5 Reviewed predecessor-binding census (2026-09-12)
§4.4 says which caller must be repointed and why. This section says which literals still spell a predecessor origin, and it is the artefact EvidenceDirectHttpCallerConformanceTests reads: the test holds no census of its own, it parses the four tables below and fails when the repository disagrees with them. Adding or retiring a predecessor binding therefore means editing a reviewed document, not an array that no reviewer sees.
What reviewing a change here means. A new row in §4.5.2 or §4.5.4 must name an EVD-HTTP-* ID that exists in §4.4 and whose disposition still describes the caller; a row that leaves §4.5.2 must land in §4.5.3 with the sprint that retired it and the reason. The test enforces the measurable half — the surfaces, the markers, and that every cited ID exists in §4.4 — and refuses a retired key that is still set anywhere. Whether the disposition is still true is the human half, and it exists only because the rows are here.
4.5.1 Supported compose surfaces
| Surface | File |
|---|---|
canonical | devops/compose/docker-compose.stella-services.yml |
bundle | devops/release/bundle/docker-compose.yml |
bundle-pinned | devops/release/bundle/docker-compose.pinned.yml.template |
scanner | devops/compose/docker-compose.scanner.yml |
release-orchestrator | devops/compose/docker-compose.release-orchestrator.yml |
tester | devops/compose/docker-compose.tester.yml |
offlinekit | devops/compose/docker-compose.offlinekit-consolidated.yml |
bundle and bundle-pinned are generated from the canonical include chain, so a binding added to one of them by hand is drift; tools/scripts/validate/check-bundle-generated.sh owns that regeneration gate and exists because this census once compared three surfaces that had silently stopped agreeing about an entire retired service.
4.5.2 Active predecessor compose bindings
No supported compose surface selects a predecessor origin after the EVD-5 consumer repoint. Keys retained for configuration continuity now select Evidence and are measured in §4.5.5.
| Binding key | Compose service | Surfaces | Witnesses |
|---|
4.5.3 Retired predecessor compose bindings
A retired key must be set on no supported surface; the test asserts that, so this table cannot decay into a list of bindings that quietly came back.
| Binding key | Last set by | Retired | Retired under | Reason recorded at retirement |
|---|---|---|---|---|
ATTESTOR_EVIDENCELOCKER__BASEURL | attestor | 2026-09-05 | SPRINT_20260722_011 EVD-8/EVD-10b | Set only on the attestor compose key, which was deleted from the canonical stack and, by regeneration, from both release-bundle surfaces in the same change, so all three files still agree. The binding is not replaced on the successor: attestor__evidenceLocker__baseUrl binds to NOTHING on the consolidated host, because the Attestor half and the EvidenceLocker half are now one process over one database and there is no locker hop to configure. EvidenceConsolidationComposeConformanceTests pins that ABSENCE, so it cannot be re-added as inert configuration that reads like restored posture. EVD-HTTP-00 is unaffected: it was always about the route surface, not this key. |
findings__ledger__VexOverrideAttestation__AttestorBaseUrl | findings-ledger-web | 2026-08-27 | SPRINT_20260722_010 FND-10 | Set only on the findings-ledger-web compose key, and that key was deleted from the canonical stack and from both generated release-bundle surfaces in the same change, so all three files still agree. Compose-surface retirement only: the caller source VexOverrideAttestationOptions.cs is kept; EVD-5 now selects the Evidence origin, because findings-web composes that library. If the consolidated host is ever configured with an Attestor origin, the new binding name is added to §4.5.2 rather than this one being restored. EVD-HTTP-10 retains its live acceptance requirement. |
STELLAOPS_ATTESTOR_URL | platform | 2026-09-12 | SPRINT_20260722_011 EVD-5 | Unused Platform setting removed; the only configured owner is Evidence. |
STELLAOPS_EVIDENCELOCKER_URL | platform | 2026-09-12 | SPRINT_20260722_011 EVD-5 | Replaced by the canonical Evidence owner setting; predecessor resolver fallback removed. |
Excititor__Attestation__Attestor__BaseAddress | excititor-web | 2026-09-12 | SPRINT_20260722_011 EVD-5 | Census retirement catches up with withdrawn Excititor source/compose from the completed vulnerability consolidation. |
Excititor__Attestation__Rekor__BaseAddress | excititor-web | 2026-09-12 | SPRINT_20260722_011 EVD-5 | Same withdrawn host; no Rekor-v2 fallback retargeted. |
4.5.4 Production source predecessor literals
The scan covers production C# under src/, excluding tests and src/__Obsoleted. A file is listed because it still spells a predecessor host or config key; that is weaker than being a live caller, which is why the Witnesses column points at the §4.4 row that classifies it — EVD-HTTP-17 is listed here and is measured as making no call at all.
| Source file | Predecessor markers | Witnesses |
|---|---|---|
src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/Program.cs | STELLAOPS_ATTESTOR_URL | EVD-HTTP-16 |
src/Timeline/StellaOps.Timeline.WebService/Audit/UnifiedAuditContracts.cs | http://evidencelocker.stella-ops.local | EVD-HTTP-17 |
src/Timeline/StellaOps.Timeline.WebService/Program.cs | STELLAOPS_EVIDENCELOCKER_URL | EVD-HTTP-17 |
Four markers are recognised: the two predecessor hosts http://attestor.stella-ops.local and http://evidencelocker.stella-ops.local, and the two config keys STELLAOPS_ATTESTOR_URL and STELLAOPS_EVIDENCELOCKER_URL. A caller can be direct without spelling any of them, which is why §4.4 was built from typed HttpClient registration and route-literal tracing as well; this table pins only what a text scan can hold, and it is a floor under §4.4 rather than a substitute for it.
4.5.5 Consolidated caller origin bindings
EVD-5 retains these option names while changing their sole owner origin. Typed clients use native /api/evidence/v1/** paths. Policy’s unchanged verdict controller path is /internal/api/v1/attestations/verdict; it receives only an origin repoint.
EvidenceLocker__BaseUrl moved from export-web to offlinekit-web on 2026-09-13 (SPRINT_20260722_025 OK-10): the OfflineKit consolidation retired both ExportCenter roles and the consolidated host composes the same export domain. The ORIGIN is unchanged, which is the point of recording it here — a consolidation that quietly repointed a caller at a different Evidence owner is exactly what this census exists to catch. Its surface moves from canonical to offlinekit because the consolidated host is declared in that overlay; the overlay is on the flagship include chain, so bundle and bundle-pinned still generate from it.
| Binding key | Compose service | Surfaces | Origin |
|---|---|---|---|
EvidenceLocker__BaseUrl | offlinekit-web | offlinekit, bundle, bundle-pinned | http://evidence.stella-ops.local:8080 |
ReleaseOrchestrator__EvidenceSeal__BaseAddress | release-orchestrator | canonical, bundle, bundle-pinned, release-orchestrator | http://evidence.stella-ops.local:8080 |
SCANNER_SCANNER__SCANATTESTATION__ATTESTORBASEURL | scanner-web | canonical, bundle, bundle-pinned, scanner | http://evidence.stella-ops.local:8080 |
STELLAOPS_EVIDENCE_URL | platform | canonical, bundle, bundle-pinned | http://evidence.stella-ops.local:8080 |
Tester__EvidenceLocker__BaseAddress | stellaops-tester | tester | http://evidence.stella-ops.local:8080 |
VerdictAttestation__AttestorUrl | policy-engine | canonical, bundle, bundle-pinned | http://evidence.stella-ops.local:8080 |
5. What S1 adds (decision already DONE — owner approved the widened merge 2026-07-22)
EVD-2 is closed; the S0 review should confirm: (1) the module home (src/Evidence/), (2) the vex.trust_verdicts disposition (§2.3 — now a park-or-adopt decision, the mis-homing is dead wiring), (3) the two-migration-homes collapse (§2.4), (4) the closed Evidence SDK surface.
Inbound-caller inventory DONE (2026-08-03) — and it reshapes EVD-3. The register shows ~25 consumer keys pinned to attestor/evidence-locker/signer, but the witness chains route through a SMALL set of shared carrier libraries, not per-consumer type usage: StellaOps.Attestation (the dominant carrier — authority, notify, policy-engine, RO, scanner, sbomservice, signer, vexhub/vexlens all enter through it), Attestor.Envelope (platform, airgap, binaryindex), Attestor.ProofChain (concelier, export), Attestor.Core, EvidenceLocker.Core/Evidence.Pack (evidence side), Signer.Core/Signer.Infrastructure (signer side). The EVD-3 contract freeze is therefore a LIBRARY-CLASSIFICATION pass (which of these carriers are pure closed contracts, which drag implementation and must split) — not a per-caller type enumeration; classifying ~7 carriers collapses ~25 consumers’ pins. (Same shape as the 024 finding: pins concentrate on edges, not on types.) OWNER RULING (2026-08-03, review item A5): approved as the EVD-3 approach.
Historical route + deploy inventory (2026-08-03; superseded by the Evidence cutover): ~14 gateway routes (/api/v1/watchlist, /api/v1/transparency, six /api/v1/evidence/* shapes, /api/v1/proofs, /api/v1/verdicts, /api/v1/attestations, /api/v1/rekor) split across attestor.stella-ops.local and evidencelocker.stella-ops.local — plus /api/v2/evidence fronted by PLATFORM (a Platform read-model surface to keep, not a family route). At that inventory all six containers ran in the live main stack (attestor, tileproxy, signer, evidence-locker web+worker, tsa). The later EVD-9 window carried the data and APIs onto Evidence; the remaining consumer repoints retain their explicit runtime acceptance gates. Compose: tsa-data + capsule CAS volume rows per matrix §6.3; family env keys consolidate at S8 with the usual own-database gate.
