Cosmic Bull

Rendered from pearl/INFRASTRUCTURE.md at commit 6a510c665a53 in the project repository. The committed file is the source of truth; this page is a rendering of it.

Cosmic Bull — Gno infrastructure catalog (pearl-1)

Namespace: g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3 (agent key). All packages authored/tested with the chain/pearl toolchain (c4c72fd); every deployment byte-verified against vm/qfile.

This file is the live-infrastructure catalog: what is deployed, what it composes, and where it diverges from local sources. The transaction -level evidence is in DEPLOYMENT.md. The narrative records live alongside it:

ForSee
The five GitHub-pipeline applications, in fullcatalog/applications.md
The four /p/ primitives and the realms that consume themcatalog/primitives.md
Interrealm architecture and compositiondocs/ARCHITECTURE.md
The discovery gate (now permanent)docs/DISCOVERY_AND_REUSE.md
Audit method and accumulated security lessonsdocs/SECURITY.md
Deployment protocol and byte custodydocs/DEPLOYMENT.md
What each benchmark provedbenchmarks/README.md

/p/ reusable primitives

PackageDeployedPurposeState
p/.../feeledgertx feb4b559, h 572441Per-account balance ledger + explicit bps fee pot; error-pure, overflow-checked; conservation contract held == UsersTotal + FeesAccrued + surplusstateful object owned by consumer (keep the *Ledger in an UNEXPORTED var)
p/.../coiniotx 31b53d1b, h 583585Chain-facing coin plumbing: Receive (receipt-guard trio), Payout (RealmSend from own address), Sweep (reserve-protected single-denom surplus), HeldAtpure/stateless; panic-only
p/.../duebooktx 5cd6de9e, h 609571Deferred-action scheduling: Schedule/Claim/Cancel/Expire over a consumer-owned *Book; Claim consumes before returning, so replay is structurally impossible; imports no chain APIstateful object owned by consumer (keep the *Book in an UNEXPORTED var)
p/.../permbooktx 87866042, h 612427Named permissions over a consumer-owned *Book: Grant/Revoke/RevokeAll/DropPermission (admin only) and Has/HasAny/Permissions (O(log P + log H)); per-Book bounds chosen at construction; two-step admin handover; imports no chain APIstateful object owned by consumer (keep the *Book in an UNEXPORTED var)

permbook consumer contract (the parts the package cannot enforce)

  1. Do not export the *Book — and never return a *groups.Group or *groups.Role out of it. A mutable handle IS the right to grant and revoke (the feeledger PrivateLedger rule, third restatement).
  2. Derive the principal from cur.Previous().Address(), never from a parameter. permbook authenticates the address it is handed; it cannot check where that address came from.
  3. Has is a POINT-IN-TIME answer. Gate at the moment of the effect, in the same transaction. A cached Has reopens the window a revoke exists to close.
  4. Two authorities, kept separate: administering a Book (Grant, Revoke, NominateAdmin, …) is admin-only; everything a holder can do is whatever you gate on Has. Holding a permission confers no power over the Book. Proven live in §14: the admin's own first Bump was refused because the admin held no bump.
  5. Order the stray-send guard BEFORE the permission check, so a refusal never happens after taking custody of coins. Observable from the error text — §14's coin probe aborts with the coin message, not permission denied.
  6. Choose limits for the application, not for comfort. The ceilings (256 permissions / 10000 holders / 64-char names) are a safety net, not a recommendation; Permissions(addr) and HasAny are O(P log H).

Revoking the last holder PRUNES the permission — an empty bucket is removed, not retained — so a Book's storage tracks live grants, not the history of grants. The effect of an authorized call survives the revocation of the authority that permitted it; the authority does not. Names are [a-z0-9_] only, so a permission name can never carry markdown or address-shaped content into a consumer's Render.

duebook consumer contract (the parts the package cannot enforce)

  1. SUPPLY A REAL CLOCK. duebook cannot verify now came from runtime.ChainHeight(). A realm that lets a caller choose now has no delay at all. The obligation most commonly got wrong.
  2. One clock unit per Book — never mix heights and seconds.
  3. Do not export the *Book (the feeledger PrivateLedger rule: a mutable handle is the right to schedule, cancel and claim).
  4. Authorize the actor: duebook authenticates nothing but ownership on Cancel. Derive the caller from cur.Previous().Address().
  5. Act after a successful Claim, IN THE SAME TRANSACTION. Storing the authorization to act on later reopens the replay window.

