Purser

Every live run

All 24 live runs, newest first 29 Oct 2026: Pay-per-call clearing30 Oct 2026: Four eyes on chain30 Oct 2026: Clearing under load30 Oct 2026: Receive policy: money from strangers held30 Oct 2026: Compliance before a payout from the policy contract2 Nov 2026: A checkout signed with Visa's Trusted Agent Protocol, on an Airwallex card3 Nov 2026: Three Claude agents run a company for a day7 Nov 2026: Airwallex itself declines an agent's card over the CFO's limit7 Nov 2026: An agent buys with a single-use Visa card; above the limit, only after Face ID10 Nov 2026: Purser opens a test company's Airwallex account and pays on its behalf10 Nov 2026: A customer pays an invoice by card; Purser books it only once Airwallex says SUCCEEDED10 Nov 2026: Purser's books posted to T:0 and matched line by line10 Nov 2026: Three test companies, each on its own Airwallex account12 Nov 2026: A hold for exactly the approved amount on Metal, then captured to the supplier12 Nov 2026: One payout, two locks: signed in Purser, then approved in Airwallex's web app12 Nov 2026: Purser's purchase books in Moneybird, read back to the cent12 Nov 2026: Passkeys sign on chain (P-256): the agent's limit changes only when two passkeys sign12 Nov 2026: The payee's bank checks the name before the CFO is asked12 Nov 2026: One signature, one Airwallex batch of two payouts, read back before submit12 Nov 2026: An approved invoice becomes a token, is pre-financed, then settled (prototype)12 Nov 2026: Claude chooses the Airi rail; the CFO's signed hash read back from Airi and Airwallex13 Nov 2026: A payout approved with the owner's own iPhone Face ID13 Nov 2026: Two paid, one after Face ID; Purser refuses a reused credential before any call13 Nov 2026: Records anchored on chain29 Oct13 Nov

Last live run: 13 Nov 2026. 24 live runs, newest first, every id from its own record. Test money only; what was simulated is said on each run.

