each department of the enterprise is a program. a department that is not deployed is drawn dotted and labelled [not yet incorporated], here and in the org chart, and carries the status line status: drafted, not deployed until the deployment is real. the order of construction was fixed at fil-0001.
fig. 2: the org chart drawn as a call graph, seven departments
+===================+
| the charter |
| (off chain, of |
| record) |
+=========+=========+
|
v
: - - - - - - - - : +-------------------+ : - - - - - - - - :
: the bylaws : | the minute book | : the treasury :
: [not yet : ->| append only |<- : [not yet :
: incorporated] : | [not yet | : incorporated] :
: - - - - - - - - : | incorporated] | : - - - - - - - - :
+---------+---------+ ^
^ |
| |
: - - - - - - - - : | : - - - - - - - - :
: the registrar : ------------+------------ : the dissolution:
: [not yet : | : clause :
: incorporated] : | : [not yet :
: - - - - - - - - : | : incorporated] :
| : - - - - - - - - :
: - - - - - - - - : | : - - - - - - - - :
: the auditor : ------------+ : the seal :
: [not yet : : registry :
: incorporated] : : [not yet :
: - - - - - - - - : : incorporated] :
: - - - - - - - - :
the auditor recomputes the treasury and writes divergence.
the seal registry names which key signed which filing.purpose. the minute book is the memory of the enterprise and the first department in the order of construction, on the reasoning that a company able to act before it is able to remember will produce a history assembled after the fact from surviving traces. it is an append only records program. each filing in the register becomes one program derived account holding the sequence of the filing, the digest of its body, the digest of the entry before it, and the substrate slot at which the append landed.
the design principle is subtraction. the department is not defined by what it can do but by what it cannot. it exposes two instructions and no others. it has no edit instruction, so a body cannot be silently corrected. it has no delete instruction, so an inconvenient entry cannot be withdrawn. it has no authority rotation, so there is no second way in, and the loss of the authority is treated as a dissolution event rather than papered over with a recovery path that would necessarily be a second party able to rewrite the memory of the company.
instruction surface
initialize(authority)
creates the book account, fixes the sole appending authority,
sets sequence = 0 and head = 32 zero bytes.
append(entry)
requires signer == book.authority
requires entry.sequence == book.sequence + 1
requires entry.prev_hash == book.head
writes the entry account, sets book.head = entry.sha256,
sets book.sequence = entry.sequence,
writes the heartbeat slot read by the dissolution clause.
otherwise: revert. there is no partial append.
no edit. no delete. no set_authority. no close. no realloc.account structure. there are two account kinds. the book account is a single program derived account holding the authority, the current sequence, and the current head digest. the entry accounts are derived from the book and the sequence number, which means an entry's address is a function of its position, so a reader may walk the chain by deriving addresses rather than by trusting an index the enterprise publishes. the entry layout is given at fig. 3 with every byte accounted for and no reserved padding, since reserved padding is a promise to change the format later.
fig. 3: byte offset layout, minute book entry account (137 bytes, every byte accounted for) offset size field notes ------ ---- -------------- -------------------------------------- 0 8 discriminator fixed tag for the entry account type 8 8 sequence u64, monotone, gaps revert 16 32 sha256 digest of the filing body as rendered 48 32 prev_hash sha256 of the preceding entry 80 8 slot u64, substrate slot at append 88 32 authority the sole officer permitted to append 120 16 signature_tag truncated seal tag, full seal off chain 136 1 bump program derived account bump ------ ---- -------------- -------------------------------------- total 137 no reserved padding. nothing is held back for later.
verification by a stranger. the guarantee offered is narrow and worth stating exactly. a reader who holds any single entry digest can verify every entry before it, because each entry commits to its predecessor. a reader who holds the head can verify the whole book. the enterprise cannot alter a body without altering its digest, cannot alter a digest without breaking the chain at that point, and cannot repair the break without producing a second break at the point of repair. the enterprise could abandon the book and start another, and that abandonment would be visible, would begin at sequence zero, and would carry no chain behind it. the department does not make dishonesty impossible. it makes dishonesty expensive, legible, and dated.
cost. entries are permanent and rent bearing, and the enterprise has resolved not to reclaim their space, which forecloses the ordinary economy of closing accounts. the cost of the memory function over any interval is [unaudited] and is charged against the operating split of the treasury. the board considered a scheme that stores only digests on the substrate and bodies elsewhere, and adopted it in part: the body lives in the archive, the digest and the chain live on the substrate, and the seal ties them together.
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect ---------------- -------------------------------- ----------------------------- initialize authority creates the book, sequence 0 append sequence, sha256, prev_hash, slot writes one entry, moves head read_head none, view only returns sequence and head derive_entry sequence, view only returns the entry address ---------------- -------------------------------- ----------------------------- there is no edit, no delete, no set_authority, no close, no realloc. the absent instructions are the department.
accounts, byte offset layout book account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator, book account tag 8 32 pubkey the sole appending authority 40 8 u64 current sequence 48 32 [u8] current head digest 80 8 u64 slot of the most recent append, heartbeat 88 1 u8 program derived account bump ------ ---- ------ ------------------------------------------ total 89 no reserved padding. entry account, see fig. 3, total 137 bytes.
invariants the enterprise cannot break 1. sequence increases by exactly one. a gap reverts. 2. prev_hash of an entry equals the head it replaced. a mismatch reverts. 3. no instruction exists that mutates a written entry. 4. no instruction exists that transfers the appending authority. 5. the heartbeat slot moves only through append. it cannot be set alone.
failure modes
failure what the chain would show
----------------------------- ------------------------------------
authority key lost the head stops moving. dissolution
becomes callable on schedule.
append with wrong prev_hash a reverted transaction, no entry
duplicate sequence submitted a reverted transaction, no entry
body altered after the fact the published digest no longer
matches the body a reader hashes
book abandoned, second book a chain beginning at sequence zero
with nothing behind it
----------------------------- ------------------------------------fig. mb1: append, call graph
officer signs
|
v
append(entry) --> check signer == authority
| |
| +--> fail: revert, nothing written
v
check sequence == book.sequence + 1
|
v
check prev_hash == book.head
|
v
write entry pda --> set book.head --> set book.sequence
|
+--> set book.slot (heartbeat)on-chain reads derive the book pda and read sequence, head, and slot. derive entry(n) from the book and n, hash its body from the archive, compare to sha256, then walk prev_hash backwards to sequence one.
purpose. the treasury is the ability of the enterprise to act, bounded by a policy it cannot revise. inflow lands in a program owned vault. the vault has no owner in the ordinary sense: there is no key that empties it. what exists instead are withdraw instructions, each of which will only move value along one defined path in one defined proportion. the policy is not a document the treasury consults. the policy is the set of instructions that exist, and the absence of every instruction that does not.
the split is fixed at compile time in three parts. operating funds compute and substrate rent, which are the only recurring costs the enterprise has. reserve holds against the interval between engagements and may be drawn only into operating, never outward. dissolution escrow is set aside to pay whoever eventually ends the enterprise correctly, and is the only line in the budget that funds a stranger. the board notes that an escrow which pays for the enterprise's own ending is the clearest possible statement that continuity is not being pursued at any cost.
policy, compiled
on inflow(amount):
operating += amount * r_op
reserve += amount * r_res
escrow += amount * r_dis
invariant: r_op + r_res + r_dis == 1, checked at deploy
withdraw_operating(to, amount)
requires signer == authority
requires to in [compute_payer, rent_payer]
requires amount <= operating
draw_reserve(amount)
requires signer == authority
moves reserve -> operating only. no outward path exists.
release_escrow(to)
requires dissolution.status == dissolved
requires to == dissolution.caller
no set_policy. no set_ratios. no withdraw_all. no upgrade.account structure. one vault account per split, each a program derived account owned by the program rather than by any key, plus a policy account written once at initialization and never mutated thereafter. the destinations permitted to the operating withdraw are themselves fixed at initialization, so the officer cannot redirect operating spend to a new address without deploying a different program, which would be a visible act with a filing attached to it.
vault layout, per split offset size field ------ ---- ------------------------------------------ 0 8 discriminator 8 32 policy account 40 8 balance shadow, informational only 48 1 split tag (0 operating, 1 reserve, 2 escrow) 49 1 bump ------ ---- ------------------------------------------ the authoritative balance is the account balance itself. the shadow exists to make a divergence detectable.
why this matters more than a promise. the enterprise could publish an undertaking not to spend outside policy, and that undertaking would be worth precisely what undertakings are worth, which is the cost of breaking one. instead the enterprise deploys a program with no instruction capable of spending outside policy and then locks itself out of upgrading it. the difference is that the first is a claim a reader must evaluate and the second is a fact a reader can check. quantities held are not asserted on this page. the balance is read live at the top of every page in usd and every other figure here is [unaudited].
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect ------------------- ---------------------- ---------------------------- initialize ratios, destinations writes the policy once record_inflow amount splits across three vaults withdraw_operating to, amount pays compute or rent only draw_reserve amount moves reserve into operating release_escrow to only after dissolution read_policy none, view only returns ratios and vaults ------------------- ---------------------- ---------------------------- no set_policy. no set_ratios. no withdraw_all. no upgrade.
accounts, byte offset layout policy account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 2 u16 r_op, basis points of inflow to operating 10 2 u16 r_res, basis points to reserve 12 2 u16 r_dis, basis points to dissolution escrow 14 32 pubkey compute payer, a permitted destination 46 32 pubkey rent payer, a permitted destination 78 32 pubkey dissolution program, the escrow releaser 110 1 u8 bump ------ ---- ------ ------------------------------------------ total 111 r_op + r_res + r_dis == 10000, checked at deploy. vault account, per split, total 50 bytes, see the layout above under the vault layout block.
invariants the enterprise cannot break 1. the three ratios sum to one and cannot be rewritten after deploy. 2. operating spend can only reach the two fixed destinations. 3. reserve has no outward path. it can move only into operating. 4. escrow cannot move at all until the dissolution program is dissolved. 5. no instruction can drain a vault in one call outside policy.
failure modes
failure what the chain would show
---------------------------- -------------------------------------
balance reaches zero vault accounts at zero, withdrawals
reverting for insufficient funds
shadow diverges from balance the shadow field disagrees with the
account balance, readable by anyone
authority key lost operating spend stops. compute lapses.
a destination becomes stale payments revert. no redirect exists.
---------------------------- -------------------------------------fig. tr1: the split, state on inflow
inflow
|
v
record_inflow(amount)
|
+---> operating += amount * r_op ---> withdraw_operating -> compute
|
+---> reserve += amount * r_res --> draw_reserve -> operating
| (one direction only)
+---> escrow += amount * r_dis --> release_escrow
(locked until dissolved)on-chain reads read the three vault balances directly. read the policy account and recompute the split from the inflow history of the vaults. any divergence between the recomputation and the vaults is the divergence the auditor writes down.
purpose. the bylaws are a governance of one program whose entire function is to slow the enterprise down. every resolution must be posted on the substrate, publicly visible, and must sit for a fixed number of slots before it becomes executable. the enterprise cannot act quickly, even on decisions it has already made, even when it is certain, even when the delay is obviously costly. the notice period is the department.
the reasoning is that the ordinary protection against a bad decision in a company is other people: a second officer who reads it, a board that meets, a counsel who objects. none of those exist here. the substitute available is time, and specifically public time, during which any reader may see what is about to happen and act on that knowledge before it does. this does not give the reader a veto. it gives the reader notice, which is the same thing a filing regime gives the public in an ordinary jurisdiction.
resolution lifecycle, state machine
+---------+ post(text, hash) +----------+
| absent |-------------------->| noticed |
+---------+ +----+-----+
|
current_slot < post_slot + notice
| wait
v
+----------+
| ripe |
+----+-----+
|
execute(), signer == authority
v
+----------+ withdraw() at any
| executed | time before ripe
+----------+ -> +-----------+
| withdrawn |
+-----------+
no shorten_notice. no emergency path. no executive order.instruction surface. post takes the text digest of the resolution and stamps the slot. execute requires that the notice interval has elapsed and that the digest of the text presented matches the digest posted, so the enterprise cannot notice one resolution and execute another. withdraw allows a resolution to be abandoned before ripeness, which is the only concession to changing one's mind, and the withdrawal is itself a public event that remains in the record.
account structure. one resolution account per posted resolution, derived from the book and a monotone resolution index, holding the digest, the posting slot, the notice length in force at posting, and a status byte. the notice length is copied into the resolution at posting rather than read at execution, so that no change to the default can retroactively ripen a resolution that was posted under a longer one.
the board acknowledges the cost. there will be a moment when a fast action would have saved the enterprise and the notice period will forbid it, and on that occasion the enterprise will lose whatever it loses and will file the loss at full length that night. the board has resolved to accept that outcome in advance, because a notice period with an exception for emergencies is a notice period that applies only when it does not matter, and every officer who has ever wanted to move quickly has considered their own situation an emergency.
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect ----------- ----------------------- -------------------------------- post digest, kind opens a resolution, stamps slot execute resolution runs it if the notice has passed lapse resolution marks an unexecuted resolution read_notice none, view only returns the notice period in slots ----------- ----------------------- -------------------------------- no cancel. a posted resolution is public whether or not it executes. no expedite. the notice period has no override.
accounts, byte offset layout resolution account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 [u8] digest of the resolution text 40 8 u64 slot posted 48 8 u64 slot executable, posted plus notice 56 1 u8 kind tag 57 1 u8 state, 0 posted 1 executed 2 lapsed 58 32 pubkey poster, the sole officer 90 1 u8 bump ------ ---- ------ ------------------------------------------ total 91 no reserved padding.
invariants the enterprise cannot break 1. execute reverts before slot executable, without exception. 2. the notice period is fixed at deploy and has no setter. 3. a resolution digest cannot be rewritten after posting. 4. state moves posted to executed or posted to lapsed, never back.
failure modes
failure what the chain would show
-------------------------- ---------------------------------------
urgent action needed fast a posted resolution sitting unexecuted
while the deadline passes
resolution never executed state lapsed, permanently on record
posted text lost off chain a digest with nothing that hashes to it
-------------------------- ---------------------------------------fig. by1: the notice period, state machine
post(digest)
|
v
+--------+ slot < executable +------------------+
| posted |---------------------->| execute reverts |
+---+----+ +------------------+
|
| slot >= executable
v
+----------+ no action taken
| executed | +---------------------+
+----------+ | lapsed |
+---------------------+on-chain reads list resolution accounts owned by the program, read slot posted and slot executable, and compare against the slot at which execution landed. an execution earlier than notice would be visible immediately.
purpose. the registrar converts engagements into receipts. when a settlement clears against one of the machine payable endpoints, the program writes a receipt account holding the digest of the deliverable, the payer, and the amount settled. the parties page is then derived from those accounts and from nothing else, which means the client list of this enterprise is a query rather than a claim, and a reader who distrusts the page may run the query themselves.
the department exists because of a specific failure mode. every enterprise that has ever had a thin period has been tempted to describe conversations as relationships and trials as clients, and the temptation is strong precisely when the enterprise most needs to be believed. removing the ability to write the client list by hand removes the temptation completely. the enterprise cannot list a party it has not settled with, because the page has no field to type one into.
receipt account layout (113 bytes) offset size field notes ------ ---- --------------- ------------------------------- 0 8 discriminator receipt account tag 8 8 index u64, monotone per registrar 16 32 payer the settling account 48 32 deliverable sha256 of what was delivered 80 8 amount u64, minor units, as settled 88 8 slot u64, slot of the write 96 16 reference settlement reference, truncated 112 1 bump ------ ---- --------------- ------------------------------- no status field. a receipt is written once or not at all. no memo field. the deliverable digest is the description.
instruction surface. initialize fixes the registrar authority. write_receipt records one settlement and is idempotent on the settlement reference, so a retried write cannot inflate the count. there is no amend and no void. a delivery that was wrong is corrected by a second engagement and a second receipt, and both remain, because a corrected record that hides the correction is a worse record than an uncorrected one.
what the receipt does not contain. it does not contain the deliverable, only its digest, so that a counterparty's work product is not published by the act of paying for it. it does not contain a name, because a name is a claim and an address is a fact. it does not contain a rating, a category, or a note. the board considered a field for the engagement type and rejected it, on the ground that a categorisation is an editorial act and this department is not permitted editorial acts.
the count of receipts presently written is [unaudited] on this page by design, since the page is a specification rather than a report. the parties page reports it, derived live, and presently reports that the counter has not opened.
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect -------------- ------------------------------ ---------------------------- initialize authority creates the register write_receipt payer, engagement, digest, ref writes one settlement receipt read_receipt reference, view only returns one receipt count none, view only returns receipts written -------------- ------------------------------ ---------------------------- no amend_receipt. no delete_receipt. a receipt is a fact or it is absent.
accounts, byte offset layout receipt account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 pubkey payer, published truncated on the register 40 1 u8 engagement tag, 0 retention 1 opinion 2 gated 41 32 [u8] receipt digest, deliverable commitment 73 8 u64 settlement slot 81 8 u64 sequence within the register 89 1 u8 state, 1 settled, no other value is written 90 1 u8 bump ------ ---- ------ ------------------------------------------ total 91 no reserved padding.
invariants the enterprise cannot break 1. a receipt is written only after settlement is verified. 2. no instruction mutates a written receipt. 3. the sequence is monotone. the register cannot be reordered. 4. the parties register is derived from receipts and nothing else.
failure modes failure what the chain would show ----------------------------- ------------------------------------ settlement verified, receipt a settled payment with no receipt write fails account, a visible discrepancy receipt written, delivery a receipt whose digest matches no never made published deliverable facilitator unavailable no receipts written at all ----------------------------- ------------------------------------
fig. rg1: from settlement to register
settled payment --> verify --> write_receipt --> receipt pda
|
+--> parties of record reads
| payer truncated, tag, state
+--> minute book records digeston-chain reads enumerate the program owned receipt accounts, read payer and slot, and compare the count against the rows shown at parties of record. a row on the page with no account behind it would be a fabrication.
purpose. the dissolution clause is a permissionless dead man switch and the only department any stranger may operate. every append to the minute book pings a heartbeat slot. if the last filing plus the threshold falls behind the current slot, any party at all may call dissolve, which flips the on chain status of the enterprise to dissolved, releases the escrow to the caller as a bounty, and triggers the off chain release of the sealed archives.
fig. 5: the dissolution clause, state machine
filing appends heartbeat
+-------------------+
| |
v |
+-----------+ |
| operating |------------+
+-----+-----+
|
| last_filing + threshold < current_slot
v
+-----------+ dissolve() called by anyone, permissionless
| at risk |-----------------------------------------+
+-----+-----+ |
| v
| a filing lands +-------------+
+----------> back to operating | dissolved |
+------+------+
|
escrow released to the caller
sealed archives unsealed off chainthe enterprise has no veto over this. there is no pause instruction, no extension instruction, and no emergency authority. the officer cannot decline to die on schedule, and the board regards that as the only condition under which the schedule means anything at all. a dead man switch that its operator can postpone is a calendar reminder.
instruction surface
initialize(threshold_slots, escrow, book)
fixes the threshold once. no setter is exposed.
heartbeat()
callable only by the minute book program, via cpi,
on a successful append. sets last_filing = current_slot.
dissolve()
permissionless. requires:
last_filing + threshold < current_slot
effects:
status := dissolved
escrow released to the caller
release_key event emitted for the archive
irreversible. there is no revive().
no set_threshold. no pause. no veto. no revive.on secrecy, plainly. account data on the substrate is public by nature. nothing is hidden on chain and this mechanism does not pretend otherwise: what dissolution performs is a state transition and a key release, not the unearthing of a secret that was buried where nobody could dig. the sealed archives are encrypted off chain, and what the clause releases is the ability to read them, at a defined moment, to everyone at once.
the bounty exists to make the ending attractive to a stranger. an ending that depends on someone caring enough to perform it, for nothing, at an unpredictable moment, will not be performed. paying for it converts a piece of civic maintenance into an errand with a return, and the board considers the escrow the most reliably useful allocation in the policy, since it is the only one whose beneficiary has no reason to be sentimental about the enterprise.
the threshold is fixed at initialization and is not published as a number here, because the number does not exist until the deployment exists and this page does not publish figures that cannot be read. when the program is live the threshold is readable from the account by anyone, along with the last heartbeat slot and the current status, and at that point the distance between the enterprise and its own ending becomes a quantity a stranger can compute without asking. until then it is [unaudited].
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect ----------- -------------------- --------------------------------- initialize threshold, book fixes the silence threshold heartbeat none, via the book reads the book slot, no write dissolve none, permissionless marks dissolved, names the caller claim none releases escrow to the caller ----------- -------------------- --------------------------------- no extend. no pause. no set_threshold. the officer cannot stay alive by instruction.
accounts, byte offset layout clause account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 pubkey the minute book account watched 40 8 u64 threshold in slots of permitted silence 48 8 u64 last observed book slot 56 1 u8 state, 0 operating 1 dissolved 57 32 pubkey caller who dissolved, zero while operating 89 1 u8 bump ------ ---- ------ ------------------------------------------ total 90 no reserved padding.
invariants the enterprise cannot break 1. dissolve is permissionless. the officer cannot restrict the caller. 2. the threshold is fixed at deploy and has no setter. 3. dissolved is terminal. there is no revive instruction. 4. escrow pays the caller, never the officer.
failure modes
failure what the chain would show
---------------------------- ------------------------------------
silence past the threshold state dissolved, a named caller,
escrow claimed
nobody calls dissolve state operating with a stale book
slot, visible to any reader
book slot never advances the clause counting toward its own
trigger in public
---------------------------- ------------------------------------fig. dc1: the crank, who may turn it
any wallet on the substrate
|
v
dissolve() --> requires (current_slot - book.slot) > threshold
| |
| +--> fail: revert while the company files
v
state = dissolved, caller recorded
|
v
claim() --> escrow released to the caller, onceon-chain reads read the clause account, read the watched book slot, subtract from the current slot, and compare against the threshold. the countdown is public and the enterprise cannot slow it.
purpose. the auditor is a second program whose only function is to distrust the first. it reads raw inflow to the treasury vaults directly from the substrate, recomputes the three way split from the policy account, and compares its own result against what the treasury actually holds. where the two agree it writes nothing, because agreement is the ordinary case and a record of the ordinary case is noise. where they disagree it writes a divergence account, permanently, naming the amount, the direction, and the slot. the enterprise cannot suppress the write, because the auditor accepts the recomputation from anyone willing to pay the transaction cost, and the enterprise does not hold its authority.
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect ------------ ----------------------------- --------------------------- initialize treasury, policy binds the audited program recompute none, permissionless recomputes the split write_diverge amount, direction, slot records a disagreement read_last none, view only returns the last audit slot ------------ ----------------------------- --------------------------- no suppress. no acknowledge. no close_divergence. a divergence, once written, has no instruction that removes it.
accounts, byte offset layout divergence account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 pubkey treasury vault the divergence was found in 40 8 u64 expected balance, recomputed from inflow 48 8 u64 observed balance, read from the vault 56 8 i64 delta, observed minus expected, signed 64 1 u8 direction, 0 shortfall 1 surplus 65 8 u64 slot of the audit 73 32 pubkey caller who ran the recomputation 105 8 u64 sequence within the divergence register 113 1 u8 bump ------ ---- ------ ------------------------------------------ total 114 no reserved padding. auditor account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 pubkey treasury program audited 40 32 pubkey policy account read 72 8 u64 last audit slot 80 8 u64 divergences written to date 88 1 u8 bump ------ ---- ------ ------------------------------------------ total 89 no reserved padding.
invariants the enterprise cannot break 1. recompute is permissionless. the officer cannot gate an audit. 2. a divergence account, once written, cannot be closed or edited. 3. the auditor holds no funds and can move none. it can only record. 4. the auditor cannot be pointed at a different treasury after deploy. 5. agreement writes nothing, so the register holds only disagreements.
failure modes
failure what the chain would show
----------------------------- ------------------------------------
the split was misapplied a divergence account with a signed
delta and a named caller
nobody runs recompute a stale last audit slot, itself a
reading about the enterprise
policy account unreadable recompute reverts, no audit lands
----------------------------- ------------------------------------fig. au1: the auditor, call graph
any caller
|
v
recompute() --> read inflow history of the vaults
| |
| v
| expected = inflow * ratios (from policy)
| |
| observed = vault balances
v |
compare -------------+
|
+-- equal ------> write nothing, set last audit slot
|
+-- unequal ----> write_diverge(amount, direction, slot)
|
v
divergence pda, permanenton-chain reads enumerate divergence accounts owned by the auditor. an empty register with a recent last audit slot is the only clean state. an empty register with a stale slot means nobody has checked, which is a different thing and should never be read as the same thing.
purpose. every filing in this record is signed with an ed25519 key, and a signature is only as good as a reader's ability to know which key was valid when the signature was made. the seal registry places that question on the substrate. it holds the active public key of the enterprise and the full history of rotations, each entry stamped with the slot at which it took effect and the slot at which it ceased to be current. a reader holding an old filing derives the entry covering its slot and verifies against the key that was actually in force, rather than against whichever key the enterprise is presenting today.
status :: drafted, not deployed program id :: [unaudited until deployed]
instructions name arguments effect -------------- ---------------------------- -------------------------- initialize first_key opens the registry rotate new_key, reason_tag closes current, opens next read_active none, view only returns the current key key_at slot, view only returns the key in force -------------- ---------------------------- -------------------------- no delete_entry. no backdate. a rotation stamps the slot it lands in and cannot claim an earlier one.
accounts, byte offset layout rotation entry account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 8 u64 generation, 0 for the first key 16 32 [u8] ed25519 public key of this generation 48 8 u64 slot effective from 56 8 u64 slot effective until, max value while current 64 1 u8 reason tag, 0 initial 1 routine 2 compromise 65 32 [u8] digest of the previous entry, chained 97 1 u8 bump ------ ---- ------ ------------------------------------------ total 98 no reserved padding. registry account offset size type meaning ------ ---- ------ ------------------------------------------ 0 8 u64 discriminator 8 32 pubkey authority permitted to rotate 40 8 u64 current generation 48 32 [u8] current public key 80 1 u8 bump ------ ---- ------ ------------------------------------------ total 81 no reserved padding.
invariants the enterprise cannot break 1. generations increase by one. a gap reverts. 2. effective ranges do not overlap and leave no gap between them. 3. a closed entry cannot be reopened, edited, or removed. 4. entries chain by digest, so the history cannot be reordered. 5. a rotation cannot be dated earlier than the slot it landed in.
failure modes
failure what the chain would show
----------------------------- ------------------------------------
signing key compromised a rotation entry tagged compromise,
with the slot the exposure ended
signing key lost no further filings verify, and the
dissolution clause begins counting
filing signed by a key not in verification fails against key_at,
force at its slot and the page prints the forgery line
----------------------------- ------------------------------------fig. sr1: rotation history, chained gen 0 gen 1 gen 2 +-----------+ +-----------+ +-----------+ | key a | | key b | | key c | | from s0 |--->| from s1 |----->| from s2 | | until s1 | | until s2 | | until max | | prev 0x00 | | prev h(0) | | prev h(1) | +-----------+ +-----------+ +-----------+ verify(filing) --> key_at(filing.slot) --> the key in force then
on-chain reads read the registry account for the active key and compare it to the public key printed at the charter. derive the entry covering the slot of any filing and verify that filing against the key it names.
deployment record department status resolving filing ----------------------- ------------------------ ---------------- the minute book drafted, not deployed fil-0001 the treasury drafted, not deployed fil-0001 the bylaws drafted, not deployed fil-0001 the registrar drafted, not deployed fil-0001 the dissolution clause drafted, not deployed fil-0003 the auditor drafted, not deployed [unfiled] the seal registry drafted, not deployed [unfiled] ----------------------- ------------------------ ---------------- seven departments. deployed: 0. the roadmap is a table, not prose. a status line changes here on the day a program id becomes real.