Skip to content

feat: gate mod/deploy/decentralize/deploy-all behind a revealed builder identity#413

Merged
UtkarshBhardwaj007 merged 1 commit into
mainfrom
feat/builder-identity-gate
Jun 17, 2026
Merged

feat: gate mod/deploy/decentralize/deploy-all behind a revealed builder identity#413
UtkarshBhardwaj007 merged 1 commit into
mainfrom
feat/builder-identity-gate

Conversation

@UtkarshBhardwaj007

Copy link
Copy Markdown
Member

What

Reserves the value-creating commands — mod, init, deploy, decentralize, deploy-all — for users who have revealed themselves (bound a verified identity on-chain via the playground-app's "Become a builder" flow). Anonymous accounts earn no competition points, so the CLI now refuses to act for them.

How it works

  • Predicate: "revealed" == playground-registry.getRootAccount(productH160) returns a non-zero bytes32. Anonymous accounts read back as the 32-zero-byte sentinel (the contract unwrap_ors a missing binding to zero and never reverts) — the exact predicate the playground-app uses (hasRevealedIdentity vs ZERO_ROOT).
  • Signer-free: the product H160 is derived from the persisted session (findSessionderiveSessionAddresses) and the read uses the keyless read-only revive origin (getReadOnlyRegistryContract), so evaluating the gate needs no phone tap, no account mapping, and no funding.
  • Signer-mode-agnostic: dev mode and --suri are gated too — the gate checks the session's reveal status, not the signing key. Once revealed, dev mode works exactly as before.
  • Outcomes: revealed proceeds silently (no UI flash on the happy path); not-logged-in, anonymous, and unverifiable (read failure → fail-closed) each render a yellow callout and exit 0 (soft, actionable — mirrors drip/status).
  • init is gated because it delegates to runModCommand.

Structure

  • src/utils/identity/identityGate.ts — pure logic (no React/Ink): checkIdentityGate + isAnonymousRoot.
  • src/commands/shared/IdentityGateNotice.tsx (yellow Callout), identityGateCopy.ts (testable copy), gateOrNotice.ts (enforceIdentityGate).
  • Gate wired into all four command entry points, before any signer resolution / phone work.

Tests

21 new unit tests (identityGate, identityGateCopy, gateOrNotice). Full suite 994 pass; typecheck, format:check, lint:license all clean. Changeset included (minor).

⚠️ Known follow-up — e2e suite

The e2e tests drive mod/deploy/decentralize with --suri and no logged-in session, so the gate (correctly) blocks them. This is an intended behavior change, not a logic bug — but the e2e harness needs a revealed-session fixture (and its deployer account revealed on-chain) before the e2e matrix is green again. I deliberately did not weaken the gate or add an env bypass. Tracking the e2e session story as a follow-up.

…er identity

The value-creating commands (mod, init, deploy, decentralize, deploy-all) now
require the signed-in session's product account to have revealed itself
on-chain via the playground-app. Anonymous accounts earn no competition
points, so the CLI refuses to act for them.

The gate derives the product H160 signer-free from the persisted session and
reads playground-registry.getRootAccount via the keyless read-only origin (no
phone tap, no mapping/funding needed). A non-zero bytes32 means revealed; the
32-zero-byte sentinel means anonymous — the same predicate the playground-app
uses. It is signer-mode-agnostic: dev mode and --suri are gated too, but once
revealed they work as before.

Blocked outcomes (not logged in, anonymous, or an unverifiable read) render a
friendly yellow callout and exit 0 (soft). Revealed users proceed silently.
@UtkarshBhardwaj007 UtkarshBhardwaj007 merged commit fcab7a0 into main Jun 17, 2026
14 of 20 checks passed
@UtkarshBhardwaj007 UtkarshBhardwaj007 deleted the feat/builder-identity-gate branch June 17, 2026 14:54
@github-actions

Copy link
Copy Markdown
Contributor

E2E Test Pass · ❌ FAIL

Tag: e2e-ci-pr · Branch: feat/builder-identity-gate · Commit: 935877c · Run logs

Cell Result Time
pr-preflight ❌ FAIL 3m33s
pr-install ✅ PASS 0m50s
pr-deploy-frontend ❌ FAIL 2m50s
pr-mod ❌ FAIL 2m42s
pr-deploy-cdm ✅ PASS 3m45s
pr-login-session ❌ FAIL 4m36s
pr-deploy-foundry ✅ PASS 0m46s
${{ matrix.cell }} ⏭️ SKIP 0m-1s
${{ matrix.cell }} ⏭️ SKIP 0m-10s

Sentry traces: view spans for this run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant