Timestamp Assurance — source-grounded information pack and proposed design

Status (2026-08-21): TA-1 (source-only) and TA-2 (read-only protocol adapters) are IMPLEMENTED; everything else remains PROPOSED and awaiting owner acceptance. This document answers owner-decision register item 14. It is an engineering recommendation, not an owner ruling and not a regulatory opinion. Still true after TA-2: no deployment, database, remediation, key-custody or product-claim change has been made — both libraries are referenced by no host, so nothing composes or executes them, and the adapters read no database (see §8 and §9). TA-2 does add code that CAN open a socket, which is why it lives in a separate assembly behind an explicit allowlist and a resolved-address policy. The executable proposal is SPRINT_20260819_001_Evidence_timestamp_assurance_program.md.

1. Recommendation

Make Timestamp Assurance a subsystem of the Evidence service family:

Do not create a Timestamping microservice, database, or central Doctor host. A separate service would either duplicate Evidence’s timestamp/token/trust state or reach across the Evidence boundary. JobEngine is also the wrong owner: it would need Evidence data, regulated trust inputs, tenant context, and privileged egress merely to schedule work in a domain it does not own. Platform should only discover and aggregate the service-owned check contract.

This recommendation follows the already-approved Evidence-family lifecycle: sign → attest → store → verify → timestamp. It is still proposed because item 14 has not accepted this disposition.

2. What exists now

2.1 The orphaned Doctor family

The project is src/Doctor/__Plugins/StellaOps.Doctor.Plugin.Timestamping/StellaOps.Doctor.Plugin.Timestamping.csproj. It targets .NET 10 and directly compiles:

