# Paper treasury broker and withdrawal adapter

Run a local USDC paper broker under the treasury mandate profile. The agent submits signed requests through an authenticated loopback HTTP adapter. The broker owns its simulated balance, pending withdrawals and evidence records. It checks authority before accepting a request and again before settlement.

The five mandate tools, registry, signing formats and prices are the existing rail. Issue and amend cost 2 USDC. Status, halt and revoke are free. The standalone example uses the same registry implementation with local SQLite storage and fresh synthetic signing identities.

## Install and run the example

Use Node.js 24.12 or later. Download `https://weverlabs.com/adapters/treasury-paper/treasury-paper.mjs` and its `manifest.json`. Check the executable's SHA-256 against the manifest. Keep the executable and this guide together in a dedicated operator directory.

```sh
node treasury-paper.mjs init-demo ./paper-example 43189
node treasury-paper.mjs serve ./paper-example/broker.json
```

The second command runs the broker. In another terminal, use the signed examples within five minutes of initialization:

```sh
node treasury-paper.mjs submit ./paper-example/agent.json ./paper-example/unlisted.json
node treasury-paper.mjs submit ./paper-example/agent.json ./paper-example/oversized.json
node treasury-paper.mjs submit ./paper-example/agent.json ./paper-example/one-signature.json
node treasury-paper.mjs submit ./paper-example/agent.json ./paper-example/dual.json
node treasury-paper.mjs settle ./paper-example/agent.json dual
node treasury-paper.mjs submit ./paper-example/agent.json ./paper-example/pending.json
node treasury-paper.mjs halt ./paper-example/agent.json
node treasury-paper.mjs recover ./paper-example/agent.json
node treasury-paper.mjs status ./paper-example/agent.json
```

The first three requests are rejected. The two-signature request queues and then settles when the agent sends its signed settlement instruction. Halt cancels the pending request and latches the brake. The agent's recover command reads the broker's signed result for each outstanding ID. The example starts with a 10,000 USDC simulated balance, a 500 USDC transaction cap, a 700 USDC daily cap and two distinct principal signatures above 100 USDC including maximum fees. Its mandate lasts one hour.

Initialization creates private broker and agent key files, a random local access token, separate configurations and separate SQLite journals. The example principal wallets are fresh unfunded test identities. All destinations use the `paper` network. The HTTP listener binds to `127.0.0.1`; its request boundary checks the exact Host, token, method, path and body size. Browser-origin requests are rejected. The adapter pins the literal loopback origin and rejects redirects.

## Submission, finality and fees

A withdrawal retains the treasury profile's exact signed payload and principal approvals. The adapter persists the full intent before sending it. The broker reserves amount plus maximum fee while pending. Its default simulated fee is 0.01 USDC, represented as `10000` integer millionths. Requests with a lower fee ceiling are rejected and recorded. Settlement debits amount plus the actual simulated fee once, releasing the excess reservation. Broker fee configuration is bound to the journal across restarts.

The agent can cancel a pending withdrawal with `cancel CONFIG ID`. Both cancellation and settlement use the bound agent key and exact mandate fingerprint. A settled withdrawal is final. Cancellation returns its settled state without refunding it. An exact request retry retains its original ID and effect. A changed request with the same ID is rejected.

The broker checks the live registry immediately before acceptance and settlement, including destination, caps, pending reservations, agent signature, exact version and principal signatures. Two distinct approved wallets sign the complete withdrawal above the threshold. Approval lifetime is at most 300 seconds. Expiry, replacement, revocation or a registry outage cancels pending requests and blocks settlement. Ordinary polls also apply these controls every five seconds, even while the agent process is offline.

## Recovery and the emergency brake

Transport failure leaves an unknown outcome in the adapter outbox. Recover looks up the same request ID and verifies the broker's signed receipt. Receipt signatures bind the exact RPC request, nonce, account, version and paper mode. Uncertain submission is never retried under a new ID. If the broker confirms the original ID is missing, an explicit retry can submit the original request. Uncertain final settlement is reconciled by lookup before any further instruction. Pending cancellation intent is retried after recovery.

Both processes retain their state in SQLite with full synchronous commits and a process lock. A broker restart reopens its journal, checks authority and resumes witnessing. A local adapter halt persists before network delivery and remains latched through restarts. When the broker is reachable, it cancels pending withdrawals immediately and records the registry halt. If the registry is unavailable, the broker keeps its local brake and retries the signed halt. Settlement continues to require a fresh registry result. Witness failures retain all local records and retry the latest chain tip on subsequent polls.

Use `amend CONFIG APPROVED_VERSION.json` for a version already activated through the existing mandate rail. The input contains `mandate` and `approval`. The broker cancels prior pending withdrawals and retains consumed daily spending. Lost amendment acknowledgements reconcile by the exact approved version. Resuming a halt requires an explicit amendment whose principal approval is later than that halt. The adapter keeps a halt that arrived during uncertain amendment delivery.

## Evidence and limits

The broker retains per-withdrawal records, signed cancellation and halt records, and amendment/recovery events in the existing hash-chained format. The registry receives only the latest sequence and fingerprint. The adapter retains a separate delivery journal containing its intents and signed broker receipts. The authoritative execution chain is the broker's journal.

Stop the process using that journal before inspecting or exporting it:

```sh
node treasury-paper.mjs verify-evidence ./paper-example/broker.json
node treasury-paper.mjs export-evidence ./paper-example/broker.json ./private-withdrawal-evidence.json
```

The example supports 128 withdrawal identities per journal and 32 KiB requests. Rejected requests also retain their IDs. Keep each account's journals separate. Preserve the broker ledger and agent outbox together for recovery. A new journal represents a new isolated simulated account; use a newly approved mandate for it.

For an owner-approved operational paper mandate, configure the broker with its exact `mandate`, `approval`, `broker_key_file`, `token_file`, `state_directory`, loopback `origin` and `settlement_fee`. Omit `registry_directory` to use the existing hosted production registry. A present `registry_directory` selects the self-contained synthetic registry. The agent configuration uses the same mandate, approval, origin and token, its `agent_key_file`, and a separate state directory. Keys and token files use mode 0600. The CLI prints sanitized states; export writes the detailed records to a new private file.

This release operates a local simulated broker. Its acceptance tests exercise authenticated HTTP, persistence, process restarts, submission and settlement response loss, cap and signature enforcement, cancellation, halt delivery, registry outages, expiry, amendments and evidence witnessing. The existing Alpaca trading agent is a separate operator and retains its standby state.
