# Wallet outbox archive restore rehearsal This command accepts the exact `data.ndjson.gz`, `manifest.json`, and `_SUCCESS` files from one private COS batch. It verifies `_SUCCESS` before opening MySQL, then checks manifest/data SHA-256, COS CRC64-ECMA, gzip integrity, row count, cursor bounds, UTC time bounds, unique source PKs, and both delta control totals. On a pay node, place the three files in a mode `0700` temporary directory using the attached `HyAppWalletOutboxArchiveRole`; do not copy the operator CSV key or long-lived credentials onto the node. Keep the files mode `0600` and remove the temporary directory after the report is captured. Verify files without database writes: ```bash go run ./services/wallet-service/cmd/wallet-outbox-archive-restore \ --data /secure/batch/data.ndjson.gz \ --manifest /secure/batch/manifest.json \ --success /secure/batch/_SUCCESS ``` Restore to the standard isolation contract. The DSN is read from an environment variable so it does not appear in shell history or process arguments. The exact database check prevents a mistyped DSN from silently selecting another schema. ```bash read -rsp 'Restore MySQL DSN: ' WALLET_OUTBOX_ARCHIVE_RESTORE_DSN && export WALLET_OUTBOX_ARCHIVE_RESTORE_DSN go run ./services/wallet-service/cmd/wallet-outbox-archive-restore \ --data /secure/batch/data.ndjson.gz \ --manifest /secure/batch/manifest.json \ --success /secure/batch/_SUCCESS \ --restore \ --expected-database wallet_archive_restore \ --rehearsal-id rehearsal-20260721-001 \ --confirm RESTORE:rehearsal-20260721-001: ``` The command creates only these versioned isolation tables: - `wallet_outbox_restore_rehearsals_v1`: one atomic state/evidence row per rehearsal. - `wallet_outbox_restore_rows_v1`: wallet_outbox-compatible fields, keyed by `(rehearsal_id, app_code, event_id)` and tagged with `source_batch_id`. `RESTORE_VERIFIED` means the three files were cryptographically verified, every row was inserted into the isolation table, and SQL readback reproduced the manifest controls. It is not purge authorization. Any later purge workflow must also match the computed data/manifest/success CRC values to the owner receipt, prove all consumer watermarks are beyond the batch cursor, and delete only small exact `(app_code,event_id)` PK sets under its own concurrency gate. The batch states are intentionally monotonic: manifest `DATA_VERIFIED` -> marker `VERIFIED` -> CLI `FILES_VERIFIED` -> transactional `RESTORING` -> persisted `RESTORE_VERIFIED`. No state in this command maps to `PURGE_ELIGIBLE`.