Base Sepolia developer-preview runbook#
Operator-gated, like
docs/deploy/demo.md. This is the full sequence — deploy, wire, verify, ship — for standing up a free, reversible developer preview of the whole funnel on Base Sepolia. Nothing here should run unattended; several steps broadcast from a real (throwaway) key.
1. What this is#
A developer preview is the whole self-serve funnel — the browser demo, the register.html on-chain registration flow, an SDK resolving Registry.canonical(), and the onboarding manifest an agent discovers via a 401 — live on Base Sepolia (chainId 84532), at zero cost and fully reversible. It proves the product end to end against a real chain before anything commits to mainnet.
This is not mainnet launch. Registry.canonical()'s compiled-in map stays empty for chain 8453 (Base mainnet) until the launch runbook's Phase 3 mainnet deploy — see docs/strategy/2026-08-01-launch-runbook.md. The preview only ever touches 84532, and wiring it in is a one-command, one-commit, one-revert operation (§4, §6).
The preview is three layers, each already built and each documented separately — this runbook is the missing glue that sequences them:
- The verifiable browser demo (
docs/deploy/demo.md) — deploys the registry + two demo tenants and shipslanding/demo.html, a real passkey-signed deed verified client-side against a real chain read. - The register/SDK/manifest funnel (
just preview-wire, new in this preview) — wires that same registry address into the compiled-in canonical map and regenerateslanding/registry.json+landing/.well-known/grantor-onboard.json, soregister.htmlresolves a real tier table andRegistry.canonical()works against84532for any consumer, not just the demo page. - The onboarding manifest — already live at
/.well-known/grantor-onboard.json(docs/ONBOARD.md); step 2 is what flips itschainsentry for84532from absent to real.
2. Prerequisites (operator)#
- Everything
docs/deploy/demo.md§0 requires: Foundry (forge,cast,anvil),jq, Node, andnpm exec --yes --package wranglerreachable (Cloudflare Pages deploy, §7). - A deploy keypair, generated and held with the same hygiene as any other operator key in this repo (Tails session recommended; never paste a private key into chat or a committed file).
docs/deploy/demo.md§1 (cast wallet new) is the exact recipe — this key becomes the deployer, the funded demo tenant's admin, and the origin-vouch signer. - Base Sepolia faucet ETH for that key — a few cents' worth covers the whole deploy (MockUSDC is minted free; only gas costs anything). Pick one of the faucets named in
docs/deploy/demo.md§1 (Coinbase Developer Platform, Alchemy, thirdweb). - A throwaway
TREASURYaddress —contracts/script/DeployTestnet.s.sol's_resolveTreasuryrequiresTREASURYto be set explicitly on any chain other than anvil/ganache, and84532is real Base Sepolia, so it will not silently default here. The treasury address is otherwise meaningless for a preview deploy (draws just accumulate testnet MockUSDC nobody redeems) — the deployer address itself is fine; do not reuse a mainnet treasury candidate (docs/deploy/demo.md§2).
3. Deploy the registry + demo#
Run the demo's own deploy generator against Base Sepolia:
RPC=https://sepolia.base.org \
DEPLOYER=0x<your funded throwaway private key> \
TREASURY=0x<your throwaway treasury address> \
ORIGIN=<the origin you will serve landing/ from> \
AUDIENCE=<same as ORIGIN> \
CHAIN_ID=84532 \
EXPLORER_BASE=https://sepolia.basescan.org \
OUT=landing/demo/demo-config.json \
just demo-deploy
This is docs/deploy/demo.md §3, verbatim — read that runbook for the full detail (what the script does, the printed GrantorRegistry=0x... address to save, the "every run deploys a brand-new registry" warning, and the local-fork rehearsal in its closing section). The short version: it deploys MockUSDC + a fresh GrantorRegistry, stands up tenant 1 funded to Active and tenant 2 created-but-unfunded (Inactive), signs the origin vouch for ORIGIN, and writes landing/demo/demo-config.json.
Save the GrantorRegistry address printed at the end (also recoverable from landing/demo/demo-config.json's registry field) — the next step needs it.
4. Wire the register/SDK/manifest side#
just preview-wire <GrantorRegistry addr from step 3>
This is Task 1's recipe (justfile, near onboard-gen): it writes (84532, "<addr>") into CANONICAL_REGISTRIES in crates/grantor-sdk-core/src/registry.rs (which stays &[] — empty — until an operator runs this), then runs just onboard-gen to regenerate landing/registry.json and landing/.well-known/grantor-onboard.json from the now-populated map. Review before committing:
git diff crates/grantor-sdk-core/src/registry.rs landing/registry.json \
landing/.well-known/grantor-onboard.json
Both landing/registry.json and the onboarding manifest should now carry a "84532" entry pointing at the deployed registry. Then:
TZ=UTC git commit
(the pre-commit hook refuses a non-UTC-timezone commit). After this commit, register.html resolves a real tier table on 84532, Registry.canonical() returns the deployed address for any SDK consumer targeting Base Sepolia, and any agent that discovers the onboarding manifest sees a live chain entry instead of an absent one.
5. Verify#
- Serve
landing/locally (cd landing && python3 -m http.server 8000) and openregister.htmlwith a wallet connected to Base Sepolia — it should resolve a real registry address and tier table instead of the "this chain has no registry" honesty-gate message (landing/register.js). - The demo (
docs/deploy/demo.md§6, once deployed to Pages per §7 below) reads green: "Verify a real deed" mints and verifies against the funded tenant; "See the billing gate reject an unpaid tenant" is refused against the unfunded one. - Confirm the manifest carries the chain entry:
``bash curl -s https://<your served origin>/.well-known/grantor-onboard.json \ | jq '.chains."84532"' ``
(or, before it's deployed anywhere, read the local file: jq '.chains."84532"' landing/.well-known/grantor-onboard.json).
6. Local-anvil rehearsal (free, before touching real Sepolia)#
Rehearse the entire sequence — deploy generator and the wiring recipe — against a local fork of Base Sepolia, with no faucet and no real funds. This mirrors docs/deploy/demo.md's own closing "Fork-testing this runbook" section, extended one step further to cover preview-wire:
anvil --fork-url https://sepolia.base.org > /tmp/fork.log 2>&1 &
sleep 4
RPC=http://localhost:8545 \
DEPLOYER=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
TREASURY=0x000000000000000000000000000000000000dEaD \
ORIGIN=http://localhost:8000 AUDIENCE=http://localhost:8000 \
CHAIN_ID=84532 EXPLORER_BASE=https://sepolia.basescan.org \
OUT=/tmp/demo-config.fork.json \
just demo-deploy
export REG=$(jq -r .registry /tmp/demo-config.fork.json)
just preview-wire "$REG"
git diff --stat crates/grantor-sdk-core/src/registry.rs landing/registry.json \
landing/.well-known/grantor-onboard.json # should show the 84532 entry
kill %1
Then revert — this is a rehearsal, not the real deploy, and the map must stay empty until a real Base Sepolia address exists:
git checkout -- crates/grantor-sdk-core/src/registry.rs landing/registry.json \
landing/.well-known/grantor-onboard.json
Do this revert either entirely before making any other edits, or entirely after any other pending edits are already committed — git checkout -- restores those three files to HEAD, which clobbers any uncommitted work on them too (the same lesson Task 1's own rehearsal recorded).
7. Then (separate step): ship the landing page#
Deploying landing/ to Cloudflare Pages and attaching a real domain is its own follow-up, not part of wiring the registry:
docs/deploy/demo.md§5 (wrangler pages deploy/just landing-deploy) is the deploy mechanism, unchanged by this preview.- Attaching
chaingrantor.comand deciding whether to remove thenoindexline inlanding/_headersare launch-runbook items (docs/strategy/2026-08-01-launch-runbook.md, Phase 0 and Phase 4) — do not removenoindexfor a developer preview; that flag is reserved for the real launch decision.
8. Funding upkeep + teardown#
docs/deploy/demo.md§8 —drawPeriodis permissionless and nothing auto-renews; periodically check the funded tenant's status and re-runSetupTenant.s.solwith a freshFUNDamount before it drops out ofGrace, against the same registry (do not re-rundemo-deploy, which deploys a brand-new registry and would orphan the address just wired in).- Teardown / reversal:
just preview-wireis reversible the same way its own rehearsal (§6) is — restore the empty map:
``bash git checkout -- crates/grantor-sdk-core/src/registry.rs landing/registry.json \ landing/.well-known/grantor-onboard.json ``
(as a committed change, revert with a normal git revert of the wiring commit instead). The Base Sepolia contracts themselves stay on-chain either way — harmless, testnet-only, no real funds — exactly like docs/deploy/testnet.md's teardown note.
Anonymity notes#
Same posture as every other deploy runbook in this repo (docs/deploy/testnet.md § Anonymity notes, docs/deploy/demo.md §1): fund the deploy key from a fresh source, never reuse a doxxed wallet, and commit under the existing grantor-dev identity with TZ=UTC.