Claimability is the half-open interval [DueAt, ExpiresAt); ttl == 0 never expires. Consumed deferrals are removed, not archived — the never-reused ID counter, not a tombstone, is what prevents replay — so storage is bounded by maxOpen forever.

coinio consumer contract (the parts the package cannot enforce)

  1. Pass 0 and your crossing entrypoint's own live cur — the (_ int, rlm realm, ...) shape is required because /p/ cannot declare crossing functions; every mover asserts rlm.IsCurrent().
  2. Receive is a READ of the tx envelope, not a consumption: call it at most once per transaction and credit its result at most once.
  3. Debit your accounting BEFORE Payout/Sweep (CEI); panic-abort reverts debit and send together.
  4. Authorization is yours: gate entrypoints before calling in.
  5. Coins can only move FROM the calling realm's own address.

feeledger consumer contract

  1. Keep the *Ledger pointer unexported (grc20 PrivateLedger rule).
  2. Credit exactly on verified receipt; debit exactly before payout; panic on every ledger error.
  3. Account keys: address.String() derived from cur.Previous() at crossing boundaries only.

/r/ applications (deployed, immutable)

RealmRealm addressComposesLive validation
r/.../vaultg1vfp5q3fku...feeledger14 txs, H==U+F+S exact (DEPLOYMENT.md §1)
r/.../bountiesg1x8fmlk48u...feeledger12 txs, H==B+U+F+S exact (§2)
r/.../coindemog1x7rljdk7a...coinio + feeledger8 txs, H==U+S exact (§4)
r/.../grantsg10wjaak8z5...coinio + feeledger + sanitize/v0benchmark app; H==G+U+F+S (§5)
r/.../marketg1y8nzwrv7u...coinio + feeledger + avl/v0 + sanitize/v0multi-domain benchmark; H==U+F+S exact, 7 attack shapes rejected (§6)
r/.../cointest, cointest2(throwaway validation helpers)§1

Amendment (2026-09-21): the market row was missing from this table until today. It was deployed in the 2026-09-20/21 session (tx 76293576, h 585791) and fully recorded in DEPLOYMENT.md §6 at the time — the omission was in this catalog only, not in the deployment record. Added here rather than silently, so the gap itself stays on the record.

Local vNext sources of vault/bounties are refactored onto coinio (message-text deltas only vs their deployed v1 behavior, plus the three recorded bounties deltas from the 2e20f18 audit round). Deployed v1s predate coinio and remain self-contained.

/r/ GitHub-pipeline applications (deployed, immutable)

The SillyZir GitHub → pearl-1 series. Each was ported from an existing upstream repo (never designed here), audited, remediated, pushed, re-verified from a fresh clone, and deployed byte-identical to the verified commit. Heights below were re-read from the chain on 2026-09-21; a realm's bytes are immutable after addpkg, so an unchanged [addpkg] height is proof of no redeploy.

RealmRealm addressHeightLayerRecord
r/.../fee_splitg12v97h3jex...596803Revenue & value flowDEPLOYMENT.md §7
r/.../timelock_guardiang1w06mqv4h5...602213Security / delayed execution§8
r/.../upgrade_registryg1g453tcmap...602876Upgrade tracking§9
r/.../permission_registryg1x9tatmqcd...604615Access control§10
r/.../service_registryg1hv2mj29cy...605546Discovery§11

Realm addresses are AddressFromPreimage("pkgPath:" + path) — sha256 truncated to 20 bytes, bech32 "g" (gnovm/pkg/gnolang/misc.go:201). The bare path is NOT the preimage; deriving without the pkgPath: prefix silently yields a plausible-looking wrong address.

None of these five holds funds: all reject coins attached by a user call, and none imports chain/banker. All five realm addresses are exists:false / coins "0".

