sandbox_ledger paths; they do not provision a custody provider, merchant
recovery store, notification channel, or regulatory approval for the operator.
Dependency matrix
Choose the custody mode honestly
sandbox_ledger is complete local/off-chain accounting with PostgreSQL as the
system of record. It is suitable for development, deterministic integration
tests, and deployments that explicitly intend to operate an internal ledger.
It is not a bank account, prepaid card, on-chain balance, proof of external
funds, or a regulated stored-value product.
external records provider identifiers but is intentionally unusable for
funding, authorization, and settlement until provider-specific code verifies
provider state. Do not turn arbitrary provider references into balance. A
production adapter must, at minimum:
- authenticate signed provider webhooks and reject stale or replayed events;
- deduplicate funding and settlement references transactionally;
- reconcile Grantex available/reserved amounts with provider state;
- reserve and settle through provider-supported atomic or compensating flows;
- persist provider transaction and evidence references without exposing credentials to agents;
- define timeout, partial failure, reversal, dispute, and restart recovery;
- fail closed when provider state is unavailable or ambiguous.
Route the public resource
SetJWT_ISSUER to the exact issuer URL used in tokens and
PUBLIC_BASE_URL to the browser-reachable origin. In a normal reverse-proxy
deployment, route the entire API origin to the auth service. If a static host
and API share one domain, explicitly forward at least:
https://auth.example.com/v1/prepaid-wallets. TLS is required outside
loopback development. A static-host 404 at this path means the agent cannot
list wallets, request reloads, or authorize a payment even if Cloud Run or the
origin service itself is healthy.
After deployment, unauthenticated probes should reach the auth service and fail
with structured authentication errors, not HTML:
Preserve the financial evidence store
Migration091_agent_prepaid_wallets.sql creates wallet, assignment,
reservation, reload, control, and append-only ledger structures. Treat
PostgreSQL as durable financial evidence:
- take and restore-test backups before and after migration;
- run every auth-service instance against the same authoritative database;
- monitor migration completion before marking a new instance ready;
- retain ledger and audit records according to an approved policy;
- never repair balances by deleting ledger or reservation rows;
- reconcile
available_amount,reserved_amount, ledger entries, and any provider evidence before reopening a blocked wallet.
Deliver reload notifications
The service emitswallet.low_balance, wallet.reload.requested,
wallet.reload.approved, wallet.reload.rejected, and wallet.reloaded
events. Agents can request a reload but cannot approve or fund it.
There is no built-in promise that a reload request reaches email, SMS, Slack,
WhatsApp, or another human channel. The current public webhook-registration API
accepts only its documented grant/token event allowlist. For wallet alerts,
operate an authenticated SSE/WebSocket consumer and bridge events to the
principal’s approved channel, or implement a separately reviewed webhook
extension. The bridge must deduplicate by event ID, retry durably, protect
principal contact data, and expose delivery failures to operators.
Do not auto-approve or auto-fund merely because a notification was delivered.
The principal decision and funding calls remain separate authenticated actions.
Make merchant work recoverable
For a side-effecting paid request, the resource server must use this order:- Validate the x402 request and call
/v1/x402/verify. - Complete
/v1/x402/settlesuccessfully. - Atomically create or retrieve the protected business result under the
caller’s HTTP
Idempotency-Key. - Return the cached result on an identical retry.
idempotencyKey recovers a Grantex reservation response lost before
settlement. The HTTP Idempotency-Key recovers merchant work lost after
settlement. They should contain the same durable logical operation ID, but one
does not replace the other.
Registry availability
Server deployment and npm publication are independent. A self-hosted server can run repository source while its application consumers still resolve older npm packages. Check the registry before deployment:0.4.1 and x402 0.2.0. Treat the registry as authoritative and pin exact
versions. See Release
Status for the public artifact matrix.
Maintainer-only PowerShell publication
Publishing is irreversible for an already consumed version. Run this only as an npm maintainer of the@grantex scope, from a reviewed and clean main.
Direct publication requires npm publishing permission and either account 2FA or
an appropriately restricted publishing credential.
1. Verify repository and registry state
2. Build, test, audit, and inspect both packages
npm pack --dry-run file lists. Each package should contain its
compiled dist output, README.md, package metadata, and no keys, credentials,
environment files, test fixtures, or unrelated repository content.
3. Publish in dependency order
Publish the SDK first. Let npm prompt for the one-time code instead of placing an OTP in shell history.4. Test the registry artifacts
release-status.json, web/release-status.json, COMPATIBILITY.md, the root
README, release documentation, and public website notices in one release PR.
Do not describe the packages as published until the exact registry queries
above succeed.
For stronger future releases, configure npm trusted publishing from a dedicated
GitHub Actions workflow with OIDC and provenance instead of maintaining a
long-lived npm token. See npm’s official scoped public package
publishing
and trusted publishing
documentation before changing the release mechanism.
Go-live checklist
- Exact repository commit and npm package versions are recorded.
- Migration
091_agent_prepaid_wallets.sqlcompleted and backup restore was tested. - Public OAuth, wallet, principal, and x402 routes reach the auth service over TLS.
- DPoP tokens use the exact public wallet audience.
-
sandbox_ledgerorexternalcustody behavior is described accurately to users. - External custody remains disabled unless the provider adapter and reconciliation runbook passed review.
- Reload alerts have a monitored consumer and delivery-failure path.
- Merchant handlers persist results by HTTP
Idempotency-Keyafter settlement. - Wallet blocking, reservation release, reload approval, restart recovery, and provider outage drills passed.
- Security, privacy, financial, and regulatory owners approved the intended production use.