Sable Vault
Sable Vault is a private registry for tokenized real-world assets. The principle is tokenize privately, settle publicly: everything sensitive is sealed before it touches storage, every state change is hash-chained, and batch commitments anchor to Solana, so a public observer can verify that history is intact without learning what it contains.
What is private, what is public
| Surface | Visibility |
|---|---|
| Declared value, yield, maturity, notes | Sealed (AES-256-GCM), issuer's session only |
| Position sizes | Sealed, each holder sees only their own |
| Transfer amounts and counterparties | Sealed, the two parties only |
| Asset name and type | Visible to holders of the asset |
| Event commitments and chain hashes | Public: GET /v1/vault/chain/{id} |
| Batch anchor roots + Solana signatures | Public: GET /v1/vault/anchors/{id} |
The database stores sha256 commitments of the sealed content, so a leaked dump reveals structure, never values. Supporting documents are never uploaded at all: the browser hashes them locally and only the digest is registered.
The ledger
Every asset carries an append-only event chain:
hash(n) = sha256( hash(n-1) ‖ commitment(n) )
Rewriting any event breaks every later hash. The chain is public: anyone holding an asset id can fetch it and recompute every link, no Sable account required.
Settlement
The anchor worker batches unanchored event hashes, computes a batch root, and
publishes sable-vault:v1:<root> to Solana mainnet as a memo transaction.
GET /v1/vault/anchors/{id} returns the root, the ordered event hashes, and
the Solana signature, so the root is recomputable and the on-chain memo
checkable by anyone. Events not yet covered by a finalized anchor are
labeled awaiting anchor: the registry never fabricates settlement.
Distributions: paying holders
Real assets pay: interest, dividends, a principal return. A distribution records a payout the issuer made across current holders, split pro-rata by position. It is not a transfer. It does not move principal; it records that a total was paid and seals each holder's share.
POST /v1/vault/assets/{id}/distribute { total_usd, kind, note? }
kind is one of yield, interest, dividend, principal, other. The
total is split pro-rata across holders by current position, floored per holder
with the rounding remainder handed to the largest holder, so the shares sum to
the declared total to the micro-dollar. Each share is sealed at rest; the payout
appends one hash-chained yield_distribution event, so it anchors to Solana
with everything else. The issuer sees the total; each holder sees only their own
share (GET /v1/vault/distributions). A distribution fires an amount-free
vault_distribution webhook.
Proofs: verify without revealing
An owner mints a signed statement disclosing exactly the fields they choose
(POST /v1/vault/proofs). The statement carries the chain head, the latest
anchor, and the disclosed values, signed secp256k1/EIP-191 by the same signer
as receipts, and verifies through the same public
endpoint:
curl https://api.buildsable.com/v1/receipts/verify \
-H 'content-type: application/json' \
-d '{"receipt": "<proof>", "signature": "<signature>"}'The trust model, honestly
Every proof embeds its own trust framing: attested (signed by the Sable registry over its hash-chained ledger) plus a public anchor when one exists. This is not zero-knowledge cryptography, and we don't call it that. What a verifier gets: the registry's signature is genuine, the ledger it signed over is tamper-evident, and its anchors exist on a public chain. What a verifier is trusting: that Sable's registry recorded honestly. Asset entries are issuer-declared. The registry records what an issuer states and proves the record's integrity; it does not appraise assets or verify backing.
What Sable Vault is not
Registry infrastructure only: Sable does not custody assets, make investment offers, or provide legal enforcement of ownership. Those wrappers belong to issuers and their counsel.
Endpoints
| Method | Path | Auth |
|---|---|---|
| POST / GET | /v1/vault/assets | session |
| GET | /v1/vault/assets/{id} | session |
| GET | /v1/vault/portfolio | session |
| GET | /v1/vault/assets/{id}/holders | session, issuer only (the cap table) |
| POST | /v1/vault/assets/{id}/close | session, issuer only, irreversible |
| POST | /v1/vault/assets/{id}/distribute | session, issuer only (pay holders) |
| POST / GET | /v1/vault/transfers | session |
| GET | /v1/vault/distributions | session (your payouts, as issuer or holder) |
| POST | /v1/vault/proofs | session |
| GET | /v1/vault/chain/{id} | public |
| GET | /v1/vault/anchors/{id} | public |
An issuer sees the full holder register (/holders); each holder sees only
their own position. Closing an asset chains an asset_closed event and stops
transfers permanently, irreversible by design, so recorded history can never
quietly change meaning. Transfers fire amount-free
vault_transfer_sent / vault_transfer_received webhooks.
Transfers settle to another wallet's Sable account: the recipient signs in once (SIWE) before they can receive, so positions are never unclaimable.