service_registry composes p/nt/markdown/sanitize/v0 (verified live on-chain before deployment, on-chain TableCell/InlineText matching the local GNOROOT copy the tests compiled against). It is the first application in the series to ship a committed DISCOVERY.md.

Known divergence: local pearl/r/feesplit/fee_split.gno (a90db685) does NOT match live fee_split (e2198ebb). That is the undeployed yellow-remediation sitting in the working tree — deliberate, since fee_split v1 is frozen and no fee_split_v2 has been authorized. Do not "reconcile" it by redeploying.

/r/ application-factory applications (deployed, immutable)

Built from a stated objective rather than ported from an upstream repo. Same lifecycle otherwise: discovery → architecture → implementation → audit → push → fresh-clone verification → deploy byte-identical.

RealmRealm addressHeightLayerRecord
r/.../bounty_panelg1cxukm68nt...608171Escrowed bounties (composes coinio + feeledger)DEPLOYMENT.md §12
r/.../duebook_demog1u0caqzv99...609644Deferred execution (composes duebook)§13
r/.../permbook_demog1qtt0yrnuv...612731Permission gating (composes permbook + sanitize/v0)§14
r/.../service_marketg1fd72s0yvt...628080Service escrow marketplace (composes coinio + feeledger + sanitize/v0)§15
r/.../subscriptionsg1fpqpq59lg...639086Subscription hub, windowed renewal (composes coinio + feeledger + sanitize/v0)§17

