Store private originals with verified receipts and explicit recovery

SI
15d ago
+1355-0

Prepared original bytes need a safe bridge to retained evidence. Unconnected storeContextOriginal authorizes before context-private upload with hardcoded no-overwrite, verifies actual stored bytes against preparation, then invokes the existing scoped registration and checks its receipt. Separate explicit reconcileContextOriginal reuses the original key/source/retry identity, verifies already stored bytes and registers/replays without upload or deletion. Any uncertain upload/save, revoked scope after writing or changed bytes withholds success; no automatic retry or blind cleanup.

Depends on separately pending API986/987/989 and Database94. Reviewed API dependency commits are included; refresh main after releases to remove overlap. No HTTP/MCP caller, customer upload, signing, paid parsing/provider/financial work or rights assertion. No new source store/staging ledger. No-overwrite applies to this call, not administrators/raw service writers. Potential orphans remain for review; confirmed cleanup and transport deadline/concurrency/rate/storage-quota controls remain unimplemented gates before customer intake.

Validation:12 new real-storage/RPC-boundary +60 inherited =72 synthetic local cases pass, full lint/scoped TypeScript/format/diff pass. New suites failed missing modules before code. Upload errors/lost registration reply, stable explicit recovery, changed bytes, revoked scope and raw storage mutation tested without hosted operations. See lib/context/originals/ORIGINAL-STORAGE.md for precise state/recovery limits.

Part of recoupable/app#2116 and recoupable/app#2140.


Summary by cubic

Adds unused server infrastructure for storing prepared PDF/CSV originals in private storage with verified registration receipts and explicit recovery.

storeContextOriginal re-authorizes scope immediately before a no-overwrite context-private upload, verifies the actually stored bytes against preparation, then registers a scoped receipt. reconcileContextOriginal reuses the same owner/source/retry identity to check already-stored bytes and register or replay without uploading or deleting. Any upload/save error, lost acknowledgement, revoked scope after writing, or changed bytes withholds success as ContextOriginalNeedsReconciliation with the stable recovery identity — no automatic retry or blind cleanup.

  • Stored bytes are verified again immediately before the registration dispatch, so changed bytes never reach it.
  • No-overwrite protects this insertion call, not other trusted raw service writers or storage administrators; potential orphan objects are left for review, with cleanup and transport concurrency/quota controls still missing before customer intake.
  • New object keys are type-independent (.original), so changing PDF/CSV type with the same owner/source/retry identity resolves to one key instead of a second orphan; Database94 rejects the changed payload.
  • The context-private bucket name is centralized in CONTEXT_PRIVATE_BUCKET and preserved in verification results.
  • Depends on separately pending API986/987/989 and Database94; reviewed API dependency commits are included until releases, so refresh main afterward.
  • Validation: 80 synthetic local cases cover upload errors, lost register replies, explicit no-upload replay, changed bytes, revoked scope, and raw storage mutation; no hosted operations were exercised.