The organs: services as composable cell programs
The kernel is eight verbs (rung 2); a real application needs lines of credit, private group chat, asynchronous delivery, durable storage. dregg provides these as organs — service primitives that are not new kernel and not bolted-on subsystems, but cell programs built from the verbs you already know, with the executor enforcing each organ's law on every turn. An organ is a factory with a name and a guarantee. The payoff this page builds to: organs compose — one cell can wear four organs at once, each contributing a slot caveat, and the executor enforces all four together.
The design discipline. None of these organs added a verb. Each is a
guarantee re-expressed as a guard the executor already knows how to check — a bounded
relation, a write-once commitment, a monotone counter, a value split. That is what makes
them composable: they are all the same kind of object,
a Pred, installed on one cell.
Trustlines — credit as an attenuated, quantitative capability
"Issuer A extends holder B a line of N" is granted ⊆ held made numeric: B holds a
capability whose every exercise debits a shared counter, and the cell's installed program
enforces drawn ≤ ceiling for the life of the cell. A draw within the line
commits; a draw over the line is refused by the executor itself — not by app bookkeeping
that could be skipped. Settlement applies the net position back to the ledger as ordinary
moves, so conservation is the kernel's ordinary law with no side table. Lines
of credit and sub-second payment channels are one primitive at two settings.
Channels — a group is a cell, and removal darkens two planes at once
A group is a cell: its membership commitment, its key-epoch counter, and
its epoch-key commitment all live on-cell, and joins / removals / rekeys are turns under
the group's program — so the whole governance algebra applies to membership. Message bodies
never touch the chain (control plane on-cell, ciphertext over any transport, including
mailboxes). The keystone is an epoch unification: the group's key epoch and the
capability-freshness epoch are the same counter, so a single
remove(member) turn darkens both planes at once — the removed member
loses the ability to read forward (the key epoch stepped) and the use of any
group-held capability (the freshness epoch stepped), atomically, in one turn. There is no
window in which a removed member can still act.
Mailboxes — accountable handoff across arbitrary delay
A mailbox lets A hand B a sealed turn-intent while B is offline. B's crank later drains B's hosted relay inbox over a real HTTP route; the relay's dequeue proof anchors a custody receipt; the executor-anchored sender gate admits A (and refuses an ungranted sender, with no state change); and the intent executes as an ordinary turn on B's cell. The delay-tolerant property comes for free because turns are self-certifying — a turn proved correct is correct whenever it lands, so store-and-forward becomes accountable across any delay without a new trust assumption.
Storage, adjudication, randomness
- Storage — a content-addressed store whose admission is a verified
storage-gateway-mandate cell: an op allowlist, a path-prefix scope, and a volume
budget the executor enforces (
sgm_volume_legal_forever). The read-cap / write-cap / verify-cap separation lets a host prove custody of, scrub, and replicate what it cannot read. Persistence is a per-collection axis —attested(permanent, conservation-grade) ·retained(window)(prunable after a challenge period) ·prunable(deletion is a guarded write: who may remove is law). - Adjudication — a bond lives in the disputed cell's own balance; slash
is an ordinary
move; no-double-resolve is the same terminal-state discipline as an escrow. The court's rule is witness-first: where either party can exhibit a verifying witness, the exhibit decides, and tribunals enter only on the non-certifiable residue. - Randomness — a committee threshold-signature beacon
(
beacon_at(epoch, height)) anyone holding the group public key can verify; every t-subset produces the same signature, so there is nothing to grind. Consumers draw juries and seed sortition deterministically.
Worked example: the escrow-market, four organs in one cell
Here is the whole through-line — capability → cell → turn → guard → proof — in one shipped app. A buyer and a seller transact a good they don't trust each other over, with no escrow agent and no off-chain coordinator. The escrow is a single factory-born cell whose installed program is the rules, re-checked by the verified executor on every turn that touches it. Its lifecycle:
LISTED ──fund──▶ FUNDED ──ship──▶ SHIPPED ──settle──▶ SETTLED
- list — the seller opens a listing: writes the escrow
CEILINGandSELLER_HASH. - fund — the buyer escrows
amount ≤ CEILING, bindsBUYER_HASH. - ship — the seller commits the sealed-delivery digest (the encrypted
goods or turn-intent) into
DELIVERY_HASH. - settle — the deal closes: funds release to the seller and any remainder refunds the buyer, atomically and value-neutrally.
Each organ's guarantee appears as a slot caveat the executor enforces — and because they are
all Preds on one cell, the executor checks all four together on every turn:
| Organ | The guarantee | The caveat this cell installs |
|---|---|---|
| Trustline | a draw never exceeds the credit line | FieldLteField { ESCROWED ≤ CEILING } — the escrow is a bounded line;
the buyer cannot escrow past the listing's ceiling |
| Mailbox | sealed delivery, bound exactly once | WriteOnce(DELIVERY_HASH) — the seller commits the sealed-goods digest
once; tamper-evident, no swap-after-ship |
| Flashwell | atomic, conserving settlement | no-mint AffineLe { RELEASED + REFUNDED ≤ ESCROWED } on every turn,
and exact no-burn AffineEq { RELEASED + REFUNDED = ESCROWED } at settle —
the payout neither mints nor burns |
| Lifecycle | one-way, no replay, no double-settle | StrictMonotonic(STATE) —
LISTED→FUNDED→SHIPPED→SETTLED; no regress, no replay |
The flashwell invariant, honestly split. The executor re-checks the
descriptor's flat constraints unconditionally on every turn, so the no-mint half
(RELEASED + REFUNDED ≤ ESCROWED) is a universal invariant — no party
can ever extract more than was escrowed. The exact no-burn equality would be false
before settle (escrow is held, not yet paid), so it is scoped to the settle step and upheld
by the balanced split the SDK emits. Both halves have teeth: a value-minting settle is
refused by the AffineLe; a value-burning settle is refused by the
AffineEq.
That is the claim made concrete. The buyer's bounded draw is a trustline; the seller's
one-shot sealed commitment is a mailbox; the conserving payout is a flashwell; the
irreversible march of state is a lifecycle. Each is a guarantee dregg already proves at the
kernel; the app does not re-prove them — it inherits them by installing the caveats
and letting the executor enforce. Built from dregg primitives only:
FactoryDescriptor, Effect::SetField, a real
Authorization::Signature — no domain-specific escrow effect, no unchecked
authorization, no placeholder signatures.
Grounding
starbridge-apps/escrow-market/src/lib.rs— the capstone: the four-organ cell program, its factory descriptor, and thebuild_{list,fund,ship,settle}_actionturn builders;tests/factory_birth.rsdrives it through the real executor.sdk/src/trustline.rs— the trustline organ (open_escrows_the_line_and_grants_the_holder_capability,draw_within_line_succeeds_and_over_line_refuses,settle_moves_net_position_and_conserves,executor_program_rejects_over_line_draw_directly).sdk/src/channels.rs— the channel organ and the epoch-unification keystone (remove_is_one_turn_and_darkens_both_planes,executor_rejects_partial_membership_turns).sdk/src/mailbox.rs+node/src/mailbox_crank_e2e.rs— the mailbox organ and a genuine two-node async handoff with a custody receipt.docs/ORGANS.md— the organ charter (the welds, the parameterization discipline, the persistence axis);docs/TRUSTLINES.md— the trustline design note.
Touch it: walk the escrow-market and the other organ-composing apps in
the use-case explorer, or open the
Starbridge app surfaces. Every organ rides the same
.turn() path through the verified executor — no organ has its own executor
entry.