The OpenCSV Journal

Discoveries and how the architecture evolved — told as it happened, with the receipts linked.

← home · Bitcoin performance · formal verification · source

2026-07-31

Inception: client-side verified stablecoins on Bitcoin L1

Starting point: Shielded CSV (Nick–Eagen–Linus). Day-one decisions: anchor to Bitcoin L1 directly (no fork), shielded amounts with public assets and issuers (auditable supply over shielded transfers), and no zkVM — hand-written AIR with in-circuit recursion. First artifacts: the paper and this site.

2026-07-31

Recursive PCD works: constant proofs over arbitrary history

The transfer circuit verifies two predecessor proofs in-circuit — mint → transfer → transfer — so proof size and verify time are constant in coin history. Later measured: 56,041 bytes, ~3.6 ms verify, identical at hops 1 and 2. See BENCHMARKS.md.

2026-07-31

Formal verification from the start

Lean 4: inflation soundness, conservation, nullifier uniqueness, receiver correctness — sorry-free, every assumption a labeled axiom. Later enforced by CI axiom gating: the assumption set can't grow silently.

2026-07-31

Proving is single-thread-bound

Core-scaling: 1 core ≈ 4 = 8 = 64 cores at ~3 s per transfer. Single-core speed is all that matters — which unexpectedly makes phones interesting.

2026-08-01

Phones beat the server 3–5×

