docs / deploy

view as .md

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:

  1. The verifiable browser demo (docs/deploy/demo.md) — deploys the registry + two demo tenants and ships landing/demo.html, a real passkey-signed deed verified client-side against a real chain read.
  2. The register/SDK/manifest funnel (just preview-wire, new in this preview) — wires that same registry address into the compiled-in canonical map and regenerates landing/registry.json + landing/.well-known/grantor-onboard.json, so register.html resolves a real tier table and Registry.canonical() works against 84532 for any consumer, not just the demo page.
  3. The onboarding manifest — already live at /.well-known/grantor-onboard.json (docs/ONBOARD.md); step 2 is what flips its chains entry for 84532 from absent to real.

2. Prerequisites (operator)#

  • Everything docs/deploy/demo.md §0 requires: Foundry (forge, cast, anvil), jq, Node, and npm exec --yes --package wrangler reachable (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 TREASURY addresscontracts/script/DeployTestnet.s.sol's _resolveTreasury requires TREASURY to be set explicitly on any chain other than anvil/ganache, and 84532 is 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 open register.html with 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.com and deciding whether to remove the noindex line in landing/_headers are launch-runbook items (docs/strategy/2026-08-01-launch-runbook.md, Phase 0 and Phase 4) — do not remove noindex for a developer preview; that flag is reserved for the real launch decision.

8. Funding upkeep + teardown#

  • docs/deploy/demo.md §8 — drawPeriod is permissionless and nothing auto-renews; periodically check the funded tenant's status and re-run SetupTenant.s.sol with a fresh FUND amount before it drops out of Grace, against the same registry (do not re-run demo-deploy, which deploys a brand-new registry and would orphan the address just wired in).
  • Teardown / reversal: just preview-wire is 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.

This page is also served as Markdown — agents should read that. The whole tree is indexed for machines in llms.txt.