Unattributed witness custody
Source verified against
a2cbb07a51c74c30d367aefd7f8ad0c506bbbc28on 2026-10-13, including the algorithm-identity audit repair that supersedes the unapproved v1 proposal. Re-verify with the persistenceWitnessCustodyMigrationTestssuite and the Storage/WebService witness tenant-isolation suites. Live custody transfer is a separate approval and acceptance step.
CCP-075 adds 012a_preserve_unattributed_witnesses.sql before the unchanged 013_tenant_qualify_witnesses.sql and 014_witness_scan_id_text.sql. The owning authority is Scanner’s embedded startup chain. Re-verify with WitnessCustodyMigrationTests and ScannerSchemaTopology.OwnedMigrations.
The prerequisite selects an unqualified witness only when its exact scan id has no unique normalized owner in scanner.scan_runtime_state. It never uses the number of tenants elsewhere in the database as attribution. An already-qualified row or unique exact scan match remains active. Fresh databases and databases already through 014 need no custody approval when the selected set is empty.
What is preserved
scanner.witness_quarantine holds every original parent field in source_record, the original source column metadata, an explicit digest_algorithm, a content digest, transfer manifest digest, reason, approval reference, operator identity, database session identity and preservation time. scanner.witness_verification_quarantine holds every original verification field and identifier plus its exact digest algorithm, with a foreign key to the preserved parent. Original timestamps, UUIDs, payload and envelope values remain unchanged. JSONB retains its stored values; this does not reconstruct lexical JSON bytes discarded when the original JSONB was written.
The transfer fences writes to runtime ownership, parents and children in the runner’s transaction. It checks exact parent and child sets and source schema, rejects conflicting preserved records, copies missing identical records, verifies field equality and counts, and only then removes those children and parents from the active tables. The active verification foreign key is neither dropped nor redirected. An unknown incoming foreign key refuses the transfer. All work in 012a, including its ledger receipt, rolls back together on failure.
The custody tables have no TTL or automatic purge. Updates and deletes are refused by immutable-history triggers. Normal witness repositories read only the active tables; quarantine is excluded from id/hash/scan/CVE/graph reads, signing updates and verification. There is no quarantine HTTP API. Preserving a DSSE-shaped value does not validate its signature, supply a missing signed payload, or establish ownership.
The reviewed one-shot transfer is limited to 10,000 selected parents. A larger set is refused intact and requires a separately reviewed capacity plan; it is never truncated to the limit.
Manifest and read-only preflight
Use the qualified Scanner web candidate’s existing --migrate-only invocation, with Scanner__WitnessCustody__PreflightOnly=true. Supply the canonical STELLAOPS_POSTGRES_SCANNER_CONNECTION through the existing secret pointer. The command checks that it reaches stellaops_scanner as the least-privilege scanner role, then reads a repeatable-read, read-only snapshot. It starts no web listener or worker, and creates no migration ledger or custody table. The output lists the witness IDs, verification counts, per-record content digests and manifest digest; payloads, envelopes and connection strings are not printed.
Digest contract scanner-witness-custody-v2 supersedes the unapproved v1 proposal. The earlier v1 manifest is not a valid approval for this contract; no v1 custody transfer was applied to the live database.
- PostgreSQL renders
to_jsonbparent/child rows under UTC andDateStyle=ISO,YMD. Rows are ordered by witness UUID, children by verification UUID, and source columns by table and ordinal position. The source schema covers both tables. - The shared
CanonJsoncanonicalizer serializes an envelope containing the format, exact algorithm identifier, and base64 UTF-8 source-schema, parent and ordered-child JSONB snapshots. Base64 keeps exact original Unicode and numeric values outside the canonicalizer’s normalization. Stored JSONB is never replaced by canonical JSON. - Creation captures
ICryptoHash.GetAlgorithmForPurpose(HashPurpose.Content)once, including the active compliance profile and configured purpose override. The same central abstraction hashes with that explicit algorithm, recorded on each parent and child and bound inside both digest envelopes. The digest string is the exact lowercase algorithm identifier followed by a colon and the central library’s hex digest, for examplesha512:<hex>. It does not use a profile-only prefix alias. No signing key is used or generated. - The manifest binds the format, exact algorithm and ordered witness IDs, content digests and verification counts. It is canonicalized and hashed through the same libraries. A changed source row, child, source column definition, or hash profile requires a new preflight and approval. External forensic SHA256 measurements are not substitutes for this manifest.
- Historical replay uses each preserved parent’s algorithm through the central explicit-algorithm operation and checks the children’s recorded algorithm and digests. Changing the current creation profile or purpose override does not rewrite or invalidate unchanged historical custody. Blank, noncanonical, unsupported or mismatched algorithm metadata and changed evidence fail closed; replay never substitutes the current algorithm or reseals a record.
Candidate qualification and approved migration window
Complete candidate qualification, exact read-only inventory and a usable forward recovery package before requesting approval of the live custody transfer. The deployment owner must then approve the tested policy and exact manifest before fencing or changing live services. Source audit and candidate-build authorization do not authorize a live custody transfer.
- Qualify clean-source Scanner web and worker images together, including plugin cohorts and source binding. Record a usable database recovery point, exact outgoing images and compatible forward-recovery images. Check disk and live Compose chains. Record actual qualified image/cohort identities and their validation results; planned build commands are not qualification. Resolve the sanctioned Scanner signing identity through the existing operator path; do not silently consume a test seed or substitute another module’s key contract.
- After explicit live approval, acquire the deployment owner’s window lock and fence both Scanner hosts and every Scanner writer. Re-run read-only preflight after fencing. Compare every ID, child count and digest to the approved set.
- Run
--migrate-onlywith preflight mode disabled and these settings supplied only to the one-shot process:Scanner__WitnessCustody__ApprovedManifest,Scanner__WitnessCustody__ApprovalReference, andScanner__WitnessCustody__Actor. Values are the exact approved manifest digest, durable approval evidence reference, and accountable operator identity. Do not put approval settings in standing web or worker environments. - The migration-only command uses the same
StartupMigrationHostas ordinary startup, with a Scanner-owned transaction executor. Under its write fence it regenerates the inventory, compares the approval, supplies exact field snapshots and shared-library digests, and executes the immutable SQL. Normal startup has no custody executor and refuses any nonempty transfer set. Migration-only replay also validates retained parent/child digests when 012a is already in the ledger; it refuses corruption instead of hiding it behind an idempotent insert. - Confirm 012a, 013 and 014 ledger entries in order, with unchanged 013 checksum
8852994ce1c463df602addc0c2f8adbe9482e3d49d4b82f95207ef8ac267e657and 014 checksuma137430398925e60677bd90aede9a2ad0899979baa4189c2d2a9c061ce0a5b11. Check parent/child conservation, preserved digests, active tenant constraints, text scan IDs and foreign keys before admitting compatible hosts. - Perform the sanctioned positive scan and owner/second-tenant read/sign/verify forcing checks. CCP-059 and CCP-060 cite that same evidence. Empty lists or healthy containers do not meet those criteria.
Forward recovery
Each migration commits separately. If 012a fails, its custody changes and ledger entry roll back; compare the active inventory before restarting the previous cohort. If 012a commits and 013 or 014 fails, leave writers fenced, verify preserved custody and resume the qualified migration-only chain after resolving the failure. Do not copy quarantine back or infer a tenant to bypass a migration.
After 014 commits, a web image expecting UUID scan IDs is incompatible even when health checks pass. An old-image-only rollback is unsafe. Use the prequalified schema-compatible web/worker pair or a reviewed forward repair; preserve all custody and migration receipts. A full database recovery-point restore is a separate operator-authorized recovery action covering the entire database, both hosts and writes since the recovery point. It is not a routine image rollback.
Independently evidenced operator resolution
Resolution is a separate operator action, through the owning database maintenance session; the application exposes no operation for it. First establish ownership from independent evidence, such as a retained source scan record or authenticated historical backup. A payload tenant string, signature metadata, or an operator’s guess is insufficient. Revalidate the preserved digest using migration-only replay.
In a transaction, insert one scanner.witness_custody_resolutions row naming the exact witness_id, preserved_digest, independently established normalized tenant_id, durable evidence_reference, resolved_by, and UTC resolved_at. The database also records session_user. Its foreign key binds the exact preserved identity/digest; its primary key prevents reusing an evidence reference for that witness. Corrections append a new independently evidenced record; prior decisions, original witnesses and verification history are never rewritten or deleted.
Recording a resolution does not restore a witness to tenant-facing tables, sign an old envelope, or mark it verified. Any later release of preserved material requires its own approved bounded owner operation and evidence checks. Until then even resolved evidence remains outside normal tenant reads and verification.
