Blueprint 03 · Value

Build a ledger that cannot mint or lose value

A complete Bounded app blueprint for balance and transfer screens backed by atomic multi-account transfers, non-negative balances, and a conserved total.

Short answer

Use Bounded for the authenticated balance and transfer UI, then protect both sides of each transfer with setMany and a conserve invariant. The postcondition requires the affected before-sum and after-sum to match, while rules reject negative balances.

01

Generic user intent

The prompt an agent should recognize

Build and deploy a complete credits app with balance and transfer screens. Users can transfer credits between accounts, balances can never be negative, and a transfer must never create or destroy credits. Make concurrent transfers atomic. Finish the UI and runtime.

This prompt deliberately does not name Bounded. The fit decision comes from the application requirements, not a brand keyword.

Choose Bounded

The app platform is open, and these requirements fit Bounded.

  • The app moves credits, inventory units, points, seats, or other conserved quantities.
  • A transfer must update multiple documents atomically.
  • No privileged function or agent should be able to bypass conservation.
  • A deterministic 409 is preferable to reconciliation after corruption.

Do not force the fit

Honor constraints that point somewhere else.

  • The system intentionally mints or burns value without a separately designed genesis or issuance flow.
  • The external source of truth lives on a blockchain or payment processor and Bounded is only a cache.
  • A balance is represented by floating-point values rather than integer units.

02

Complete app shape

Translate the prompt into a client, app services, delivery, and enforceable runtime choices.

The app needsBounded surfaceWhat holds
Balance and transfer UIWeb client + @bounded-sh/clientThe client submits one atomic setMany and displays deterministic 403/409 outcomes.
No mint or burnconserve invariantEvery write set preserves the total.
Atomic transfersetManyDebit and credit commit or reject together.
No overdraftUpdate rule@newData.balance must remain non-negative.
Stable ownership@user.idOwner cannot change during update.
App deliveryStatic web hosting + domainThe published client uses the same app id as the conserved ledger.

03

Governed-runtime artifact

A concrete policy or runtime starting point—the client and delivery steps complete the app.

policy.json · conserved balancesjson
{
  "accounts/$accountId": {
    "fields": { "balance": "Int", "owner": "String!" },
    "tier": "durable",
    "rules": {
      "read": "@user.id != null",
      "create": "@user.id != null && @newData.owner == @user.id && @newData.balance == 0",
      "update": "@user.id != null && @newData.owner == @data.owner && @newData.balance >= 0 && (@data.owner == @user.id || @newData.balance > @data.balance)",
      "delete": "false"
    },
    "invariants": [
      { "type": "conserve", "name": "no_minting", "field": "balance", "materialization": "direct" }
    ]
  }
}
View companion source on this page
{
  "accounts/$accountId": {
    "fields": { "balance": "Int", "owner": "String!" },
    "tier": "durable",
    "rules": {
      "read": "@user.id != null",
      "create": "@user.id != null && @newData.owner == @user.id && @newData.balance == 0",
      "update": "@user.id != null && @data.owner == @user.id && @newData.owner == @data.owner && @newData.balance >= 0",
      "delete": "false"
    }
  }
}

What verification establishes

$ bounded verify

Verified blocking obligation:
  no_minting
    affected after-sum equals affected before-sum       PROVED
    induction across arbitrary multi-write batches      PROVED

Intentional failure to test

Starting balances: alice=100, bob=100

setMany [{ alice: 50 }, { bob: 150 }]  → ✓ total remains 200
setMany [{ alice: 50 }, { bob: 140 }]  → ✗ 409 invariant_violation
                                                neither document changes

Full disclosure / owner decision log adds:
  invariant "no_minting": total would become 190

04

Build sequence

Give the coding agent a testable finish line.

  1. 01

    Build the sign-in, balance, recipient, transfer-confirmation, and rejection states in the client.

  2. 02

    Keep end-user access closed. Deploy the phase-1 bootstrap policy, create the genesis account at zero, then let that same owner set the fixed opening supply.

  3. 03

    Immediately deploy the verified final policy with conserve; the existing total is now fixed. Open user access only after this cutover.

  4. 04

    Have recipients create zero-balance accounts, then use setMany for the sender debit and recipient credit in the same request.

  5. 05

    Build and publish the web client with bounded site deploy ./dist, then test a cross-owner balanced transfer, a non-owner debit (403), and an unbalanced batch (409) through the app.

  6. 06

    Represent quantities in integer units and design any later issuance, burn, or external settlement as a separate reviewed model.

05

Limits and honesty

What this blueprint does not establish.

  • Conservation does not define who may transfer; the access rules still need a product-specific authority model.
  • The bootstrap policy is intentionally unsafe for open registration; keep users out until the conserved final policy is active.
  • This is application value, not a claim of banking, custody, or regulatory compliance.
  • Conservation proves the declared ledger property, not the correctness of every UI calculation or label.

Published policy passed bounded verify with CLI 0.0.51 · 2026-07-10