The project defines its own local IDoctorCheck rather than the canonical IServiceDoctorCheck. The retired Doctor WebService adapted that private surface by reflection in DoctorMountedRuntimePluginLoader; it also owned seven dashboard endpoints under /api/v1/doctor/timestamping/* and mapped three heal actions. There is no direct WebService project reference to the plugin.

devops/build/package-runtime-plugins.ps1 still lists descriptor id stellaops.doctor.timestamping for base, recommended, harness, and bad-signature profiles. The generated descriptor is a runtime-bundle.v1 Doctor bundle with capability doctor:checks, an assembly digest, and detached signature. That packaging fact does not make the family runnable:

Therefore the measured runtime reachability of all 22 checks is zero. The bundle is a packaged orphan, not a live plugin.

2.2 The 22 checks, row by row

The canonical ids below are implemented as of TA-1 (2026-08-21) in StellaOps.Evidence.TimestampAssurance.Catalog, which is their single source of truth; the target surfaces remain proposed until TA-4. Every legacy id needs a compatibility alias during migration because the ids still occur in Doctor’s integration catalog/ratchets, AdvisoryAI’s doctor-search seed, unified-search fixtures, and Web E2E fixtures.

#Current legacy idWhat current code tries to measureProposed canonical idScope and target surfaceRequired real source
1check.timestamp.tsa.reachableconfigured TSA reachabilitydoctor.evidence.timestamp.tsa.reachableinstallation; /doctor/evidence/checksallowlisted RFC3161 endpoint probe
2check.timestamp.tsa.response-timeTSA response latencydoctor.evidence.timestamp.tsa.response-timeinstallation; /doctor/evidence/checkssame probe, monotonic duration
3check.timestamp.tsa.valid-responsevalid timestamp responsedoctor.evidence.timestamp.tsa.valid-responseinstallation; /doctor/evidence/checksnonce/imprint-correlated RFC3161 request/response
4check.timestamp.tsa.failover-readyusable backup TSAdoctor.evidence.timestamp.tsa.failover-readyinstallation; /doctor/evidence/checksconfigured provider set + read-only probes
5check.timestamp.tsa.cert-expiryTSA leaf expirydoctor.evidence.timestamp.tsa.cert-expiryinstallation; /doctor/evidence/checksparsed signer certificate from token/provider material
6check.timestamp.tsa.root-expirytrust-root expirydoctor.evidence.timestamp.tsa.root-expiryinstallation; /doctor/evidence/checksvalidated trust bundle, not configured dates
7check.timestamp.tsa.chain-validTSA chain validitydoctor.evidence.timestamp.tsa.chain-validinstallation; /doctor/evidence/checksreal chain build at the relevant verification time
8check.timestamp.ocsp.responderOCSP responder availabilitydoctor.evidence.timestamp.revocation.ocsp-responderinstallation; /doctor/evidence/checkscertificate-derived OCSP request/verified response
9check.timestamp.crl.distributionCRL distribution availabilitydoctor.evidence.timestamp.revocation.crl-distributioninstallation; /doctor/evidence/checkscertificate-derived URI + signed CRL validation
10check.timestamp.revocation.cache-freshcached OCSP/CRL freshnessdoctor.evidence.timestamp.revocation.cache-freshinstallation; /doctor/evidence/checksEvidence-owned validated snapshot metadata
11check.timestamp.ocsp.staplingstapled revocation evidence posturedoctor.evidence.timestamp.revocation.stapling-presentinstallation; /doctor/evidence/checkscurrent issuance/profile policy + captured evidence summary
12check.timestamp.evidence.stalenessstale timestamp evidencedoctor.evidence.timestamp.evidence.stalenesstenant; Evidence Timestamp Assurance APItenant-RLS timestamp inventory
13check.timestamp.evidence.tst.expirytokens approaching certificate expirydoctor.evidence.timestamp.evidence.token-expirytenant; Evidence Timestamp Assurance APIparsed token/certificate validity, tenant scoped
14check.timestamp.evidence.tst.deprecated-algodeprecated imprint/signature algorithmsdoctor.evidence.timestamp.evidence.deprecated-algorithmtenant; Evidence Timestamp Assurance APIparsed token algorithms + approved policy catalog
15check.timestamp.evidence.tst.missing-staplingtimestamp evidence without OCSP/CRL materialdoctor.evidence.timestamp.evidence.missing-staplingtenant; Evidence Timestamp Assurance APItenant-RLS token/evidence metadata
16check.timestamp.evidence.retimestamp.pendingoverdue re-timestamp workdoctor.evidence.timestamp.evidence.retimestamp-pendingtenant; Evidence Timestamp Assurance APIidempotent Evidence-owned work queue
17check.timestamp.eidas.trustlist.freshEU trusted-list freshnessdoctor.evidence.timestamp.eidas.trust-list-freshinstallation; /doctor/evidence/checksvalidated signed trust-material pack and provenance
18check.timestamp.eidas.qts.qualifiedconfigured TSA qualified statusdoctor.evidence.timestamp.eidas.qualified-statusinstallation; /doctor/evidence/checksCryptography plugin result + the three gates (§11)
19check.timestamp.eidas.qts.status-changerecent qualified-status changesdoctor.evidence.timestamp.eidas.status-changeinstallation; /doctor/evidence/checkssuccessive validated trust snapshots
20check.timestamp.timesync.systemsystem/NTP skewdoctor.evidence.timestamp.time.system-syncinstallation; /doctor/evidence/checksallowlisted time source or sealed NTP proof
21check.timestamp.timesync.tsa-skewTSA time versus system timedoctor.evidence.timestamp.time.tsa-skewinstallation; /doctor/evidence/checksparsed TST generation time + monotonic request bounds
22check.timestamp.timesync.rekor-correlationTST/Rekor chronologydoctor.evidence.timestamp.time.rekor-correlationinstallation; /doctor/evidence/checksEvidence-owned attestation/transparency metadata

That is a deliberate 17 installation + 5 tenant split. The current ServiceDoctorContext has no tenant identity and evidence-web uses forced RLS, so registering the five tenant rows as ordinary service checks would invite either false-green results or an unsafe cross-tenant query. evidence-worker should evaluate them under an explicit tenant scope and the tenant-authenticated Evidence API should return their detail. /doctor/evidence/checks may report only a bounded, redacted installation summary such as affected-tenant count; it must never expose tenant ids, token bytes, or cross-tenant rows.

2.3 What the Doctor implementation actually does

The family is broader on paper than in composition:

The test project covers deterministic evaluator logic, registrations, synthetic offline files, and the gated-remediation plumbing. It does not prove a live TSA round trip, production Evidence data, signed LOTL/member-state TSL validation, complete OCSP/CRL verification, qualified status, durable scheduling, or production remediation.

2.4 Real timestamp issuance is already in EvidenceLocker

This must not be confused with the dead Doctor façade. The live predecessor evidence-locker-web currently:

  1. hashes the bundle signature;
  2. builds a nonce-bearing RFC3161 request with BouncyCastle;
  3. POSTs application/timestamp-query;
  4. validates the response against the request;
  5. requires an accepted response status and token; and
  6. stores timestamp time, authority, and raw token in evidence_bundle_signatures.

TimeStampResponse.Validate(request) proves request/response correlation (including the expected imprint/nonce contract); it is not full verification of the token signer’s certificate chain, trust anchor, timestamping EKU, or revocation status. Those remain target work in TA-2.

Outside the local harness, startup fails closed if timestamping is disabled or the endpoint is missing. Compose configures http://tsa.stella-ops.local:318/ and RequireTimestamp=true. The tsa role wraps openssl ts -reply, has no database, exposes no host port, and keeps its cert, private key, serial, and index under the tsa-data volume. Development self-provisions clearly labelled non-production material; production requires operator-provisioned material.

The assurance subsystem must reuse/re-author that real issuance, correlation, accepted-status, and token-storage path. It must then add full token signature, signer-chain/trust, timestamping-EKU, and revocation verification as separately tested target behavior. It must not replace either layer with the Doctor HEAD probe or any placeholder library.

2.5 Other timestamp code is useful evidence, not proof of production support

SourceCurrent measured statusDurable disposition
StellaOps.Attestor.TimestampingParses CMS/TSTInfo, checks imprint, signature, timestamping EKU, offline chain and Rekor time correlation; its issuance method always throws because no TSA transport is configured. Production consumers: CLI only; tests otherwise.Re-author verified pure parsing/evaluator logic inside Evidence; remove the CLI source edge through a closed Evidence API/SDK seam.
StellaOps.Attestor.Infrastructure/Timestamping/TsaMultiProvider.csNo call sites. Builds a raw SHA-256 payload instead of RFC3161 and treats response bytes/time-now as a parsed response.Do not carry.
StellaOps.EvidenceLocker.TimestampingSolution-only, zero production project consumers. Repository targets legacy evidence.timestamp_tokens/revocation_snapshots; those tables are absent from the consolidated Evidence baseline, have no tenant id, and exist only in a central pre-1.0 migration. Expiry is a three-year generation-time proxy; OCSP/CRL verification is parse-only.Do not wire or mechanically port. Use its bundle/retimestamp vocabulary only as an inventory input.
StellaOps.Cryptography.Plugin.EidasContains trust-list parsing/signature checking, qualified timestamp verification, sealed fixture packs, and fail-closed runtime claim gates. It also contains incomplete/heuristic paths. Shipped runtime YAML does not enable a live public endpoint by default, although the library configuration type still carries an EU LOTL URL default.Consume only through the existing cryptography plugin contract/result boundary; never compile its implementation into Evidence.
StellaOps.AirGap.Time / AirGap ImporterContains offline RFC3161/trust-material experiments but is dark/unrouted and belongs to the OfflineKit consolidation/retirement path.OfflineKit transports a versioned artifact; Evidence owns validation. No source reference.

2.6 Existing Evidence doctor checks do not overlap

The not-yet-live evidence-web skeleton already registers the three standard database checks plus five family checks:

Those checks measure database and evidence-spine invariants. None measures RFC3161 issuance, timestamp-token validity/expiry, TSA/trust/revocation state, or time correlation. Timestamp Assurance extends this family; it does not replace or duplicate those eight checks.

3. Proposed runtime and contract boundary

3.1 API surfaces

IMPLEMENTED 2026-09-07 (TA-4) — this table is the contract as it ships, verified against src/Evidence/StellaOps.Evidence.WebService/TimestampAssurance/TimestampAssuranceEndpoints.cs and pinned by EvidenceRouteInventoryTests (fixture consolidated-route-inventory.tsv). Scopes are the existing catalog scopes; no new scope name was needed.

SurfaceScopePurpose
GET /doctor/evidence/checksinstallation, ops.healthThe 17 installation checks beside the family’s eight, through doctor-check/v1; deterministic envelope, measured values and pointers only. No tenant row is read.
GET /api/evidence/v1/timestamp-assurance/statusevidence:read (caller’s tenant)The latest durable run’s five tenant results plus a bounded installation posture (sources configured, provider count, check count) and the closed-gate notice.
POST /api/evidence/v1/timestamp-assurance/runsevidence:create (caller’s tenant)Evaluate the five tenant checks over the caller’s stored tokens and re-timestamp queue NOW and record the run durably (evidence.timestamp_assurance_runs/_results). Idempotent on idempotencyKey; the run id is derived from tenant + key. No network probe: tenant runs read stored evidence only.
GET /api/evidence/v1/timestamp-assurance/runs/{runId}evidence:read (caller’s tenant)One durable run; another tenant’s run is 404 by row-level security, not by filter.
GET /api/evidence/v1/timestamp-assurance/providersinstallation, ops.healthProvider ids, endpoint hosts, requirement, plaintext posture and whether a credential reference is configured — never a credential, never an endpoint URL with user info.
GET /api/evidence/v1/timestamp-assurance/evidence/{bundleId}evidence:read (bundle’s tenant)One capsule’s parsed token facts (genTime, imprint/signature OIDs, signer expiry, revocation-material presence) and its local evidentiary classification: technical state indeterminate with reasons named, regime not claimed, every gate closed, validation basis local-validation-against:<pack>@sha256:… (pack none when no trust-anchor bundle is configured). Carries the §1.E disclaimer verbatim.

The API takes tenant identity from the verified request context only — the tenant claim resolved through the family’s catalog replica, exactly as every Locker route — and reads no query or body tenant. Every payload carrying a classification carries TimestampClaimWording.RequiredDisclaimer verbatim; every payload carries the product-wide closed-gate notice while the operator claim gate is closed; the emitted-text guard (TimestampClaimWording.FindForbidden) is asserted over every payload by TimestampAssuranceApiTests.

3.2 Events and plugins

3.3 Privilege and network isolation

4. Online, sealed, degraded, and scheduling semantics

4.1 Online

4.2 Sealed/offline

4.3 Schedules

IMPLEMENTED 2026-08-22 (TA-5) as StellaOps.Evidence.TimestampAssurance.Scheduling; COMPOSED into evidence-worker 2026-09-07 (TA-5, §13). The seven intervals below are carried VERBATIM into TimestampSchedulePlan.DesignDefaults and pinned one-per-interval by test, following D-TA-8’s reasoning: the rehome already changes where checks run and what feeds them, and changing the cadence at the same time would make any behaviour difference unattributable. Jitter (a tenth of the interval, subtractive only) and backoff (one minute, doubling, clamped to the interval) are TA-5’s additions, not the design’s.

All schedules are worker-owned, configurable, jittered, single-flight, and fenced. Safe defaults (subject to acceptance testing):

On-demand calls coalesce with an in-flight scheduled run. A failed source never causes a tight retry loop; exponential backoff is bounded by the next normal schedule.

How those two sentences are enforced, and why it takes two mechanisms. The LEASE (ITimestampScheduleLeaseSource, implemented over a PostgreSQL session advisory lock on the family’s own database) is cross-replica single-flight — on a two-role family where web and worker host the same loop, it is the only thing stopping two processes probing the same TSA. COALESCING is in-process: an on-demand caller that merely failed to take the lease would get NotLeader and no answer, when the answer it wants is being computed in the same process. Ordering is coalesce, then lease, then the P7 writer budget — the budget bounds WRITES, so a run that never happened because another replica held the lease must not spend a unit of it.

Backoff is CLAMPED to the interval, and the clamp is the contract rather than a safety net. An unbounded backoff eventually stops reporting on exactly the source that is broken, and the health output goes quiet rather than red.

Replay-safety is deliberately NOT in the scheduler. A lease bounds concurrency; it cannot make a run that already committed harmless to repeat, because the retry may happen minutes later on another replica with the lease legitimately free. That guard is the content key on evidence.timestamp_assurance_runs — the UNIQUE (tenant_id, idempotency_key) TA-3 added and documented as “the replay guard”.

5. State, migrations, retention, and evidence

5.1 Database and object ownership

No new database. If implementation proves durable state is required, it belongs in stellaops_evidence and auto-migrates from embedded forward-only Evidence migrations. Proposed logical state (names are design labels, not approved DDL):

Raw timestamp tokens already stored with evidence bundles are not duplicated. Large trust lists, certificate chains, OCSP/CRL snapshots, and proof bundles live content-addressed in an Evidence-owned object prefix; PostgreSQL stores digest, media type, size, validity, provenance, and reader keys.

5.2 ADR-039 implications

6. Compatibility, rollout, rollback, and observability

6.1 Compatibility

6.2 Rollout and rollback

  1. Land a source-only catalog/evaluator slice in the idle Evidence tree; no host wiring. DONE 2026-08-21 (TA-1) — see §8.
  2. Add real read-only adapters and red-proof every unavailable/error branch.
  3. Compose into evidence-web/evidence-worker only after the Evidence API/cutover program permits it; registration stays default-off.
  4. Shadow-run against current EvidenceLocker/TSA without changing issuance, compare results, and record divergences.
  5. Enable read-only installation checks, then tenant evaluations.
  6. Enable durable scheduling. Remediation remains disabled until its own gate is complete.
  7. Stop packaging the orphan bundle and retire legacy source only after all consumers and ids have migrated and parity is proven.

Rollback disables registration/scheduling and returns to the prior Evidence issuance path. It does not roll back migrations; recovery follows ADR-004 forward-only rules. No step changes TSA or Signer key custody, so rollback never moves private material.

6.3 Observability and security acceptance

7. What local source proves, and what it does not

Locally provedNot proved; validation still required
The Doctor family has 22 registrations and zero runtime host after doctor-web retirement.That the 22 checks are legally sufficient for any jurisdiction or certification.
EvidenceLocker currently performs real RFC3161 request/response correlation, requires an accepted response with a token, stores it, and requires a TSA in non-harness mode.Full signer-chain/trust/EKU/revocation verification by that issuance client, or that the development OpenSSL TSA/any operator certificate is a qualified TSA/QTSP.
The eIDAS plugin can technically parse/verify configured material and its claim gate denies affirmative qualified-service claims without the pack/agreement conditions.Whether any particular deployment’s provider, exact service, jurisdiction and agreement satisfy the three gates — counsel ruled on the RULES (§11), not on any deployment’s facts. No external regulatory research was performed by engineering.
The consolidated Evidence model stores bundle timestamp metadata and enforces forced tenant RLS/legal holds.Exact regulatory retention periods or whether every OCSP/CRL/trust snapshot must be retained.
Signer is a separately approved custody boundary and the TSA has its own key volume.Any authority to move, share, or reuse either private-key population. This proposal explicitly does not.

The legal/claim question was put to counsel and answered on 2026-08-23; §11 carries the ruling and is authoritative over any wording earlier in this document. In short: Stella Ops never describes itself as providing a qualified trust service, and it may describe a specific token as an EU qualified electronic time stamp at issuance only under an approved provider/service/jurisdiction/ deployment claim profile that passes all three gates. No such profile exists, so the positive path is unreachable today by construction rather than by policy.

8. First safe implementation slice — LANDED 2026-08-21 (TA-1)

The source-only slice is implemented. What exists:

PathWhat it holds
src/Evidence/__Libraries/StellaOps.Evidence.TimestampAssurance/Catalog/The 22-row catalog: legacy id, canonical id, scope, category, default severity, surface, what it measures, and the real source it may not report without. Alias resolution both ways lives here and nowhere else.
.../Evaluation/TimestampSource.csThe availability wrapper plus the stable unavailable-reason codes.
.../Evaluation/TimestampAssuranceVerdict.csThe verdict type and Match, which short-circuits before an evaluator body can run without an observation.
.../Evaluation/TimestampObservations.csThe explicit input records — every field a measurement, none fillable from configuration.
.../Evaluation/TimestampAssurancePolicy.csThe legacy-compatible thresholds, transcribed from the orphaned Doctor options so the rehome changes ids and sources without changing when an operator is paged.
.../Evaluation/TimestampAssuranceEvaluators.csThe 17 deterministic installation evaluators.
.../Checks/ITimestampAssuranceSources (the read port), UnavailableTimestampAssuranceSources (the TA-1 default: every source unavailable), and the 17 IServiceDoctorCheck types.
src/Evidence/__Tests/StellaOps.Evidence.TimestampAssurance.Tests/98 tests: catalog conformance, the false-green ratchet, per-evaluator happy/malformed branches, determinism, and the structural inertness proofs.

What is deliberately absent, and is TA-2/TA-3/TA-4 work:

The slice is independent of owner/legal claim approval and safe before the Evidence live cutover because nothing can execute it. The qualified-status evaluator is where that separation is visible: a passing technical verdict with the TA-6 gate closed reports technical validation only in wording pinned verbatim by test, and never asserts a qualified timestamping service claim.

9. Read-only protocol adapters — LANDED 2026-08-21 (TA-2)

StellaOps.Evidence.TimestampAssurance.Adapters supplies the six observations TA-2’s criteria name. It is a separate assembly from the TA-1 core on purpose: everything that can open a socket lives here, so the core’s runtime assertion that its only non-BCL reference is the shared doctor contract survives unchanged, and a future edit that gives the core an HTTP dependency fails the core’s own test.

AdapterLegacy placeholder it replacesWhat it now measures
Rfc3161/Rfc3161ProbeClientHTTP HEAD/OPTIONS and the unavailable TSA clientA real nonce-bearing RFC3161 exchange. Status, token presence, nonce match and imprint match are measured separately, so the check can name which one failed; TimeStampResponse.Validate runs as an independent cross-check and a disagreement between the two is itself reported.
Certificates/CertificateChainInspectorthe configured ExpiresAt dateValidity, signature algorithm and SHA-256 thumbprint parsed from DER; a real chain build at a stated verification time against the operator’s anchors; id-kp-timeStamping presence and criticality (RFC 3161 §2.3).
Revocation/OcspProbean HTTP probe of a configured URIA request built from the certificate’s own AIA, with the response’s signature, CertID equality, status and validity window each verified. Delegated responders are accepted only when the issuer certified them with id-kp-OCSPSigning.
Revocation/CrlProbeparse-onlyA CRL fetched from the certificate’s own distribution point, signature-verified against the issuer, checked for the subject’s serial and for a current nextUpdate.

9.1 The egress control, and why IEgressPolicy is not it

IEgressPolicy is used as the estate’s sealed-mode gate and nothing more. Read before assuming: EgressPolicy.Evaluate opens with if (!IsSealed) return EgressDecision.Allowed;, so on an unsealed installation it permits every destination unconditionally; its IsLoopback/IsPrivateNetwork helpers are allow-list widenings inside sealed mode, and both classify by host string, so a host that is a name is never recognised as private.

That gap matters here more than anywhere else in the estate, because two of the four adapters fetch URLs chosen by whoever issued the certificate. TimestampEgressGuard therefore owns the SSRF half outright, in this order: scheme → explicit host allowlist (no wildcards, applied in every mode, and applied to certificate-derived destinations too) → sealed-mode gate → DNS resolved here with every resolved address vetted → the connection pinned to a vetted address so the name cannot be re-resolved between check and connect → redirects refused rather than followed, bytes-read capped (never a declared Content-Length), one budget over the whole sequence.

X509Chain is built with RevocationMode = NoCheck as a security choice: it does its own AIA/OCSP/CRL fetching on its own HTTP stack, which would bypass the allowlist, the address policy and the sealed gate entirely.

9.2 What TA-2 deliberately does not supply

Nine of the fifteen port reads still return source-not-configured, each naming the task that will supply it: the revocation-snapshot cache, the stapling summary and transparency correlation need Evidence-owned state (TA-3); the trusted-list pack needs the signed timestamp-trust-bundle/v1 artifact and the NTP proof needs its sealed form (TA-5); qualified status needs the Cryptography plugin ABI and the owner/legal claim gate (TA-6). A partially wired adapter that returned a plausible observation instead would be the exact false green this program exists to retire, so the honest unavailable is the correct output rather than a gap.

The trust anchors TA-2 uses are an operator-supplied PEM bundle, recorded by digest. TA-5 replaces the transport with a signature-verified content-addressed pack; the parsing and chain building do not change. Because that bundle is unsigned operator material, eidas.trust-list-fresh continues to report unavailable rather than reporting on it.

10. Evidence-owned state — DELIVERED SLICE 2026-08-25 (remaining TA-3 work is pending)

002_timestamp_assurance.sql adds four tables to the family’s own evidence schema, inside the existing stellaops_evidence database. After TA-6 supplied counsel’s disposition, 003_timestamp_assurance_reproducibility.sql adds the reproducible-result, exact-snapshot, retention and legal-hold dependency state that 002 correctly refused to guess. Migration 002 is applied history and was not edited. This slice covers parsed-token conclusions; counsel §7’s pre-token failed-probe evidence remains the explicit gap in §10.4. No new deployable and no new database.

§5.1 candidateVerdictReason
bounded run/result summariesADDEDtimestamp_assurance_runs, timestamp_assurance_resultsOnly the five TENANT results are stored. Installation results are not: the 17 are pure functions over live probes served pull-based, and doctor-check/v1 carries no timestamp by contract, so a stored copy holds nothing a re-run cannot produce while being able to contradict it. The runs table is kept for the TA-5 replay guard, not for normalisation.
idempotent re-timestamp work itemsADDEDtimestamp_retimestamp_queue…evidence.retimestamp-pending counts overdue work; you cannot count work that was never recorded.
immutable observation/audit pointersADDEDtimestamp_reissuesOn a measured constraint: evidence_bundle_signatures is PRIMARY KEY (bundle_id, tenant_id), one row per bundle, so a successor written there would OVERWRITE the original that criterion 5 requires preserved.
provider/trust metadata and content digestsADDED BY FORWARD MIGRATION 003 after TA-6timestamp_assurance_objects, timestamp_trust_snapshots, timestamp_snapshot_authentication, timestamp_qualification_results, result dependency tables, retention profiles and exact hold pinsCounsel §§4/7/9 now define the exact retained material, R, supersession and reproducibility rules. The earlier refusal remains in migration 002 as the correct historical decision; 003 is its forward-only successor.

10.1 Why the successor table is not a second TST representation

§5.1 says raw timestamp tokens already stored with evidence bundles are not duplicated, and that still holds exactly. timestamp_reissues never reads, copies or modifies evidence_bundle_signatures; a successor is new material from a later exchange, and the row stores a content-addressed pointer plus bounded metadata rather than token bytes. The original row is what the table exists to avoid overwriting, and a test reads it back byte for byte after two successors are appended.

10.2 Invariants the DATABASE enforces, not the application

10.3 Counsel-disposed reproducibility state (migration 003)

10.4 §7 failed-probe evidence (gap closed by migration 004, 2026-09-02)

Counsel requires a failed active probe’s raw request/response, headers and parser/transport error to survive through incident closure and the failed-run audit period, for R when it influenced a retained decision, and under a release/incident hold. Migrations 002/003 could not represent a pre-token failure (a qualification result requires timestamp_token_object_id and gen_time; 002’s doctor-result JSON is derived/rebuildable with no content-object or hold edge). 004_timestamp_failed_probe_observations supplies the state: an append-only timestamp_failed_probe_observations row per failed attempt (failure taxonomy, bounded error detail, retention-profile linkage, decision_relevant requiring a linked retained result) whose raw request/response/header bytes are content-addressed capture objects (probe-request/probe-response/probe-response-headers kinds) referenced through kind-validated, role-unique edges that the object-deletion blockers count; the existing timestamp_object_hold_pins path pins them under a release/incident hold. The TA-4/TA-5 runtime boundary is unchanged: no writer is composed into a host, so no host may yet CLAIM live failed-probe retention - the schema and its Testcontainers proofs are executable now.

10.5 Runtime boundary still owed

No object-store writer or qualification-result writer is composed into a host (TA-4 and TA-5 both declined to add one: with every claim gate closed the only classification that exists is indeterminate, D-TA-28). Whichever row can open a gate must add the fail-closed byte-capacity check named by the P16 registry before the first object write. The schema and acceptance tests are executable now; they do not claim the standing estate uses them. The worker-owned schedules (§13) write only the two things TA-3 already modelled — tenant run rows and PENDING queue rows.

11. The counsel disposition — what may be SAID and what must be RETAINED (TA-6, 2026-08-23)

Source of record: timestamp-assurance-counsel-thread-claims-trust-and-retention-reply.md. Disposition: APPROVED WITH CONDITIONS — the qualified-claim gate remains CLOSED by default. This section is authoritative over any wording earlier in this document.

11.1 THREE gates, not two

The two-gate model this design and its counsel inquiry both proposed is replaced:

GateAnswersImplemented as
1 — technical verificationDoes the token parse, correlate, verify and chain?TimestampQualificationInputs.TechnicalState (passed / failed / indeterminate)
2 — regulatory classificationWas the EXACT service qualified at genTime?RegulatoryClassificationEvidenceregulatory_gate
3 — rights and claim publicationMay we SAY so?TimestampClaimProfilerights_gate

operator_claim_gate opens only when all three pass and an approved claim-text version exists. The separation is not cosmetic: folding gate 3 into gate 1 is how “the owner/legal claim gate is approved” ended up in an operator-facing sentence — an internal approval presented as evidence of qualification, which is now a prohibited expression.

11.2 indeterminate is the answer to absence

Missing, stale, ambiguous or disputed evidence produces indeterminate— never not-qualified, and never a warning-only positive. not-qualified requires affirmative contrary evidence: a signature-verified, in-date trusted list whose status history covers genTime, with the token signer mapped onto the listed service, saying so. There is no post-expiry grace period; the 3-day / 7-day product windows play no part in the gate.

§8 of the disposition names four conditions that may degrade to a warning (all future-risk) and seven that may not. Both lists are a closed enum, TimestampAssuranceCondition, with no default arm: an unclassified condition throws rather than defaulting to warnable.

11.3 Approved wording, verbatim

TimestampClaimWording carries wordings A–E, the UK sentence, the historical sentence, the seven prohibited expressions and the sentences this disposition superseded. Every string is asserted character-for-character against the disposition document on every test run, and an emitted-text guard scans every check message and every evidence value for a prohibited or superseded expression.

Two honest gaps, recorded rather than papered over: counsel approved no operator-facing wording for a not-qualified outcome, and none for the EEA-country-profile or third-country-equivalent regimes. Those outcomes emit no prose at all — the machine-readable fields carry the result and approved-claim-wording-unavailable says why. Inventing regulated claim text would be the D-TA-10 defect repeated.

11.4 Machine-readable state

Ten fields, counsel’s own names, exported by TimestampQualificationClassification.Fields(): technical_state, qualification_regime, qualified_status_at_issuance, current_service_status, regulatory_gate, rights_gate, operator_claim_gate, validation_basis, reason_codes, claim_profile_id. The validation basis is local-validation-against:<operator-pack-id>@sha256:<digest>; claimed-against: and bare validated-against: were rejected by name and the parser refuses both. Every state enum’s default member is its conservative value, so a skipped field lands on indeterminate / closed / not-checked / none rather than on a positive.

11.5 What this does NOT change

No runtime, deployment or distribution gate. TA-3 adds forward-only database state but composes no writer into a host (TA-4 is gated on EVD-5/EVD-9), and no claim profile exists anywhere, so the positive path is unreachable by construction — which is exactly counsel’s implementation gate: “No positive qualified-status output may ship until a concrete provider/service/jurisdiction/deployment claim profile passes all three gates.”

12. Tenant API and installation composition — LANDED 2026-09-07 (TA-4)

What §3.1 proposed now runs in evidence-web; what §10.5 owed is discharged for the tenant half.

13. Sealed seam and schedules composed — LANDED 2026-09-07 (TA-5)

What §4.2 and §4.3 owed a host now has one, and both Evidence roles compose it from the same configuration through the family’s StellaOps.Evidence.TimestampAssurance.Hosting assembly.

14. Consumer cutover — LANDED 2026-09-07 (TA-8)

Every consumer of the Timestamp Assurance checks names the canonical doctor.evidence.timestamp.* id.