Face ID to paid: 6.3 s and 6.4 s (2 payouts, 7 Nov; settlement simulated by the sandbox)
  • P-0002: 6.3 s (Face ID 12:12:20, PAID 12:12:26 UTC, 2026-11-07) Log ↗
  • P-0003: 6.4 s (Face ID 12:13:16, PAID 12:13:23 UTC, 2026-11-07) Log ↗
  • Left out: 2026-11-12-airwallex-two-locks-paid.md, signed with a labelled virtual test passkey, not Face ID.
  • Left out: 2026-11-10-platform-e2e.md, signed with a test passkey, not Face ID.
  1. Live testnetNewest

    Records anchored on chain

    One transaction's calldata is the head over 701 rows and journal lines of the committed records. Metal testnet, test money. JSON ↗ Log ↗

    1 more id
    Anchor0xaa93f270…e6c1 ↗Block27469355

    Purser hashed 3 parts of its committed records (the recorded run's decision log, the main run's audit chain and its journal) into one head and wrote it as the calldata of one Metal testnet transaction.

    Checks: npm run verify-anchor recomputes the head from the repository, reads the transaction from the chain (a Metal testnet RPC is needed) and prints MATCH or MISMATCH.

    Rails: Metal testnet (one anchor transaction). Money: Testnet · test money.

  2. Live sandbox

    Two paid, one after Face ID; Purser refuses a reused credential before any call

    2 paid (1 after Face ID), 5 refused by Purser incl. reused credentials, 1 not tapped: nothing charged. Test card. JSON ↗ Log ↗

    AirwallexVisaClaude2 of 6 purchases paidPaid PaymentIntent (B)int_sgpvspvj9ho44vth3wd
    1 more id
    Paid PaymentIntent (B)int_sgpvspvj9ho44vth3wdPaid PaymentIntent (A)int_sgpv8fbwkho44szfz4m

    2 of 6 purchases paid. The rail was chosen by claude-haiku-5-5 from 3. C, D, E, F1, F2 refused by Purser with 0 calls. We also tried reusing a credential, for a different amount and a second time (F1, F2). Purser's credential check refused both, with 0 calls to Airi or Airwallex.

    Checks: not every check passed.

    Rails: Airi wallet, Airwallex sandbox, Claude, test card. Money: Test card · test money.

  3. Live sandbox

    A payout approved with the owner's own iPhone Face ID

    The owner's Face ID, on the owner's own iPhone, approved EUR 240.00; Airwallex holds it IN_APPROVAL. Not PAID yet. Log ↗

    AirwallexClaudeTransferd0353daf-515f-464f-bf8e-9fb99e6cca00
    1 more id
    Transferd0353daf-515f-464f-bf8e-9fb99e6cca00Purser proposalP-0001

    Claude read invoice SLL-2026-11 (Stockline Data GmbH, EUR 240.00); proposal P-0001 opened. The owner enrolled a passkey on the owner's own iPhone and approved P-0001 with Face ID. Only then did Purser create the SWIFT transfer at Airwallex, once. A read-back showed IN_APPROVAL: Airwallex's own approval workflow holds it for a person.

    Checks: One create (POST /transfers/create), read back IN_APPROVAL. The step to PAID was not done that day: the pending approval was not found in the sandbox web app on the phone. The full two-lock path to PAID is the 12 Nov run. 15 Airwallex calls, within the budget of 25 the owner approved.

    Rails: Airwallex sandbox (SWIFT transfer, approval workflow), the owner's iPhone passkey. Money: Sandbox · test money.

  4. Live sandbox

    Claude chooses the Airi rail; the CFO's signed hash read back from Airi and Airwallex

    1 paid after Face ID, 3 refused by Purser, 1 not tapped: nothing charged. Test card. JSON ↗ Log ↗

    AirwallexVisaClaude1 of 5 purchases paidPaid PaymentIntent (B)int_sgpvnmz6rho3h10jnj2
    Checks
    Paid PaymentIntent (B)int_sgpvnmz6rho3h10jnj2

    1 of 5 purchases paid. The rail was chosen by claude-haiku-5-5 from 3. C, D, E refused by Purser with 0 calls. We also tried reusing a credential, for a different amount and a second time (F1, F2). The sandbox accepted both, so in this test only Purser's check stops it.

    Checks: not every check passed.

    Rails: Airi wallet, Airwallex sandbox, Claude, test card. Money: Test card · test money.

  5. Live testnet

    An approved invoice becomes a token, is pre-financed, then settled (prototype)

    Face value 2.40 test USD (amounts scaled down 100× for testnet); a simulated financier paid 2.35. Metal testnet. JSON ↗ Log ↗

    2 more ids

    An invoice the CFO approved with Face ID on 7 Nov became a token on Metal testnet, was bought by a simulated financier, and was settled by the debtor to its holder.

    Checks: Each transaction's receipt status success; the record verified against the chain.

    Rails: Metal testnet (an invoice token contract). Money: Prototype · testnet · test money.

  6. Live sandbox

    One signature, one Airwallex batch of two payouts, read back before submit

    2 payouts of EUR 240.00 in one batch; read back with 0 differences; Airwallex holds it IN_APPROVAL. A test passkey signed. JSON ↗ Log ↗

    AirwallexAirwallex batch3960a081-b058-422b-95b1-6298e45fe257
    Checks
    Airwallex batch3960a081-b058-422b-95b1-6298e45fe257

    Two invoices, signed once as a batch; one batch created at Airwallex under a request id derived from the signed hash, read back item by item, then submitted. Airwallex's approval workflow holds it.

    Checks: Read back: 0 differences. 13 calls. Signed by a labelled virtual test passkey; nobody approved it in Airwallex's web app.

    Rails: Airwallex sandbox (batch transfers), test passkey. Money: Sandbox · test money.

  7. Live sandbox

    The payee's bank checks the name before the CFO is asked

    4 name checks at Airwallex: 3 refused before any proposal, 1 full match let through. Test accounts. JSON ↗ Log ↗

    Airwallex
    Checks

    Purser asked Airwallex whether the payee's bank holds the account under the supplier's own name; anything but a full match (or could-not-verify) refuses the proposal before the CFO's phone shows it.

    Checks: NOT_MATCHED, NOT_MATCHED, PARTIAL_MATCH, FULL_MATCH. 7 calls.

    Rails: Airwallex sandbox (verify_account). Money: Sandbox · test money; none moved.

  8. Live testnet

    Passkeys sign on chain (P-256): the agent's limit changes only when two passkeys sign

    3 mandate changes run by the account only with both signatures; one payment refused on chain, then paid. Second signer: a virtual test passkey. JSON ↗ Log ↗

    MetalPasskey account0xb5A370DCdFb60F1Ede241C9c3B28135Ac4216a3c
    4 more ids
    Passkey account0xb5A370DCdFb60F1Ede241C9c3B28135Ac4216a3cChange 10x168c6579…8c2d ↗Change 20xb6eff587…315d ↗Change 30xd3bf7e0d…9f3e ↗Refused on chain0xe6d9c7ea…5df4 ↗

    A passkey account on Metal testnet with two passkey owners and a threshold of 2 bound, raised and revoked an agent's mandate; the account checked both signatures itself (WebAuthn verifier). The second owner is a labelled virtual test passkey.

    Checks: All 3 proposals executed by the account; the over-cap payment refused on chain, then paid under the raised cap.

    Rails: Metal testnet (a passkey account, two owners), CFO passkey, labelled virtual test passkey. Money: Testnet · test money.

    P-0001 · bind the agent's mandate, signed by two passkeysThis record keeps the signed hash, not the terms: check the transaction.Run on Metal testnet: 0x168c6579…8c2d ↗5bc3f77ccf403a6395de139f2c8c1b99633a0d45418d06deb6571d766ad8763e
    P-0002 · replace the agent's mandate, signed by two passkeysThis record keeps the signed hash, not the terms: check the transaction.Run on Metal testnet: 0xb6eff587…315d ↗345e9c38733e5f2721334bafa0d0bca0267350ecd2529852c1d18dda9fbf3455
    P-0003 · revoke the agent's mandate, signed by two passkeysThis record keeps the signed hash, not the terms: check the transaction.Run on Metal testnet: 0xd3bf7e0d…9f3e ↗5d6e5789b3ac30fcc3b45a65f7c75f17e25d1ddf209c410490e0c348738c4366
  9. Live sandbox

    Purser's purchase books in Moneybird, read back to the cent

    6 purchase documents read back from Moneybird: 0 differences. Sandbox administration, test data. JSON ↗ Log ↗

    Checks

    A small test company's purchase books (suppliers, invoices with their PDF, a payment, a journal entry, a correction) sent to a Moneybird sandbox administration and read back.

    Checks: Read back: 0 differences in 6 documents; the same sync again made 0 requests. No e-mail sent; the payment was on a simulated rail.

    Rails: Moneybird sandbox administration. Money: Sandbox · test money; none moved.

  10. Live sandbox

    One payout, two locks: signed in Purser, then approved in Airwallex's web app

    Airwallex held EUR 240.00 until the owner approved, then PAID. A test passkey signed; settlement simulated. Log, 12 Nov ↗ Log, 10 Nov ↗

    AirwallexTransfer4074d684-4704-406c-a527-2832753baf4f
    4 more ids
    Transfer4074d684-4704-406c-a527-2832753baf4fRequest idc25bfc22-64fe-4ff3-aeb2-102a3684fc19Short referenceP261110-48HWOJNPurser proposalP-0001Signed terms (SHA-256)f9ba0fe8758eadbef3b48f23e571ea92e3208f4ebd802703b413a414d444ac28

    Created on 10 Nov: a labelled virtual test passkey (not a person's Face ID) signed the exact terms in Purser, only then did Purser create the EUR 240.00 transfer, and Airwallex's own approval workflow held it IN_APPROVAL with the signed hash in its metadata. On 12 Nov the owner approved it in Airwallex's sandbox web app; it then went PAID (settlement simulated).

    Checks: Airwallex answered IN_APPROVAL on create and on a read on each day; Purser did not simulate past it or send it again. The first read after the approval showed PROCESSING; the sandbox's simulation endpoint then moved it to SENT and PAID (simulated settlement). A person approved only at Airwallex, not in Purser. 14 Airwallex calls (7 on 10 Nov, 7 on 12 Nov), within the budget the owner raised from 10 to 12 to 14.

    Rails: Airwallex sandbox (transfer approval workflow), test passkey. Money: Sandbox · test money.

  11. Live testnet

    A hold for exactly the approved amount on Metal, then captured to the supplier

    0.25 test USD reserved on chain on 10 Nov; the capture sent on 12 Nov. Testnet, test money. Log ↗

    MetalcaptureHold0xb371a336…7859 ↗
    2 more ids

    After an approval, Purser reserved exactly the approved amount on chain for one spender (approve, holdFrom), and captured it to the supplier on 12 Nov (captureHold).

    Checks: Each step's receipt status success; the capture simulated read-only first. Every RPC request within a hard cap of 15.

    Rails: Metal testnet (MIP20 holds). Money: Testnet · test money.

  12. Live sandbox

    Three test companies, each on its own Airwallex account

    Run of 10 Nov, 07:06 UTC: one EUR 4.84 payout PAID, Purser's fee EUR 0.02, booked in T:0; the new accounts' payouts refused by Airwallex. A test passkey signed. Log ↗

    AirwallexT:0Claude1 of 4 payouts paidPayout PAID593c340b-1752-4537-9ef2-0eb3558897cc
    2 more ids
    Payout PAID593c340b-1752-4537-9ef2-0eb3558897ccNew accountsacct_O07lI0VvMLagXlj5aeOgyg, acct_XFhJLpkwNp6lzl8rpySE_QT:0 entriesje_prod_wop0vx1B8xOmHQl0, je_prod_WN96JsvKXGCY7mYs

    Purser opened two more connected accounts (3 ACTIVE). Invoices came in by upload and e-mail and were read by Claude. New suppliers and payments were approved with a test passkey (not Face ID). In this run (10 Nov, 07:06 UTC) one EUR 4.84 payout went PAID on the company's behalf, with Purser's EUR 0.02 fee taken; it was booked and posted to T:0. The new accounts' payouts were refused by Airwallex.

    Checks: The receipt verifies offline (signature over the exact terms, 8 hash-chained steps to T:0). Airwallex refused the new accounts' payouts: the paying company's registration number is required (they were opened as non-registered sole traders), and a payer object on the transfer is refused (code 048). 75 Airwallex, 20 Claude and 12 T:0 calls, within the budgets Max approved.

    Rails: Airwallex sandbox (connected accounts, SEPA payouts), Claude, T:0. Money: Sandbox · test money.

    P-0002 · EUR 4.84 to Zeeland Verpakkingen B.V.Airwallex payout, PAID: 593c340b-1752-4537-9ef2-0eb3558897cce3057c735d9b8381baa9c59315f204fe8c686d8c92214777cab6765d5e82a236
  13. Live sandbox

    Purser's books posted to T:0 and matched line by line

    The 3 Nov run's books in T:0's shared sandbox: 0 differences; a second push posted 0. Log ↗

    T:0All 95 entries postedFirst journal entryje_prod_z7kTCuZ1iiwad01q
    Checks
    First journal entryje_prod_z7kTCuZ1iiwad01q

    95 journal entries from the 3 Nov books posted to T:0's shared sandbox entity, one at a time, each with an idempotency key.

    Checks: Debits equal credits (21,141,221.86 USD each); T:0 matches our books line by line, 0 differences; a second push posted 0.

    Rails: T:0 shared sandbox entity (general ledger). Money: Sandbox · test money.

  14. Live sandbox

    A customer pays an invoice by card; Purser books it only once Airwallex says SUCCEEDED

    EUR 24.90 on Airwallex's documented test card: SUCCEEDED, then booked. 4 of 15 calls. Test card, test money. Log ↗

    AirwallexPaymentIntentint_sgpv9bnppho0sezgl4a
    Checks
    PaymentIntentint_sgpv9bnppho0sezgl4a

    A test customer paid one Northwind invoice (EUR 24.90) by card through Airwallex's payment acceptance; Purser booked it only after Airwallex reported the PaymentIntent SUCCEEDED.

    Checks: The PaymentIntent read back SUCCEEDED before anything was booked. 4 of 15 approved calls. No real card; nobody was paid out.

    Rails: Airwallex sandbox (payment acceptance). Money: Sandbox · test money.

  15. Live sandbox

    Purser opens a test company's Airwallex account and pays on its behalf

    Run of 10 Nov, 05:02 UTC: EUR 5.00 paid out, Purser's fee EUR 0.05. Simulated: company, verification, settlement. Log ↗

    AirwallexConnected accountacct_SC-QD89fOneAeqaRFgOymw
    1 more id
    Connected accountacct_SC-QD89fOneAeqaRFgOymwPayouta9460dba-f31b-4111-be58-6d9a9e71adb1

    Purser's platform rail opened a connected account for a fake test company; fake verification details, submitted, made ACTIVE by the sandbox's simulation. Then, in this run (10 Nov, 05:02 UTC), a EUR 5.00 payout on its behalf, with Purser's fee sent as an application fee.

    Checks: Airwallex accepted the fee at exactly EUR 0.05; the payout went PAID through the sandbox's simulation (settlement simulated, no Face ID on this payout). 17 calls, each within the budget Max approved.

    Rails: Airwallex sandbox (connected accounts, payouts). Money: Sandbox · test money.

  16. Live sandbox

    An agent buys with a single-use Visa card; above the limit, only after Face ID

    2 purchases through Airwallex's Airi wallet, one after Face ID; a disallowed merchant was refused. Test card. JSON ↗ Log ↗

    AirwallexVisaevery check passedPayment intent, EUR 12.00int_sgpvzc9hjhnxvpblt2r
    1 more id
    Payment intent, EUR 12.00int_sgpvzc9hjhnxvpblt2rPayment intent, EUR 45.00int_sgpvzc9hjhnxvxc26ie

    2 purchases with a single-use Visa credential (one within the limit, one after the CFO's Face ID); one disallowed merchant refused by Purser before Airi was asked.

    Checks: every check passed.

    Rails: Airi wallet, Airwallex sandbox, test card. Money: Test card · test money.

  17. Live sandbox

    Airwallex itself declines an agent's card over the CFO's limit

    Airwallex declined 2 of 4 card payments; 2 invoices paid after Face ID. SWIFT settlement simulated. JSON ↗ Log ↗

    Airwallexevery check passedDeclined by Airwallex (LIMIT_EXCEEDED)01a1b5e8-6dc2-7000-95bf-c8fc5e6e2f38
    1 more id
    Declined by Airwallex (LIMIT_EXCEEDED)01a1b5e8-6dc2-7000-95bf-c8fc5e6e2f38SWIFT transfer SLL-2026-11738a4263-6d6c-4de8-94a3-93da1c175fb4

    3 cards, one per agent; 4 card transactions, declines by Airwallex itself; 21 signed webhooks; 2 invoices paid after the CFO's Face ID (SWIFT settlement simulated in the sandbox).

    Checks: every check passed.

    Rails: Airwallex sandbox: cards, webhooks, FX, SWIFT. Money: Sandbox · test money.

    P-0002 · EUR 240.00 to Stockline Data GmbHAirwallex transfer, PAID: 738a4263-6d6c-4de8-94a3-93da1c175fb4b0f075d94da077084d7fc6745f99e2c2253548d967e9c0413bffa9748dbbf7bb
  18. Live testnet and sandboxThe product, end to end

    Three Claude agents run a company for a day

    86 Metal payments, 1 card charge, 1 SWIFT transfer; 5 CFO Face ID decisions. Simulated: customer, supplier, settlement, second approver. JSON ↗ Log ↗

    AirwallexMetalClaudeSWIFT transfer (Airwallex)03360bfa-afce-457b-89d1-e1097fbe3985
    1 more id
    SWIFT transfer (Airwallex)03360bfa-afce-457b-89d1-e1097fbe3985Sweep on Metal0x86936a5b…ccb4 ↗Every paymentTrace any payment

    86 Metal payments, 1 card charge, 1 SWIFT transfer; 5 CFO Face ID decisions.

    Checks: 88 money flows reconciled, 0 differences; audit log 412 rows, intact.

    Rails: Metal testnet, Airwallex sandbox, Claude. Money: Test money.

    P-0001 · a policy change, approved4c277d48e9f4842d63cc4bae74d63cb540f9f560e4b96895035cd2a9df98aae9
    P-0002 · an agent's mandate, approvedThe published copy of these terms is shortened, so the hash cannot be recomputed here.bf7ec3a098556a126260fd3a76faf012e624ce1c2089482996daf09bb9b8168e
    P-0004 · a refund batch, rejectedddf360cce8e679a5c49a33f939c443d6fd6a927338f5fe6c58fae9986ad15a64
    P-0005 · an invoice payment, approvedThe published copy of these terms is shortened, so the hash cannot be recomputed here.797d4483594fc4f6585466f39bb3f9e4ad4200c85b82d5b7dc078527dcababcd
    P-0006 · a policy change, approved4e7ab559894e3eaa5ea9260b9615a21c3284471e3b32fa2db52fad66f293d9fb
  19. Live sandbox

    A checkout signed with Visa's Trusted Agent Protocol, on an Airwallex card

    Outside the Visa entry. 1 approved, 1 declined by Airwallex over the card's limit. The merchant was simulated. JSON ↗

    AirwallexCard transaction, EUR 19.9901a19bfa-df97-7000-b24f-4f59886cdf70
    1 more id
    Card transaction, EUR 19.9901a19bfa-df97-7000-b24f-4f59886cdf70Card transaction, EUR 45.0001a19bfa-f64f-7000-bd14-f5a871b211fd

    2 signed checkouts at a merchant we run: 1 approved, 1 declined over the card's limit by Airwallex.

    Checks: Each charge read back from Airwallex (PENDING, FAILED).

    Rails: Visa's TAP reference proxy, Airwallex sandbox card. Money: Simulated merchant · test money.

  20. Live testnet

    Four eyes on chain

    1 signature: reverted (two test keys on one machine, not two people). run record ↗

    MetalCFO alone: reverted · 0xe0976c5a…69c30xe0976c5a…69c3 ↗
    3 more ids
    CFO alone: reverted · 0xe0976c5a…69c30xe0976c5a…69c3 ↗CFO and a stranger: reverted · 0x728a9c27…c43b0x728a9c27…c43b ↗CFO and controller: paid · 0xd98e94ff…d30d0xd98e94ff…d30d ↗revoke by CFO alone: reverted · 0x3bf9f70e…3ab50x3bf9f70e…3ab5 ↗

    1 signature: reverted (two test keys on one machine, not two people)

    Checks: As its run record says. 4 transactions linked.

    Rails: Metal testnet. Money: Testnet · test money.

  21. Live testnet

    Clearing under load

    Paid all 2,000 at 4.24 payments per second. run record ↗

    Metal
    Checks

    paid all 2,000 at 4.24 a second

    Checks: As its run record says.

    Rails: Metal testnet. Money: Testnet · test money.

  22. Live testnet

    Receive policy: money from strangers held

    Held, then returned. run record ↗

    Metalallowlist-only policy set on the sweep wallet · 0xf1a7fe96…0c370xf1a7fe96…0c37 ↗
    2 more ids
    allowlist-only policy set on the sweep wallet · 0xf1a7fe96…0c370xf1a7fe96…0c37 ↗a stranger's 0.02, held by Metal · 0x9076343b…20d30x9076343b…20d3 ↗returned after the CFO's Face ID · 0x786686b6…fc3c0x786686b6…fc3c ↗

    held, then returned

    Checks: As its run record says. 3 transactions linked.

    Rails: Metal testnet. Money: Testnet · test money.

  23. Live testnet

    Compliance before a payout from the policy contract

    11 attacks reverted. run record ↗

    Metalscreened payment: paid · 0xc2eb6814…f2370xc2eb6814…f237 ↗
    3 more ids
    screened payment: paid · 0xc2eb6814…f2370xc2eb6814…f237 ↗replayed decision: reverted · 0x222385b5…27370x222385b5…2737 ↗redirected to the attacker: reverted · 0x03811931…e23a0x03811931…e23a ↗sanctioned payee: reverted · 0x91ed35a5…442e0x91ed35a5…442e ↗

    11 attacks reverted

    Checks: As its run record says. 4 transactions linked.

    Rails: Metal testnet. Money: Testnet · test money.

Partial runs, not counted as live · 2
  1. Live sandbox

    A new company's Airwallex account opened; hosted onboarding needs a template

    Account CREATED and read back; the hosted KYC link answered 400 without a template. 8 of 30 calls. Test data. Log ↗

    Airwallex
    Connected accountacct_tqitvOzLOL2gzTyLb5mgXg

    Purser opened one connected test account for a new (fake) company and read its status, then asked for Airwallex's hosted onboarding link, which needs a template Airwallex has not given us.

    Checks: Account CREATED, read back CREATED; hosted_flows/create answered 400. 8 of 30 approved calls.

    Rails: Airwallex sandbox (accounts, hosted flows). Money: Sandbox · test money; none moved.

  2. Live testnet

    Passkeys as the account's owners

    A 2-of-2 account whose owners are two passkeys, signed on chain through Metal's authorizeMandateCall. Software passkeys, not a phone. run record ↗

    Metal
    bind, the CFO's passkey alone: reverted0x41a963a9…24de ↗bind, both passkeys (Metal's authorizeMandateCall): done0x96850ad4…7d5b ↗revoke the mandate with both passkeys: done0xc82912c3…b8cd ↗

    a 2-of-2 account whose owners are two passkeys, signed on chain through Metal's authorizeMandateCall; software passkeys (src/metal/softPasskey.ts), the WebAuthn format a phone produces; not a phone

    Checks: As its run record says. 3 transactions linked.

    Rails: Metal testnet. Money: Testnet · test money.

Rehearsals, dry runs and control tests · 3
  1. Local control test

    A purchase changed after the CFO signed is refused; nothing is bought

    Our own test changed it; the CFO's Face ID was real. 0 Airi and 0 Airwallex calls. JSON ↗ Log ↗

    every check passed
    Signed terms (SHA-256)8fc413311562b5d2dc96cc1c502c869dd4582a2a28c2ec918c35a5c78ba52f3e

    A purchase changed after the CFO's Face ID was refused, a shop the CFO locked was refused, and unlocking offered it again. 0 Airi and 0 Airwallex calls.

    Checks: every check passed.

    Rails: Purser relay, CFO passkey. Money: Nothing bought.

  2. Rehearsal

    The three-agent day, rehearsed once before the main run

    86 Metal payments, 0 card charges, 1 SWIFT transfer; 5 CFO Face ID decisions. Simulated: customer, supplier, settlement, second approver. JSON ↗ Log ↗

    AirwallexMetalClaude

    Checks: 87 money flows reconciled, 0 differences; audit log 460 rows, intact.

    Rails: Metal testnet, Airwallex sandbox, Claude. Money: Rehearsal · test money.

    P-0001 · a policy change, approved1034e1abb4b84cf35d49725394f952b81600216898bab27f86148a3a212e0c32
    P-0003 · an agent's mandate, approvedThe published copy of these terms is shortened, so the hash cannot be recomputed here.487a52e8147ed79c8462470d96ef0ca9974eb21c169cbde365b0004fb934f2b2
    P-0004 · a refund batch, rejected7a1b09e187786504ef348b91990b25b61092e1da3b9e019820ce5a120a0e2b52
    P-0007 · an invoice payment, approvedThe published copy of these terms is shortened, so the hash cannot be recomputed here.3c24200cb4c2079b10138a4b9e71c7c6923869f032b6984afba7148815c9018b
  3. Rehearsal

    A customer disputes payments its agent made; Purser answers from the signed orders

    12 payments disputed as never ordered; each was checked on chain against its signed order (outcome: rejected). The customer was simulated. JSON ↗ Log ↗

    Metal
    Dispute caseDD-a88e8959A disputed payment0x2a81d430…f08a ↗

    A customer's agent claimed it never ordered 12 paid stock checks; Purser answered from the signed orders and the on-chain payments (outcome: rejected).

    Checks: Each disputed payment checked on chain against its signed order.

    Rails: Metal testnet. Money: Rehearsal · test money.

Every dry run's log: docs/runs on GitHub ↗

What the main run's record holds (docs/demo/main-run.json)
recorded_at
When the record was written, UTC.
run
The run's name.
company
The example company the run plays (Northwind Outdoor, a test world).
proof
The headline counts: payments alone, blocked, Face ID decisions, refusals on chain, money over a limit.
snapshot
The CFO dashboard at the end of the run: budgets, cards, decisions, refusals, reconciliation, audit head, books, Claude calls.
snapshot.traces
Each Claude decision: agent, model, turns, tokens, latency and Anthropic request ids.
snapshot.reconciliation
Every money flow checked against Airwallex and Metal, and the differences found.
snapshot.audit
The hash-chained audit log: row count, head hash, whether the chain is intact.
ledger
The ledger's rows the pages are built from (sanitised).
kind
What kind of record it is: from a live run, or an example.