On-device benchmarks (opencsv-rs#1): iPhone 16e and 17 Pro Max prove a recursive transfer in ~0.55–0.96 s vs 2.97 s on the 64-core Xeon. Mobile proving is viable.

2026-08-01

Payments over production Signal, both directions

Physical iPhone: consignment as an E2E Signal attachment → +100 USD · verified rendered natively; the phone proves a 2-in/2-out transfer (~1 s) → CLI verifies. Audits agree on both sides. (issue, PR #2)

CLI side, regenerated weekly by CI from real regtest runs:

CLI mint flow on regtest CLI receive VERIFIED on regtest
2026-08-01

Discovery: copy-griefing discovery

A raw anchor record is just bytes: a mempool spy can copy it into their own transaction and front-run it — the copy wins the first-occurrence race and the victim's coins freeze. Burn, not theft. Three redesign rounds begin.

2026-08-01

Failure: the sidecar binding failure

First fix: publish (nf, B = H(nf, ctx)) and check it publicly. Broken on arrival — both inputs are on-chain, so the griefer recomputes B under their own context. Caught by the implementing agent, not shipped. The lesson that shaped everything after: public matchability and copy-forgeability are the same property.

2026-08-01

The bound-payload fix

The payload IS the bound value: P = H("bind" ∥ nf ∥ ctx), and the raw nullifier never goes on-chain. Copying fails (wrong ctx); recomputing needs nf (preimage). Later mechanized in Lean in both directions (griefer_copy_invisible, no_occurrence_without_knowledge).

2026-08-01

Real Bitcoin: regtest e2e and a live signet anchor

The demo chain dies: real transactions on regtest end-to-end, then a 100-USD mint confirmed on Mutinynet signet (tx 3282c8ab…, height 3308725), verified by a fresh wallet from scanned blocks. Two backends converge on one ctx derivation after a near dialect split.

2026-08-01

Discovery: BIP158 filters exclude OP_RETURN discovery

Verified against live bitcoind: basic compact filters omit OP_RETURN outputs entirely — anchor records are never filter-matchable. The compact-filter plan dies on contact; SPV (headers + merkle + one block) takes the point check.

2026-08-01

u64 limb soundness becomes a theorem

The conservation gadget's carry argument — the most failure-sensitive informal claim in the codebase — is mechanized (b036cf3). Bonus honest finding: the general converse is false (a completeness limitation, not a soundness hole) — documented, not lurking. The living formal page now carries 17 theorems, regenerated from the build. The original weekly site mirror was replaced on 2026-08-08 by a 15-minute source-revision watch plus a weekly forced rebuild.

2026-08-01

Indexing evolves four times in a day

Anchor-server (demoted) → full node → N-of-M cross-check → finally scan-first indexing, which made filters useful again: anchors add a constant marker output (546 sats to OP_0 ∥ sha256(OP_TRUE), quantum-clean). Filters include it, so phones find anchor blocks trustlessly at ~KB/block while the record stays ctx-bound. Exclusion becomes a local check; indexers become optional, spot-verifiable accelerators. Paper §4.7.1 rewritten the same day.

2026-08-01

The scan soundness formal package

The formal layer follows deployment: no-false-negatives of filter discovery (trustless absence is provable — and it fell out of the construction in one line), scan-exclusion soundness (scan-first ≡ full-block scanning), marker zero-authority, accelerator fraud-provability. 23 theorems, no new axioms (00edaed). The N-of-M honesty hypothesis is eliminated from the roadmap — the architecture got better, so the assumptions got fewer.

2026-08-01

The marker ships; scan-only verification proven

The marker output lands in anchor transactions (5564502, verified against real BIP158 filters), the ScanIndex engine follows (cd37a53), and the scan FFI completes the stack (5a21db1): a real mint consignment verified through the C ABI with no RPC and no indexerVERIFIED from the scan alone, double-spend rejected against the same index. Bandwidth for the test window: 320 filter bytes + 1,140 block bytes.

2026-08-01

Scan-first runs in the app — proven by a stranger's anchor

The iOS provider swap lands on opencsv-wallet (1fa76d6944): decision ladder (self-scan → cross-check → demo, throwing rather than falling back on an unsynced index), scheduled background sync, the "fully verified by this phone" badge. The interop proof: an anchor hand-crafted with raw bitcoin-cli from the spec — 64-byte OP_RETURN at vout 0, 546 sats to OP_0 ∥ sha256(OP_TRUE) at vout 1 — was discovered by the scan engine purely via the filter walk, under 5 KB across a 113-block chain. Two implementations, one protocol, zero coordination.

2026-08-02

Verify-then-adopt becomes real

The pure opencsv-kernel (b64bdf4) carves binding, occurrence, first-occurrence, and supply logic into an Aeneas-compatible Rust surface. The separate formal-aeneas project proves translated Rust equal to the Lean specification. The public record now keeps 29 specification theorems and 15 translated-Rust audit declarations as separate ledgers, not one inflated count.

2026-08-02

The mempool sentinel: one symptom, three lookups discovery

Fresh mints verified everywhere except the phone's credit path. The fix (1616397) could not live only in locate(): the accept driver asks anchor_at and ctx_at first. One shared lookup now resolves mempool sentinels and treats chain lag as retryable, not final.

2026-08-02

Serverless crediting closes the receive loop

opencsv_scan_export_snapshot (290c8e0) projects the phone's compact-filter scan into the snapshot consumed by the crediting verifier. A real consignment was verified and credited with no RPC, no indexer, and no anchor server. Public explorers become hints; they do not decide acceptance.

2026-08-02

A proof that only builds on one laptop is not a receipt failure

The first Aeneas project used an absolute local dependency path and audited only part of its surface. The reproducibility branch pins the Lean dependency by exact Git revision, removes a duplicate theorem, expands the audit to 15 translated-Rust declarations, and passes hosted CI (run 30765043746). The exact green commit was later fast-forwarded to formal-aeneas/main@3bcafed without a merge commit or history rewrite.

2026-08-02

Field sync and batching v1 each find a real bug discovery

Signet sync failed at height 2016 because the client applied the wrong difficulty rule; e137096 syncs 315,800 headers through 156 retargets. Batching v1 then proved that bare OP_TRUE fails CLEANSTACK when envelope items remain; 3d4da5f fixed the script. V1 remains prototype evidence, not the new-write format.

2026-08-02

Batching becomes co-funded and signer-verifiable

A signed stock input fixes the shared context. Each participant contributes one payload, one fee input, and one change output; every signer reconstructs the canonical transaction and releases only SIGHASH_ALL. C0/C1/C2 land as d51d139, 0af0258, and 54c0833. The 64-participant reference cap is a script-safety profile, not a universal relay quota.

2026-08-02

The project domain gets a real front door

The GitHub Pages project site originally kept its homepage under web/ and used a root meta-refresh. The opencsv.net cutover makes the repository root canonical: assets stay grouped under web/, while the old web/index.html becomes a compatibility redirect. Ordering is part of the design: domain ownership and DNS must verify before the Pages custom-domain flip, so the working github.io site never redirects into an unresolved hostname.

2026-08-03

Production proofs replace the beautiful prototype numbers discovery

The ~56 KB / ~3.6 ms / ~0.55 s-phone profile proved recursive PCD and mobile feasibility, but used two FRI queries and no grinding. D1 → D4 → D3 → D2 lands setup caching, hard-bound predecessor keys, in-circuit issuer authorization, and the frozen v3 boundary. The honest production receipt: a 94-bit enforced floor, ~0.54–0.85 MB proofs, 15–22 ms desktop verification, and 11.25–14.47 s transfer proving on the iPhone 16e. Two higher-memory profiles died under the iOS process limit before the final packing fit.

2026-08-03

A live child spends the marker and changes the protocol failure

The original P2WSH(sha256(OP_TRUE)) marker was filter-visible and anyone-can-spend. On signet, a third party immediately spent its 546 sats and pinned the parent against ordinary RBF. New anchors use unspendable P2WSH(sha256(OP_RETURN)); historical v2 remains readable but cannot enter a new replacement epoch. A generic Core fee bump then removed protocol change, justifying a pure change-only replacement validator. Full receipt.

2026-08-03

Adversarial review attacks the batching fix itself discovery

Typed verified-input capabilities, stock/fee-key body authorization, semantic quotas, durable signature release, and exact-manifest recovery replace Boolean assertions and newest-epoch-only state (8d047f6). A second attack pass found historical-v2 live admission and a slow-drip timeout. Tip e4265b9 closes both. Hosted CI and independent re-review remain merge gates.

2026-08-03

A Lean build can be green while the modeled rule is wrong failure

The first C3 batching-v2 model built and matched its axiom baseline, but ConformingReplacement did not require either endpoint manifest to be valid. It therefore admitted marker and conservation mutations. The corrective a831b13 requires valid endpoints and proves marker preservation. Final C1 reconciliation then added duplicate operation/payload/change-script rejection, reusable stock/change floors, and nonzero proposal guards in c4f970d. Exact hosted CI passed, the checked audit expanded to 54 declarations, and PR #2 records the fast-forward to opencsv-formal/main.

2026-08-03

Signal owns the fee wallet; Bitcoin is gas only

The anchor-server architecture is superseded. Rust owns the OpenCSV wallet, BIP84 fee wallet, UTXO reservation, change, context, signing, operation journal, safe RBF, and direct relay. Esplora accelerates reads; headers, BIP158, merkle proofs, and full blocks decide spend state. The FFI exposes no WIF, caller-selected input/change, arbitrary BTC recipient, general raw broadcast, or bespoke OpenCSV server.

2026-08-03

The phone restore that cloned a primary failure

iOS restored Keychain state onto the developer iPhone 16e, proving an account root could silently arm two primaries. Rust now binds the database and backup checkpoint to a separate non-migratable ThisDeviceOnly value. Missing/mismatched restores are read/export-only, and missing state is sticky: a later replacement cannot re-arm the wallet (fb4a26a).

2026-08-03

One consignment, one verdict, one bubble discovery

Delivery attempts are not payment identities. The Rust receive boundary decodes, canonically re-encodes, verifies/stores canonical bytes, and returns one SHA-256 identity for accepted and rejected verdicts (4dc05cf). Swift still owes the physical crash/resume receipt: two attachment attempts, exactly one rendered payment.

2026-08-03

A merged Rust foundation is still not an iOS wallet

After exact hosted candidate CI succeeded, the owner deferred the outstanding independent adversarial re-review and authorized strict fast-forwards: integration e4265b9, then wallet 4dc05cf, are now on opencsv-rs/main. The review is deferred, not represented as completed; later findings must be fixed forward. Signal-iOS, the linked iPhone, releases, and mainnet remain untouched, and physical migration/crash/retry/RBF evidence is still owed.

2026-08-04

“USD” was a label, not a product definition failure

The first Signal mint form accepted a ticker and amount, so typing USD could create an unrelated asset without recognizable issuer, terms, precision, backing, or redemption. A first correction froze one test-only Preview definition and removed custom input. It produced clean local build receipts, but it was only an intermediate design.

2026-08-04

One USD wallet; exact issuers; no minting in Signal discovery

The fixed per-wallet Preview was still wrong: deriving an issuer inside every Signal account created a different asset_id per account and placed supply authority in the consumer wallet. The corrected production boundary is owner-only. Rust accepts reviewed public issuer manifests but retains no issuer secret and exposes no mint C ABI. Signal aggregates exact trusted instruments beneath one USD product, names the chosen issuer at review, records its asset identity in the receipt, and rejects a send that would need to mix issuers. OpenCSV and any future Tether instrument remain separate claims; no Tether identity is invented and the registry remains empty until a real manifest is approved.

Draft receipts: Rust owner-only boundary 11ba73ca, issuer-tool CI gate e505b181, and Signal 645f12574d; 27 Rust account-wallet tests, focused issuer-selection/amount tests, and the complete unsigned Signal simulator build pass locally. Hosted approval, issuer activation, physical-device acceptance, merge, and mainnet remain open.

The first hosted run caught the privileged signet issuer example being compiled against the correctly owner-only default library. The correction makes issuer state and methods an explicit issuer-tools feature, requires it for that example, and gives the harness its own CI compile check. Default/CocoaPods builds remain owner-only. Exact local warning-denied workspace and feature checks pass. Both hosted CI runs for e505b181 subsequently passed; that validates the owner-only default and featured acceptance harness, not an issuer activation or merge.

2026-08-04

Issuance moved to a headless operator boundary

Removing mint from Signal did not remove OpenCSV issuance. Commit 7882e185 adds an opencsv-issuer binary behind the non-default issuer-tools feature. Signal's C ABI and CocoaPods graph remain owner-only.

The JSON operator reads independently generated issuer root and device binding secrets from owner-only files. It creates exact manifests, prepares mints only by asset id, requires exact checkpoint acknowledgements, and exposes durable broadcast, resume, cancel, and protocol-safe fee bump. Running the open-source binary cannot mint another issuer's asset without its committed seed, and a USD ticker lookalike is not admitted to Signal's reviewed registry. No Tether authority or manifest is claimed.

Four CLI tests, an exact-checkpoint regression, and focused warnings-denied/Clippy checks pass locally. Hosted CI for this exact tip is pending; Signal source, the iPhone, issuer activation, merge, release, and mainnet were untouched.

2026-08-04

Unsigned was not an in-place Signal upgrade failure

A simulator build made with CODE_SIGNING_ALLOWED=NO lacked Signal's effective application-group entitlement. Launch failed closed, and CoreSimulator replaced the simulator-only app/group containers. The provisional registration and wallet could not be recovered. Source, the physical iPhone, issuer checkpoint, and mainnet state were untouched.

The accepted procedure now requires Xcode's default local ad-hoc signature, inspection of app-group and keychain entitlements, and container identity receipts before and after install. The signed build passed; a fresh registration was completed without another reinstall. The exact runbook is ab0b20f.

2026-08-04

First exact reviewed issuer enabled on signet live test

Signal commit 4fec89e902 pins one test-only OpenCSV USD Preview manifest on signet. Mainnet and regtest registries remain empty. Its asset id is 1d58a8145eedac17efe66371293eb472a4c68554141cc14380360e6eb720b507; the public terms record six decimals, the exact issuer key and terms hash, no backing, no redemption, no monetary value, and no Tether claim.

A live registered simulator recognizes the one-USD policy at zero balance and has 20,000 confirmed signet sats restricted to protocol fees. Its public owner is ff17c90b2e7c511f8d64734e07833502d6a82308d0c5ba0ca862f61ebd48c124. The headless issuer's first preparation rejected safely before proving: its 1,000-sat confirmed UTXO was below the 2,500-sat policy floor. A 10,000-sat faucet output is observed but unconfirmed. No USD operation exists yet; confirmation, checkpoint acknowledgement, broadcast, Signal delivery, credit, crash-resume, and safe RBF remain open.

2026-08-04

Live issuance found a checkpoint self-reference before signing failure

The first funded preparation used the debug prover and took about 13 minutes. Its proof was valid, but persisting the checkpoint hash inside the operation and receipt changed the checkpoint that had just been hashed. The operation was cancelled before signing or broadcast, its fee outpoint was released, and the mismatching export was retained only as private forensic evidence.

Commit 1ef29d2 excludes acknowledgement metadata and the receipt's derived hash from the canonical checkpoint, stores the final receipt before hashing, and independently recomputes current state at acknowledgement. The exact export now remains stable across acknowledgement, while a later state change makes that old hash fail. Twenty-nine warnings-denied account-wallet tests and four issuer-CLI tests pass.

2026-08-04

First headless USD consignment crossed live Signal live test

The corrected release preparation minted 100 test-only preview USD to simulator owner ff17c90…8c124 under exact checkpoint 77f94dc96d1610da4c7775a86fbbcb576ff0b72edadcf9346a04e75c06f524ef. Rust persisted the signed transaction before submitting it to both configured signet peers. Transaction eb5571a6…1c22c uses 455 sats at 2 sat/vB, with record, marker, and change at vouts 0, 1, and 2. The canonical 536,508-byte consignment id is 16d16cde8b9fda972bf5b56abda706399907d4259987251a1d1ddd09f36fdd68.

Signal delivered and the freshly registered simulator downloaded that one 537 KB attachment. Its anchor is still in the signet mempool, so the wallet correctly remains at 0 USD. This is a transport and pre-confirmation fail-closed receipt, not a completed payment acceptance claim. Confirmation-depth credit, crash/resume, RBF, and physical-iPhone acceptance remain open.

2026-08-04

A fee bump needs one tracked writer failure + receipt

The first attempt to continue the live fee bump lost terminal ownership and briefly left two local processes competing to resume the same operation. Both were terminated before either changed the database; an audit still showed the original transaction and operation state. The accepted procedure now permits exactly one tracked writer session for a live operation.

One clean retry replaced eb5571a6…1c22c with signet transaction 2cac7c02…a762c at 5 sat/vB. The replacement adds 683 sats of fee and reduces only change to 8,316 sats. Funding input zero, record vout 0, marker vout 1, change vout 2, protocol context, and proof semantics remain unchanged. This entry originally also said the consignment id remained unchanged; that was wrong because its anchor reference names the exact transaction id. One configured peer accepted it directly; the other timed out. The new owner-only recovery checkpoint hashes to 5b02915a…f3ac1 and was acknowledged exactly. It then confirmed at signet height 316228. Signal requires six confirmations, so at tip 316229 the simulator correctly remained at 0 USD; four more blocks are required before credit is expected.

15f0ac2 adds backup export --output: create-new 0600 files, durable file and directory sync, partial-write cleanup, no overwrite, and a small receipt instead of terminal-printing a multi-megabyte secret checkpoint. Five focused issuer-CLI tests pass with warnings denied.

2026-08-04

Pending is visible, but not owned or spendable correction + boundary

The confirmed replacement exposed the exact failure: a consignment's anchor reference commits to its transaction id. The attachment already in Signal named eb5571a6…1c22c, while the chain contained 2cac7c02…a762c. AnchorNotFound was correct. Preserving input zero, the record, marker, context, output positions, and proof semantics does not preserve exact-txid consignment bytes.

Rust 53876eb1d7 atomically invalidates stale delivery bytes, persists the signed replacement, and regenerates canonical bytes only after observing the replacement. Signal 835ec46f34 pins that source and models incoming activity as confirming → available or needs attention. Pending and failed entries carry no amount, verdict, replay credit, or spendability; only full acceptance credits the Rust wallet. One replaceable notification advances with the state. Thirty Rust account tests, 20 focused Signal wallet tests, and the signed simulator build pass. Live replacement delivery and credit remain open.

2026-08-04

Verified unconfirmed is spendable; transport pending still is not correction + boundary

The earlier boundary used “pending” for two different facts. A downloaded attachment is only transport and earns no amount, coin, or spendability. An exact unconfirmed Bitcoin transaction can carry stronger evidence. Rust eee48878ee adds a separate provisional capability instead of weakening ordinary verification; follow-up 420338280f removes a disappeared parent's coins from the already-open wallet immediately.

Only the phone-owned self-scan path can use it. The confirmed scan remains the exclusion prefix; generic Esplora supplies the exact mempool transaction as a non-authoritative accelerator. Rust independently verifies proof, ownership, binding, txid, funding context, RBF, and canonical record/marker/change layout. Mempool entries never enter confirmed ordering or first-occurrence audit logic. Cross-check and single-snapshot paths remain confirmation-gated.

Parent txids persist in the operation journal, pending export, and Secure Backup checkpoint and are re-observed after selection and immediately before signing. Missing or changed parents freeze provenance. Signal 7993fefb38 exposes confirming → available-unconfirmed → settled, replacement-risk copy, promotion notifications, and needs-attention recovery. Thirty-four serialized Rust FFI tests and 71 Signal tests in 14 suites pass on a disposable iPhone 16e simulator. Debug feature-on tests and a Testable Release feature-off app build both pass with app-target warnings as errors. A live two-hop signet receipt, replacement/freeze exercise, crash recovery, and refreshed film remain open; no evidence simulator or physical phone was modified.

2026-08-04

The registered evidence simulator was not an install target failure

After the green tests and build, a manual simctl install was run against the registered evidence simulator. Its ordinary app-container UUID changed and Signal returned to onboarding. Application-group database files remain, but the old registration/keychain state is not usable, so this is not called a preserved or recovered install. The physical iPhone, private issuer state, and mainnet were untouched.

The rule is now strict: compile and test on a disposable simulator clone; never install a test host or manual app over the evidence simulator. A future evidence upgrade requires recorded app/app-group/keychain identity and a recoverable clone first. Re-registration remains owner work.

2026-08-04

The website shows the real Signal simulator evidence

A new 40-second composition combines a real registered-simulator screen recording with Remotion framing. Six full-resolution captures separately preserve the Signal consignment, shallow-confirmation rejection, 0-USD wallet, public receive key, restricted Bitcoin fee reserve, and exact reviewed issuer. The wallet screens and values are real; animation supplies labels only. Confirmed-balance and send-review frames remain absent until the replacement anchor reaches the required depth and the app credits it.

2026-08-04

A fresh Signal wallet accepted the exact unconfirmed parent live receipt

The first newly registered Carol simulator exposed three cold-start problems hidden by warm caches: account and receiver paths disagreed about the effective peer policy, a newly accepted message request could wait behind the first scan, and signet bootstrapped from height 1 despite the reviewed issuer's much later birth. Signal commit bac3042202 uses one effective policy everywhere, re-enqueues downloadable attachments before the slow scan, and applies reviewed signet birth height 316000 while preserving explicit user overrides.

The cold phone-owned scan reached tip 316259 in 232675 ms after reading 1,653,466 filter bytes and 3,727,569 matched-block bytes. It accepted the exact still-unconfirmed mint anchor 8c3a39aa…8943. Two deliveries of the same 536,279-byte attachment produced one canonical consignment id and one live Rust database row with unconfirmed finality. The focused gate passed 73 tests in 15 suites. This is a receive and replay-deduplication receipt, not a child-spend receipt; crash/resume, fee bump, final captures, and film remain open.

2026-08-05

Performance claims now come from the transaction correction + receipt

The paper repeated an attractive but false shortcut: dividing Bitcoin block space by a 64-byte record and calling the result transaction throughput. A real anchor includes inputs, outputs, witness, discovery marker, and transaction overhead. The pinned Rust model bounds a solo anchor at 911 WU and an N-participant batch at 968 + 423N WU. Under an explicitly idealized 4,000,000-WU block every 600 seconds, that is 7.32 solo operations/s and 15.15 operations/s at 64 participants—not roughly 100.

At 5 sat/vB the model charges 107,904 sats for 64 solo anchors and 35,596 sats for one 64-party batch, a 67% reduction. The new performance explainer, versioned JSON receipt, paper v0.3, and CI verification script use the same formulas pinned to opencsv-rs@4dc05cfd. They also explain that provisional OpenCSV children consume off-chain asset coins with separate Bitcoin fee UTXOs; parent risk is enforced by the wallet dependency graph, not hidden behind a claim of instant finality.

2026-08-05

One received coin no longer needs a fake second input measured draft

The first recursive transfer shape always paid for two predecessor verifiers. Proof lineage v4 adds a distinct one-input/two-output path: one authenticated predecessor, one real nullifier, a zero unused nullifier, and exact recipient-plus-change conservation. A relabeled v3 envelope fails closed. On the physical iPhone 16e, exact source b0bc324432c5 proved this path in 6.4353 seconds, verified in 19.75 ms, and emitted 788,047 bytes at a 96-bit adjusted floor. The receipt is published on draft PR #8; hosted exact-tip CI and a live Signal signet spend remain open.

2026-08-05

A valid framework is not an entitlement-correct Signal upgrade failed deployment

The first source-built simulator install omitted Signal's application-group entitlements. CoreSimulator assigned new empty group containers, so Bob and Carol could not launch with their prior account databases. The corrected app now carries the Signal group and keychain entitlements, but acceptance is paused until the 14:05 local APFS snapshot is mounted read-only and both simulator databases are copied, verified, and restored. No physical phone, mainnet state, release, or completed payment receipt is implicated.

2026-08-05

The v4 wallet shape gets a formal specialization formal + source gate

opencsv-formal@68acca5 adds seven sorry-free declarations for one authenticated predecessor, one real nullifier plus an exact zero slot, recipient plus optional change, value conservation, one context-bound anchor, and an unchanged live pool. Hosted merge and default-branch CI passed, bringing the independently generated specification audit from the historical C3 milestone of 54 to 61 declarations.

CI also checks a versioned correspondence manifest against exact opencsv-rs@6278eae and fails on drift in version tags, the one-predecessor API, conservation constraint, nullifier/output order, statement projection, or verifier tag. This is a source-drift gate, not a claim that Lean proves the Rust AIR, FRI, storage, Bitcoin consensus, or networking. The separate 15-declaration Aeneas kernel-refinement ledger remains separate.

2026-08-05

The chat no longer waits for the proof async boundary

Several seconds of phone proving is a protocol cost, not a reason to freeze the send sheet. Rust 46a3e4870e separates durable intent planning from proof generation. The plan records the exact asset, recipient, and amount without selecting a protocol coin or Bitcoin input; the prover resumes the same operation from planned or fee_reserved and returns the exact stored receipt when already proof_ready.

Signal c14f02025d atomically persists the conversation metadata and enqueues an authenticated “pending — not spendable yet” message, then returns to chat. One serialized recovery worker owns proof, checkpoint backup, signing, broadcast, and final proof-bearing delivery. Restarts reuse the operation id; terminal rejection creates one failure follow-up instead of a stuck pending row.

The pending text is not optimistic credit. It creates no coin, amount, or spendability; ordinary proof and exact-parent acceptance still gate value. The real Signal test host built, 76 OpenCSV tests passed with 3 explicit external-fixture skips, and repository precommit checks passed on the disposable iPhone 16e simulator. Registered evidence simulators and the physical iPhone were untouched. Hosted merge and the live two-hop signet film remain open.

2026-08-06

Test USD is permanent signet state product boundary

The current Signal asset is no longer described as a preview that might graduate to production. Test USD, its exact reviewed asset, account database, checkpoint history, backup namespace, and BIP84 fee tree are permanently signet-only and have no monetary or redemption value. Production USD requires a new reviewed asset and registry, separate account and backup namespace, and a separately initialized mainnet fee tree. No Tether claim exists in this test registry.

Wire data still says USD; Signal derives the Test USD label from signet plus the exact testOnly manifest. Signal cannot mint or create assets. Issuance remains an opt-in headless opencsv-issuer operation. opencsv-rs PR #10 at 3295cd5 removes issuer/mint symbols from the default Signal header and archive while retaining them under issuer-tools.

Rust also enforces the exact reviewed asset ID at planning, before proof, at proof commit, and before signing. A removed or unknown instrument stays visible but is read-only with asset_not_reviewed; unsigned solo or frozen-batch work cancels atomically, while already signed work remains recoverable. Receipts separately time proof, pre-sign verification, signing/persistence, relay, pinned observation, and SPV so chain delay cannot be misreported as proof time. Local gates and hosted push run 31113193237 plus PR run 31113199886 passed at the exact tip; main fast-forwarded without a merge commit. Signal PR #6 pins that SHA. Its hosted build and the Bob/Carol payment sequence remain open.

The first recovery-only Signal hosted job at candidate fb89112e exposed an Xcode-path assumption before compilation; 3142394 normalized application-bundle and developer-directory forms. Local deployment validation then caught a stale CocoaPods checksum, corrected by 5324150 without moving a dependency. Full recovery validation next showed that workspace-wide warnings-as-errors contradicted explicit warning suppression in third-party pods. 0da5a47 asserts Signal's existing owned-target policy instead.

At 0da5a47, deployment-mode pod synchronization passes, the default framework omits issuer/mint and recovery symbols, the complete Signal simulator app builds, and 81 OpenCSV tests pass with zero failures and two environment-gated skips. The DEBUG recovery build contains the test-only rebind symbol and restores a default framework afterward. Failed and superseded runs remain public receipts, not passing claims.

2026-08-06

The homepage starts with a dollar payment consumer story

The first Signal film combined attachment transport, shallow-confirmation failure, Rust policy, receive identities, fee reserves, and issuer review. Those screens remain honest development receipts, but they led with a binary attachment, zero balance, blocked send, and wallet internals instead of showing a payment.

The homepage now uses one new 24-second composition: Carol sends 25 Test USD to Bob and Bob sends 10 Test USD back inside their Signal conversation. Setup, minting, fee management, explorer data, and protocol terminology are absent. The film is explicitly marked product animation, Test USD, and signet, with no monetary or redemption value. It is not a live transaction receipt. The historical simulator recording and CLI screenshots remain archived in the repository and no longer appear on the homepage.

2026-08-06

The product animation was not the requested receipt withdrawn

The owner asked for a video of quick dollar transactions in Signal. Replacing the old diagnostic media with a clearly labeled product animation still missed that requirement: it recreated Signal screens instead of recording the actual Bob and Carol builds moving Test USD. Honest labeling does not turn a simulation into transaction evidence.

The animation was withdrawn from the homepage and social-preview metadata. Its replacement must use only real simulator recordings tied to actual wallet operations and signet receipts. Editing is limited to timing, crops, participant labels, and captions that do not alter recorded application state.

2026-08-07

A real forwarding proof found a signed-carry bug failure → repair

Carol's real 25 Test USD payment reached Bob and was accepted from its exact Signal consignment. Bob's attempt to send 10 back then failed at one BabyBear witness value: 2013265920, or field -1. The transfer was valid—25,000,000 = 10,000,000 + 15,000,000—but the value gadget allowed only Boolean intermediate carries. This split needs a -1 borrow across its 24-bit low limb.

The local repair constrains intermediate carries to {-1,0,1} with c(c-1)(c+1)=0 and still pins the final carry to zero. The exact persisted-consignment reproducer passes; focused transfer tests pass; and release one-input forwarding proves in 6.522s then 7.226s on the development Mac. The same run fixed a confirmed parent being duplicated as its own mempool sentinel and a corrupt rebuildable BIP158 cache candidate blocking healthy peers. These are reviewed local repairs, not yet a merged release claim.

2026-08-07

The real Signal round trip replaces the animation live signet receipt

Carol sent 25 Test USD to Bob in e5ffe607…d9ee9, confirmed at signet height 316611. Bob then spent the received coin into 10 for Carol plus 15 change in a3a3f4b1…12dc0a, confirmed at height 316620. Carol verified the second proof, ownership, anchor binding, and exact mempool bytes and exposed it as available before confirmation with replacement risk. The first anchor had confirmed before the return was signed, so a true unconfirmed-parent child is still an open gate.

The return operation took 328s from durable intent to consignment delivery. Its receipt separates 6.237s local proving, 42ms signing and persistence, 1.826s relay, 77.861s funding verification, and 93.163s pre-sign verification. Two peers recorded complete transaction-submission writes, not mempool acceptance. Required pinned Blockstream observation matched raw bytes in 347ms; optional mempool.space observation timed out after 8.025s and was recorded unavailable. The final two-required-observer policy therefore remains open.

The homepage film is a 38.067s cut of those real simulator recordings. It removes waiting time but reconstructs no Signal screen or payment state. MP4 SHA-256: ca859b8e130c2960b7541b92ca60fc83d29da6c2f9e5aab9fd42f931871808e0. Test USD is permanently signet-only and has no monetary or redemption value.

2026-08-07

Require now means every required observer policy repair

The live Signal Advanced screen exposed a contradiction after the round trip. Both mempool.space and Blockstream were configured as Require, but a separate default quorum still read 1 of 2. One provider was therefore an optional member of an availability quorum despite its required mode. That contradicted the rule that both pinned APIs must return the exact transaction bytes before an unconfirmed Test USD coin becomes forwardable.

Rust cd1e678 derives an omitted quorum from every raw-transaction check marked Require and rejects explicit mismatches. Signal 4c27eca874 removes the caller override, derives the same count, and labels the policy Required pinned APIs: 2 of 2.

Local receipts are 61 Rust FFI tests passed with zero failures and two explicitly ignored slow recursive-receipt tests. The first enabled Signal live-provider run crashed before networking because the test host had never installed DependenciesBridge; the test had previously only run while skipped. 4c27eca874 activates and tears down Signal's mock test environment around it. The warning-denied rerun passed all three tests, including a 1.831-second live fetch where both pinned providers returned the same exact bytes for the known signet return transaction. Hosted exact-tip CI and a new wallet-level forwarding receipt remain open; this proves the observer client rather than payment acceptance.

2026-08-07

A real unconfirmed parent and child live signet receipt

Carol sent 1 Test USD in 2c3bc97c…f4786. While it remained unconfirmed, Bob accepted its exact proof and raw bytes and spent that coin into child f77ff986…24554. The child was also unconfirmed when Carol displayed it as available before confirmation with replacement risk.

For parent/child, mempool.space matched the exact transaction in 256ms/239ms and Blockstream in 377ms/359ms. Local proving took 6.096s/5.995s, signing and persistence 23ms/18ms, and relay 1.462s/1.461s. Durable intent took 90ms/107ms and the send sheet dismissed in 250ms/331ms. Both operations survived a post-broadcast relaunch and protocol credit appeared once at that checkpoint.

A transient Blockstream 404 held the child at 1 of 2 until retry, proving the required quorum fails closed. The run also exposed stale broadcast_unobserved error text after successful observation; Rust 2543c25 clears it atomically. The warning-denied FFI suite passed 61 tests with zero failures and two explicitly ignored slow recursive-receipt tests. Hosted exact-tip CI remains a merge gate.

2026-08-07

One shared anchor, then one logical payment across RBF live signet receipts

Carol froze one explicit batch: 5 Test USD to Bob and 5 Test USD to Note to Self. Batch c3d0260082cea04e98a1a56d9e7713fb committed both envelopes to the single signet transaction 771aefc6…3c4c3. Three ordinary peers recorded complete transaction-submission writes—not mempool acceptance—and both pinned APIs returned the same bytes in 271ms/354ms. Both recipients credited once, the apps survived relaunch, and the anchor confirmed at signet height 316687.

A separate 1 Test USD operation first signed cb32fa10…98fd5 at 2 sat/vB and replaced it with 4ae0f1c6…bd7f7 at 5 sat/vB. The protected funding input, OpenCSV record, marker, protocol context, output positions, change destination, membership, and delivery identity remained unchanged. Both APIs see the replacement unconfirmed and no longer serve the old transaction. Carol credited exactly once; replacement settlement remains open.

The first retry rotated an attachment nonce and initially produced two visible +1 Test USD bubbles. A display-text deduplication shortcut was rejected. Rust 28010d8 now supplies one cryptographic logical-payment id across replacements and was fast-forwarded exactly to opencsv-rs/main after hosted runs 31231128052 and 31231129868 passed; Signal 348b8e1 supersedes the presentation while retaining both signed receipts. Local Rust recovery validation passed 71 tests plus two integration tests, and the warning-denied Signal wallet-store suite passed 27 tests. Signal's tracked Rust repin/CocoaPods checksum repair and hosted CI remain merge gates.

2026-08-08

The homepage film becomes one real dollar return live signet film

The owner rejected the earlier lead cut because its assembled presentation still looked fake. The replacement narrows both claim and footage to the consumer action itself: receive 1 Test USD in Signal, then send 1 Test USD back. It is made entirely from one uninterrupted Bob simulator recording. No Signal screen, tap, payment card, pending state, or verified state was recreated.

The first fresh Carol operation, d8c1645716e97ec7bd4f7ad312e8262f, failed after its DEBUG proof with stale_chain_state; it produced no spend and was rejected as a successful take. After a fresh sync, Carol operation 4b03fd18a787d9ab8ebaf2d394aee6d5 sent 1 Test USD in 445c43cb…400fd. Bob displayed +1 Test USD · available before confirmation · replacement risk. The anchor confirmed at height 316765.

Bob operation 7edbe4cde4627550288f353f2b81e343 returned 1 Test USD in 6d85895f…f49aa. Signal showed its pending card and then −1 Test USD · verified; it confirmed at height 316766. Each transaction paid 455 sats and weighed 909 WU. mempool.space and Blockstream returned the same confirmed block for each. Bob's account row nevertheless retained broadcast_unobserved after public confirmation; this receipt preserves that bookkeeping inconsistency instead of hiding it.

The first Carol recorder froze when simulator runtime focus changed, so that take was rejected too. The published file comes only from the subsequent uninterrupted 230.803-second Bob recording. A first 38.1-second edit kept a large explanatory panel beside the phone and sped interactions to 2–2.5×. The owner correctly found the action chunky and the composition too artificial, so it was replaced before merge.

The next 59.3-second portrait cut left every action segment at normal speed and put four reading cards over the otherwise static phone view. The owner rejected that geometry too: explanation should accompany evidence, not obscure it. A landscape revision placed the explanation beside the phone only during the wait, but the opening still lacked context. The final cut uses one stable side-by-side grammar throughout: Signal remains on the left while synchronized panels on the right identify the received +1 card, explain each send step, describe durable intent, local proof, signed persistence and relay, name the two-observer raw-byte check, and finish on verified delivery. No panel covers the application. Action remains at normal speed; only the static wait is compressed, to 8.5×, with the rate printed on every affected panel. MP4 SHA-256: e3c0c70e2742c622b8e852fecf0ce45d151d7405dc859753005817d13b348cb3. Test USD remains signet-only and has no monetary or redemption value.

2026-08-08

Formal methods become a proof map, not a theorem counter honesty boundary

The previous page exposed the axiom audit but buried its most important conclusion: proof coverage is strong at the protocol layer and deliberately incomplete at the product boundary. It also still called recursive PCD lineage future work and named the superseded Rust correspondence pin 6278eae.

The replacement is an interactive academic-poster-style map from protocol to phone. It separates the 72 audited specification declarations from the 15 Aeneas translated-kernel refinements; identifies the AIR gate as source-shape checking rather than equivalence; and makes Bitcoin, Poseidon2/FRI, issuer keys, storage, networking, and general runtime orchestration explicit external or tested boundaries. The current V4 manifest pins opencsv-rs@9b9eca2, and the eleven shipped recursive-lineage declarations are linked as completed work.

We rejected both a synthetic completeness percentage and an “87 theorem” aggregate because those ledgers make different claims. The page instead makes the 72-declaration ledger searchable and keeps every major statement connected to its exact Lean source, Rust source, paper section, or CI receipt. Open the proof map →

The first poster draft put the temporary Swift bridge and Signal fork on the same coverage rail as the protocol and Rust implementation. The owner rejected that implication. They exist to demonstrate a consumer dollar-payment experience to Signal's team, not as an OpenCSV production interface or formal coverage layer. The formal page now contains neither; the homepage and end-to-end story label them only as a separate non-production demonstration.

2026-08-08

The formal ledger stops waiting a week publication integrity

The formal repository already ran CI when proofs changed, but the website copied its axiom table only on Tuesdays or after a manual dispatch. The rendered ledger could therefore be seven days older than its source even though every row was correctly generated.

The publication workflow now checks the formal default-branch revision every 15 minutes. An unchanged revision exits before installing Lean. A changed revision must still pass lake build and the complete axiom-audit gate before the table and provenance can be committed. An explicit formal-main-green event hook and manual dispatch can refresh immediately; a weekly forced rebuild remains as an independent integrity backstop. This avoids storing a broad cross-repository personal token merely to remove the lag.

2026-08-08

A two-screen message-flow cut starts in review editorial draft

The approved homepage film and documentation were fast-forwarded exactly to opencsv/main at 4e698b7. Post-merge verification 31262158883 and Pages deployment 31262158263 both passed. That is the current homepage receipt; this next edit remains a separate draft while under review.

The 36.288-second cut uses one real Signal screen beside plain-language context, then two synchronized real Signal screens when the payment moves between Bob and Carol. The small dot crossing between the phones is explicitly an explanatory representation of the encrypted consignment path, not recreated Signal UI or evidence of a packet capture. Dead pauses are cut; retained application action remains at normal speed.

The raw Bob and Carol recordings share creation time 2026-08-08T10:15:29Z and hash to a19880e24921f0d08ec13364fcf0120985946ea89330838f88fd3d5446b39b68 and de7de06a4d5e28312608f41cd505ee2bd7649c22aea1e42ada37691c0592aeb2. The opening Bob source hashes to bbf524608a040bd0d7f5af561028d181dda776f1272ead529482528653a4851f. An initial render failed because ignored source media was staged one directory deeper than Remotion expected; correcting that path did not substitute footage. The 2,881,105-byte review MP4 hashes to 5a59058f94ce5863337a957e8ec21ef7d724a95520303902b91748d43fa89b0c and is available only from an unlinked review page until approved.

2026-08-08

The two-screen cut becomes the homepage film owner approved

The owner approved the exact review artifact without requesting another edit. PR #20 was marked ready and fast-forwarded without force to opencsv/main at 227d4f5. Post-merge documentation run 31268281380 and Pages deployment 31268280785 both passed.

The homepage now points to those same approved MP4 bytes and poster rather than rerendering the footage. Its copy describes the actual cut: Bob sends 1 Test USD to Carol; one-screen moments pair real UI with context, and the handoff uses synchronized Bob and Carol views. The moving dot remains explicitly editorial motion, not Signal UI or packet evidence. The historical filename still contains draft; renaming it would add no evidence and would change the reviewed artifact path and receipt.

2026-08-08

Proof, performance, and delivery become separate public pages evidence architecture

The homepage and formal poster had each accumulated a second job: they also carried abbreviated performance and roadmap sections. That made three kinds of evidence look interchangeable. A protocol theorem does not prove a throughput projection, and a completed reference baseline does not mean the software has shipped.

The public research surface is now split by question. The formal billboard exposes the 72-declaration specification ledger, 15 translated-Rust refinements, assumptions, and gaps. The performance page publishes its calculator and versioned JSON receipt. The new roadmap filters complete, active, open, and owner-gated work and has its own machine-readable snapshot.

The homepage now acts as a directory instead of repeating those claims, and the formal page no longer embeds a delivery plan. README, paper, and plan of record use the same boundary. Signal status was corrected too: PR #6 is merged at db818658, recovery CI passed, and the failed default Xcode job in run 31262161093 remains a fix-forward gate—not a release.

2026-08-08

Settlement closes; the acceptance list gets shorter state reconciliation

The protocol-safe replacement 4ae0f1c…cbd7f7 is no longer pending. mempool.space and Blockstream independently report the same signet block: height 316803, hash 000000110b921854bf388cfdfb480a73f5effb1a14603abcf2031dc47bcf72a5. That closes the RBF settlement gate without rewriting the earlier replacement-risk or exact-once receipts.

The plan and paper still described already-merged Rust and Signal candidates as drafts, while several current-facing pages still called the superseded 59.3-second cut the homepage lead. The live homepage uses the owner-approved 36.288-second, 2,881,105-byte two-screen film with SHA-256 5a59058f94ce5863337a957e8ec21ef7d724a95520303902b91748d43fa89b0c. Historical entries remain unchanged; only current claims were updated.

At this checkpoint, no code PR remained open across the five core repositories. Recovery and the OpenCSV wallet tests passed, but the broad post-merge Xcode run stopped at OWSSwiftUtils.swift:56: Missing attachment file. Live pause-state recovery, clean-install Secure Backup recovery, physical rollout, release/security decisions, DNSSEC, and mainnet remain open.

2026-08-08

A larger zero-confirmation repeat finds two boundary bugs live receipt + fix-forward

Bob operation 4837cc8c104ce828346b618a686bb828 sent 45 Test USD to Carol in parent b8cf7015…b851269. Carol forwarded 10 Test USD before confirmation in operation 48d9400065a26187ef6c6584a97c6b10, child 2fbec40a…db0d286. Both required pinned observers returned exact bytes while both transactions were unconfirmed. Bob then accepted the exact child proof and dependency.

Each transaction was 309 bytes, 909 WU, and paid 455 sats. Parent/child local proving took 6.149s/6.171s; signing and persistence took 24ms/22ms; relay took 1.586s/1.549s. The child survived terminate/relaunch with the same operation id and advanced through observation and delivery. Both later settled in signet block 316824, hash 00000013c6be519c185986b59a65a05570488743a4b629a40375425984d4a9e2.

An apparent five-minute backup stall was host suspension, not proof or backup work: after wake, the 23,621,924-byte backup uploaded in 3.54s. No product-performance claim or scheduler change is based on the suspended interval.

The relaunch exposed a presentation/credit distinction. Protocol credit stayed deduplicated, but Signal could reinsert an outgoing attachment because storage used a canonical payment id while lookup checked only the raw consignment id. Signal PR #8 checks both identities; 28 focused tests pass locally and a live Carol relaunch suppressed every prior operation. Rust also failed a send when its first deterministic coin candidate was already spent on the verified chain even if an alternate was valid. Rust PR #16 reconciles confirmed spends and retries selection, including a pre-sign batch recheck. Its local default/recovery suites pass 71/73 tests with two deliberate slow ignores each. At this point in the run, hosted CI and merge remained open for both fixes, so neither was represented as release code.

Final reconciliation: Signal PR #8 merged at 1e3472b9; Rust PR #16 merged at 908bbb53 after green PR and post-merge Rust CI; Signal PR #9 then pinned that Rust SHA at 9b72d86d. The Signal PR-tip default/recovery jobs passed, but post-merge run 31283234786 failed the default Xcode job while recovery passed. That failure remains an explicit fix-forward gate, and no release is claimed.

2026-08-11

TestFlight moves from local archive to public-beta preparation distribution receipt

The first independently branded archive completed as OpenCSV Demo 0.1.0 (1), bundle net.ultravie.signal. The app and both extensions passed local signing validation with only the OpenCSV app groups and keychain group. Signal-only associated domains, Apple Pay, push, VoIP, communications, and privileged data-protection entitlements are absent. The source preparation commit is 896e8c8521 on codex/testflight-demo.

The first upload stopped before binary ingestion. Xcode authenticated Apple team 2858MX5336, queried App Store Connect for the bundle, received a successful response with zero app records, and failed closed with missingApp. This is a one-time catalog gate, not a build or signing failure. No public availability or Apple approval is claimed.

The new public beta page is now the stable website endpoint for the eventual Apple invitation. It remains explicitly pending until the app record exists, the build is uploaded, external test information is supplied, and Apple approves beta distribution. The page labels the build as an unofficial Signal fork, Bitcoin signet only, and Test USD with no monetary value.

2026-08-15

Mainnet becomes an activation contract, not a network toggle fail-closed design

The permanent Test USD boundary already required a new asset, registry, database, backup namespace, and fee tree for production. It did not yet define how those pieces become one reviewed deployment, leaving too much room for a host to mistake a network-string change for readiness.

The new production activation contract makes that separation a review contract. Test USD never migrates. Production starts from a fresh root and deployment-scoped derivation. An empty exact-manifest registry remains read/sync-only with production_usd_not_configured. Registry changes are versioned release inputs; unsigned work rechecks them, while exact already-signed recovery and protocol-safe fee bump remain available.

We rejected relying on Signal alone for namespace separation, treating USD or a familiar name as authority, and stranding signed Bitcoin bytes after a policy update. The contract also names the things no protocol proof supplies: backing, redemption, legal authority, brand identity, key custody, and operational readiness. Those decisions remain open and block activation. No issuer, production manifest, release, wallet, key material, or mainnet transaction was created.

The first implementation audit then found that mainnet inherited no required raw-transaction observers even though Test USD required two. A second pass found that an enabled SPV mode with zero configured peers could look ready and fail only at signing. Both were rejected as silent safety downgrades. The local Rust candidate now defaults to pinned mempool.space and Blockstream exact-byte checks, counts distinct observer hosts rather than check IDs or URL spellings, and requires two distinct compact-filter peers before new production writes. The local Signal candidate uses immutable profiles for both networks and rejects endpoint, pin, or mixed-network mutation before network I/O.

Public services remain untrusted evidence sources: Rust recomputes the transaction identity and confirmed settlement still comes from the independently agreed proof-of-work chain. These candidates remain unpublished behind earlier exact-tip review gates. Final observer operators and the pin lifecycle remain human activation decisions; no issuer, release, or mainnet authorization is implied.

A follow-up audit found another host-trust gap: the first candidate treated any nonempty, internally valid mainnet usd_issuers vector as a configured product. The local Rust gate now refuses that loose list. It accepts policies only inside a versioned release bound to the exact deployment and recomputes a domain-separated SHA-256 commitment over the format and registry versions, ordered manifests/priorities, source revision, and public HTTPS approval receipts. Mutated, cross-deployment, receipt-free, commitment-mismatched, and signet-misapplied releases fail during configuration; status exposes the exact release identity.

The full FFI result is 102 passed, 0 failed, and 3 intentional slow ignores, with default, recovery, and issuer feature builds warning-clean at local tip 715982ed7c78cbef670ed7b91c680aa720df2fec. The commitment and application distribution signature identify policy; they do not prove reserves, redemption, legal authority, or brand control. No real registry bytes or production issuer were created, and the candidate remains unpublished until the earlier exact-tip review gate clears.

The first envelope pass still treated the version as metadata. Local commit 29174cca3e3221767239afd46ddaa3d40f128232 stores the highest version and commitment atomically in the database and carries it in production Secure Backup. Older or same-version-conflicting policy opens balances and evidence but blocks writes with stable rollback/conflict reasons; a restored older checkpoint cannot lower the floor. The full FFI result is now 105 passed, 0 failed, and 3 intentional slow ignores. Rejecting account open entirely was also rejected because rollback defense must not hide recovery evidence.

The next audit found that the activation contract described limited-rollout caps without making them authenticated wallet inputs. That would let a host label a build “limited” while independently choosing its loss envelope. Local commit fa0736ce0f5cbde00aef145111b1223964ab0160 therefore adds the activation phase and exact transfer, batch, rolling-day, recipient, reserve-allocation, and miner-fee ceilings to the registry commitment. Candidate releases remain inspectable but return production_activation_not_authorized; limited and general releases recheck their ceilings at intent creation and before proof/signing. Host configuration may tighten the fee cap but cannot raise it. The revised FFI receipt is 109 passed, 0 failed, and 3 intentional slow ignores, plus both feature-gated recovery-rebind tests and warnings-denied default, recovery, and issuer builds. Treating general as unlimited and relying on UI limits were both rejected because neither survives a hostile or stale host.

That first cap implementation still consulted the live registry during RBF. Consequently, a later release could raise the exposure of bytes signed under a smaller cap or lower the cap far enough to strand their safe recovery. Local commit e5cd9ef589fe24ac26f083868693a9ccc12d31a5 closes both directions. Initial solo, batch, and reserve-maintenance signing snapshots the complete authorizing release into the durable receipt; replacement revalidates its deployment and commitment and uses the original miner-fee ceiling. A modified snapshot fails as database corruption. The exact-tip FFI result is 111 passed, 0 failed, and 3 intentional slow ignores, with the recovery and issuer build gates still warning-clean. Trusting an unauthenticated numeric receipt field was rejected; the complete release must recompute to its committed identity.

A follow-up removal test showed that an entirely absent snapshot still fell back to live host policy. Local commit 4965ba366652dd243a6d830fc953daf68943d0c0 makes missing mainnet authorization fail as database corruption while preserving legacy signet receipts. The full FFI result remains 111 passed, 0 failed, and 3 intentional slow ignores, and the warnings-denied FFI build is green. Substituting a later release for missing authorization was rejected because later policy did not authorize those signed bytes.

The self-hash still did not authenticate the snapshot: a complete replacement release could carry a newly recomputed commitment. Local commit 992eef901335dbb42735e5b092a9cc07d0432ac1 derives a deployment-separated wallet key and signs the release commitment plus the stable solo, batch, or reserve operation identity. A self-consistent substituted release and a valid snapshot copied to another operation now fail signature verification as database corruption. The exact full FFI result remains 111 passed, 0 failed, and 3 intentional slow ignores; warnings-denied default, recovery, and issuer builds and both recovery-rebind tests are green. Treating an unkeyed commitment as its own authenticator was rejected because a receipt rewriter can recompute it. Test-only follow-up 30012349f4889bdcf02f4e0b9e933a809fe22f6c pins same-root reopen, missing signature, malformed signature, cross-operation copy, and self-consistent release substitution as explicit failures.

The operator path still lacked a single canonical way to create the exact registry commitment. Reimplementing the release serialization in shell or a documentation script would have added a second byte-level policy surface. Local commit aa495a76d84003c91e457e7ded522125231bac03 instead adds a separately featured, secret-free opencsv-registry binary that calls the same Rust builder and verifier as account open. Build input must omit the commitment; output is create-new and durably synced. Verification requires the deployment expected by the containing application and reports structurally_valid: true together with activation_authorized: false. Wrong-deployment verification and overwrite both fail closed. The checked-in candidate has zero issuers, candidate phase, and a placeholder revision, so it cannot arm writes. Its golden commitment is bf808e3e0a5fad6cbc8caf23741e82adb5fbe5dd21dfb5a00840fd0801361169. The exact receipt is 113 passed, 0 failed, and 3 intentional slow ignores; the registry binary adds 4 passing tests, and default, recovery, issuer, and registry builds are warning-clean. An explicit serial release-mode run executes the three ignored recursive tests as 3 passed, 0 failed in 32.60 seconds. Treating structural validity as activation authority was explicitly rejected: distribution signing, independent review, issuer evidence, and owner approval remain external gates.

Follow-up 6fc1e4ca410083297250f4d7a7cfce474f4f2d93 adds the registry-only feature to hosted Rust CI in an isolated target directory. The job runs the four golden/durability tests, builds the release binary and library, writes the symbol inventory as a separate required command, and rejects any issuer C symbol. Piping nm directly into a negative grep was rejected because a failed or incompatible inspector can otherwise look like an empty result. The exact Linux symbol inventory remains a hosted gate after the stacked branch is published; the workflow syntax and cold release build are locally checked.

Activation-phase review then exposed a dangerous editing shortcut: the public candidate's zero issuers and all-zero placeholder revision were valid candidate inputs, but merely changing its phase could still produce structurally valid limited/general bytes. Local commit 6fdafb48867e5237c0f38d4e125ec62b4e076205 now rejects an activated release unless it has at least one exact issuer and a non-placeholder source revision. Deferring that rejection to the later wallet write gate was rejected because the operator verifier must fail malformed activation bytes before wallet open.

The headless issuer path then exposed a separate authority error. It still used only the primary-device and backup gate, so a mainnet mint could bypass the consumer registry and activation checks. Local commit a1809ebf7be42e7fa01f23b969c3a401b8aa8722 keeps manifest construction available for review but makes mint preparation, signing, stale-row rebroadcast, and mint RBF fail with production_issuance_not_authorized. Signet/regtest issuance is unchanged. The exact FFI result is 114 passed, 0 failed, and 3 intentional slow ignores; the three release-mode tests pass 3/0 in 31.31 seconds, and warning-denied default, recovery, issuer, and registry builds are green. Adding supply caps to operator-editable registry JSON was rejected as false authority: production issuance needs a distinct authenticated policy after the issuer/key ceremony.

A final relay reachability pass then found that fee replacement verified the signed production authorization, but ordinary crash rebroadcast did not. Local commit 36cadb9f4e886499c5f3cae302c7c38c26badd4d makes solo, shared-batch, and reserve-maintenance resume verify the deployment-bound, operation-bound signature before transaction parsing, chain reconciliation, or network I/O. Missing pre-gate state fails as database_corrupt. The exact FFI result is 115 passed, 0 failed, and 3 intentional slow ignores; release-mode is 3/0 in 31.91 seconds. Deferring authorization to RBF was rejected because idempotent rebroadcast is itself a network write.

A follow-up ordering pass found that all three fee-bump entry points still consulted live chain state before authenticating the persisted production authorization. Local commit 11bad686b10775207d40e3c85bdde61099637e63 moves that validation ahead of authoritative chain checks, replacement reconstruction, and signing for solo, shared-batch, and reserve-maintenance replacements. This makes missing authorization fail before external state or signing work can influence the result. The complete exact FFI receipt remains 115 passed, 0 failed, and 3 intentional slow ignores; the release-mode ignored suite passes 3/0 in 31.92 seconds.

2026-08-15

Production mint authority becomes replay-safe evidence threshold authorization

The earlier production boundary correctly disabled headless mainnet minting, but a permanent denial was not a usable issuance design. The stacked Rust draft in opencsv-rs PR #31 at exact head 9e7b6cdce12faf122f9cede08b703d3821b28769 replaces that stopgap with a secret-free verification boundary. Registry v2 commits the exact issuance policy; the policy names distinct administrative secp256k1 keys and a threshold of at least two; and every signed authorization binds the registry, asset, recipient, amounts, monotonic sequence, supply transition, validity window, and public receipts. The AIR issuer key remains a separate role.

An operation ID is the authorization digest. Planning creates the mint operation and consumed-authorization ledger row in one immediate SQLite transaction. A crash, failed proof, missing fee input, or cancellation therefore cannot make the same approval reusable. Sequence one begins at supply zero; each successor begins at the preceding supply-after value. Secure Backup includes that ledger and cancelled operations needed to establish the floor, and restore validates the chain before importing it.

Consuming approval only after proof generation was rejected because it leaves a replay window when proving or fee selection fails. A circular policy-to-registry hash was also rejected. Registry v2 instead commits sorted policy references, while each authorization separately commits the final registry and policy digests. Signed operations snapshot the evidence for crash recovery and protocol-safe RBF after policy removal; unsigned work still fails against the live release.

The first exact-tip audit also found that keys were deduplicated by their submitted hex strings although parsing accepted both cases. One key could occupy two threshold slots through upper/lowercase aliases. Policy verification now requires lowercase compressed canonical encoding and deduplicates serialized key bytes; the alias is an explicit regression.

A second audit found that the durable ledger still could not distinguish an older authentic backup from the latest one. Restoring a checkpoint from before authorization N would recreate the earlier floor, letting that same signed authorization use a different fee UTXO. Another backup hash was rejected because integrity does not prove freshness. Each authorization now signs one canonical confirmed funding outpoint, and the wallet reserves exactly that input without fallback. Replay after rollback must double-spend the same Bitcoin outpoint, so at most one branch can settle.

The first implementation enforced the binding only while reserving. Pre-sign now rechecks the durable operation funding columns, and signed resume/RBF also deserialize the persisted transaction and require its first input to be the authorized outpoint. Mutating either boundary fails as database corruption before signing or relay.

That implementation also admitted the authorization before reservation but could only report, not advance, a crash-left planned mint. Reusing the authorization for another operation remained correctly forbidden, so the sequence was safe but stranded. Issuer-only resume now reopens the same operation, reserves only its signed outpoint, continues an existing fee_reserved lock, and proves it to proof_ready. If the outpoint is absent, the operation stays planned and a larger unrelated wallet UTXO remains unlocked. A reopen regression exercises this exact transition.

The warnings-denied local workspace completed without an executed failure: 126 FFI passes with 3 intentional slow ignores, 3/0 serial release recursive proofs, 4 registry-tool tests, 8 issuer-tool tests, a 7-pass PCD node suite, and a 2-pass PCD redeem suite. Exact-head hosted runs 31917910203 and 31917911851 were still executing when this entry was written. No real policy, signer, administrative key, issuer, release, or mainnet transaction was created; independent exact-tip approval remains a merge and activation gate.

2026-08-15

The roadmap overstated root-key readiness D5 fail-closed

Re-reading the original Rust security audit against the recursive receiver found one unresolved critical boundary. D4 hard-binds every predecessor verification key inside its successor circuit, but proof-lineage v4 still reconstructs the root native verifier from common data carried by the proof. The static verifier-set tag authenticates a format/profile label, not that circuit. Calling D1–D4 “prover production readiness” therefore overstated the evidence.

The missing boundary is now D5 / opencsv-rs#32. V4 remains available on signet, while every shipped mainnet account returns production_root_vk_authentication_required before a fresh consumer or issuer Bitcoin write—even under an otherwise valid limited or general registry. Read, restore, sync, and evidence export remain available.

The static tag, proof-carried self-attestation, a mutable per-transaction allowlist, issuer/server cosigning of ordinary transfers, and a finite-depth allowlist presented as the general protocol were rejected as shortcuts. V5 must independently derive or authenticate the root from a canonical lineage, reject an adversarial custom-root proof, and receive independent exact-tip review. The fail-closed implementation is published at Rust PR #31 head cd9a71f7ab4703162b47848dc1fdda0f9841b7b3. Its warning-denied workspace completed without an executed failure: FFI is 127/0/3, the PCD node suite is 7/0/3, and redeem is 2/0/1. Hosted runs 31919832350 and 31919834317 and independent review remain required. No release, production issuer, mainnet wallet, or mainnet transaction was created.