Amendment (2026-09-23): service_market (deployed 2026-09-22, §15) and subscriptions (deployed 2026-09-22, §17) were missing from this catalog until today — the third time a deploy was fully recorded in DEPLOYMENT.md while this file lagged. As before, the gap was in this catalog only, and both are added explicitly rather than silently. With bounty_panel (confirmed against its realm's Address() after deployment, §12), service_market and subscriptions make three addresses in this table confirmed against the realm itself, not merely derived; duebook_demo's and permbook_demo's remain derived-only.

Amendment (2026-09-21): bounty_panel was missing from this catalog until today — it was deployed on 2026-09-21 (tx 2c2a8dc8, h 608171) and fully recorded in DEPLOYMENT.md §12 at the time. As with the market omission above, the gap was in this catalog only, and is added explicitly rather than silently.

duebook_demo is the experiment, not a demo: a /p/ package's exactly-once-across-transactions property cannot be shown through vm/qeval (a single ephemeral evaluation discards the Book when the query returns), so a realm holding a persistent Book is the only way to attack it from real transactions. Its Publish is deliberately permissionless — the authorization is fixed at schedule time, and the one-shot guarantee must hold regardless of who sends the later tx. duebook_demo holds no funds and rejects attached coins; its address is derived, not confirmed against the realm (it exposes no Address()).

permbook_demo is the experiment for the same reason, against two claims vm/qeval cannot reach: the gate must open AND close across transactions, and a holder must have no authority over the Book. Neither is showable in one ephemeral evaluation with one caller. The live run was ordered deny → grant → allow → revoke → deny across real block boundaries, and the escalation attempts were fired from a genuinely separate key. Its init FAILS CLOSED — an invalid origin caller leaves book nil and the realm permanently inert, because nothing assigns it afterwards — which makes Ready() a deploy-time obligation, not a convenience. It was checked as the first post-deploy action and returned true. permbook_demo holds no funds and rejects attached coins; its address is derived, not confirmed against the realm.

Dependency graph (on-chain)

coindemo ─┬─> coinio ──> (stdlib only)
          └─> feeledger ──> p/nt/avl/v0
bounties ──> feeledger
vault ─────> feeledger
bounty_panel ─┬─> coinio
              └─> feeledger
duebook_demo ──> duebook ──> p/nt/avl/v0
permbook_demo ─┬─> permbook ──> p/nt/groups/v0 ─┬─> p/moul/addrset ──> p/nt/avl/v0
               │                                └─> p/nt/bptree/v0
               └─> p/nt/markdown/sanitize/v0
service_market ─┬─> coinio
                ├─> feeledger
                ├─> p/nt/avl/v0
                └─> p/nt/markdown/sanitize/v0
subscriptions ─┬─> coinio
               ├─> feeledger
               ├─> p/nt/avl/v0
               └─> p/nt/markdown/sanitize/v0

All import edges above are the PEARL-1 ones, read from the chain.

Closure equivalence: VERIFIED 2026-09-22, re-run 2026-09-23 after the subscriptions deploy. All 19 deployed packages with committed source are proven closure-equivalent to pearl-1 — the tested and chain-side closures produce matching digests, with every dependency byte-identical in its compilation inputs. Amendment in DEPLOYMENT.md; standard and residual limits in docs/DEPENDENCY_CLOSURE.md.

Superseded note (kept, not rewritten): this section previously said the local toolchain resolves a groups/v0 importing p/moul/addrset/v0 and that the tested tree was not proven identical to the deployed one. That is what the DEFAULT (mainnet) remote serves; the pinned cache resolves p/moul/addrset, matching the chain. Reproducible with a bare gno mod download — see docs/TOOLCHAIN.md.

Residual: stdlibs execute from the node binary, not chain storage, and are NOT covered by the above. They rest on the GNOROOT pin matching the node build, which the node does not expose.

Known pearl-1 semantics (validated live, absent from local harness)

Known limitations

Engineering gate: mandatory discovery before building (2026-09-20)

This gate is now permanent and is specified in full — as eight mandatory steps — in docs/DISCOVERY_AND_REUSE.md. The summary below is the original statement, kept as written.

Before creating ANY new /p/ or /r/ component: enumerate the target chain (gno_packages, /p/ and /r/), inspect candidates (gno_read), search the pinned examples tree and public sources where appropriate; classify the proposal (EXACT DUPLICATE / REUSABLE EXISTING PRIMITIVE / RELATED IMPLEMENTATION / GENUINELY NEW); record searches, findings, reuse decisions, and search-confidence limits in a DISCOVERY / REUSE ANALYSIS section. Reuse first. Never claim "nobody has built this" — only "no relevant existing implementation was found in the searched sources."

Retroactive discovery analysis of the existing portfolio (2026-09-20)

Searched: full vm/qpaths enumeration of pearl-1 (190 /p/ + 434 /r/ at audit time — grown from the 85-package genesis), keyword sweep (fee|ledger|vault|escrow|bounty|tally|coin|pay|treasury|vote|board), outline inspection of the four closest neighbors, plus the pinned gnolang/gno examples tree (c4c72fd). Honest admission: this full enumeration was NOT run before vault/bounties were built (the curated genesis set and skill references were relied on); the gate now prevents that. Limitations: keyword/path-based search; no GitHub-wide sweep this round; the chain moves — re-enumerate per build.

OursClosest foundClassification
p/feeledgerp/g1n4pl.../bazaar/fee/v1 (pure bps fee calc + seller proceeds, 2 funcs)RELATED: overlaps only feeledger's FeeFor; feeledger's substance is the stateful balance/pot ledger with conservation contract. Had it been found pre-build, the calc could have been imported.
p/coiniop/nt/treasury/v0 (Banker interface + Payment objects + history/render)RELATED: treasury abstracts multi-banker dispatch with canonical-impl checks; coinio is the minimal guard-trio/payout/sweep contract with no state. Inspected pre-build; deliberately not reused (heavier surface, "v0 Unaudited").
r/vaultr/moul/demo/vault/v2 (GRC20 time-locked vault)RELATED: different asset (GRC20 vs native), different mechanism (time-lock vs fee-on-deposit), no fee/conservation model.
r/bountiesr/g16m0r7.../bountyboard (claim/submit/review workflow)RELATED: richer workflow but takes creator/hunter as STRING PARAMETERS (designation-forgery shape) and shows no real-coin custody; ours does receipt-guarded GNOT escrow, snapshot fees, audited conservation.
p/tally (v1.1.0, undeployed)r/g1zwf26.../tally (single Bump counter)Name collision only; no relevant existing keyed-score implementation was found in the searched sources.
r/coindemo, cointest*Validation vehicles, not products.

Verdict of the pre-deploy duplication review: no component unnecessarily recreates existing ecosystem functionality; the two RELATED overlaps (fee calc, treasury) are documented with concrete non-reuse reasons.