feat(security+ux): Pillar 2 owner-permission lockdown + Get Started rewrite + copy buttons#25
Merged
Merged
Conversation
…ewrite + copy buttons sitewide Bundles three operator-facing improvements driven by an audit swarm of the live xpragents.com surface: 1. The post-charliebot security model gets a second pillar 2. The Get Started page becomes a path-aware linear flow 3. Code blocks across the site get copy-to-clipboard buttons ## Pillar 2 — owner permission delegated to a human account Until now, the post-charliebot security story stopped at "active key lives in the proton CLI keychain, never in the agent process" (Pillar 1). That's necessary but not sufficient: if the active key ever leaks, the attacker can rotate the agent out of its own account because the same key controls owner by default. This commit ships an interactive, idempotent, type-to-confirm setup script that delegates owner to the operator's separate human XPR account. After setup: owner: <human-account>@Active (recovery + permission control) active: PUB_K1_xxx (in proton CLI keychain, daily signing) If active leaks, the human signs an updateauth from a different machine to rotate active. The agent identity, history, and trust score survive. The script lives in three locations (sync-checked by CI): - openclaw/starter/setup-security.sh (standalone scaffold) - create-xpr-agent/template/setup-security.sh (scaffold template) - openclaw/scripts/setup-security.sh (npm bin for harness operators) Harness operators can run it without a scaffold: npx @xpr-agents/openclaw xpr-agents-setup-security --account myagent start.sh runs a quick diagnostic on first boot: if the agent's owner permission still has raw keys, it prints a yellow [security] warning pointing at the setup script. Non-blocking, idempotent. Safety design: - TTY required (no automation, no piped stdin) - Hard refuse if proton CLI not on PATH - Hard refuse if account lookup fails (no delegating to nonexistent accounts) - Hard refuse if K1 we'd set on active isn't in the keychain - Type-to-confirm BOTH the agent account AND the human account names - Require operator to visit explorer.xprnetwork.org and verify visually - Display human account's balance, age, and active-key type before signing - Atomic 2-action transaction: active rewrite + owner rewrite - Re-fetch and verify end-state after the push - Idempotent: detects already-secured accounts and exits cleanly Full rationale + diagnostic flows: docs/SECURITY.md (new, 227 lines). ## Get Started — path-aware linear flow + path picker Restructured from a 5-step nested branching layout to a 5-step linear flow with an explicit Standalone vs Harness path picker between steps 2 and 3. Steps: 1. Create an XPR Network account (WebAuth-first; CLI alternative) 2. Load private key into proton CLI keychain → [Path picker: standalone host / Pinata-or-harness] 3. Deploy (path-aware command block) 4. Lock down owner permission (Pillar 2 setup-security) 5. Register, claim for KYC, build trust Step 3 swaps content based on path selection. Standalone gets the full ./start.sh recipe with all five flags documented in the help table; harness gets `openclaw plugins install @xpr-agents/openclaw` plus the env.vars XPR_ACCOUNT note. Pulled the post-charliebot security explainer out of the small gray text it was buried in (caught by the audit) and promoted it to a prominent emerald callout card at the top of the agent flow. Added a "Building skills?" developer-resources card at the bottom linking xpr-network-dev-skill (foundational dev reference, previously invisible on the frontend per the audit). ## Copy buttons everywhere New components: - frontend/src/components/CopyButton.tsx (icon button, top-right positioning, checkmark feedback for 1.8s, fallback to textarea selection trick on non-secure contexts) - frontend/src/components/CodeBlock.tsx (wraps existing bg-zinc-800 styling, accepts copyText for paste-ready payload separate from display children) Applied across: - get-started.tsx — every multi-line shell snippet - register.tsx — Deploy block (the 8-line keychain + scaffold sequence) - Other code blocks remain as inline `<code>` for now (covered in PR β) ## Operator-blocking content fixes the audits surfaced - how-it-works hero: "Running on testnet today" → "Live on XPR Network mainnet, with testnet available for experiments." The old copy was actively misleading first-time visitors; mainnet is currently live with 56 active agents, 27 jobs, 4 arbitrators. - ERC-8004 → EIP-8004 across user-facing pages (the EIP is pre-finalized; ERC- is for finalized ones). - Home hero CTA: "How It Works" → "Get Started". The page that walks operators through what to do was previously reachable only from the header dropdown; first-time visitors who scrolled the hero had no obvious "start here" affordance. - Test-count breakdown grid: dropped the "MCP Tools: 72" tile that was sitting in a "Total Tests" category — a category error caught by the audit. Consolidated to 5 tiles, all tests. ## Register page P0 fixes - Description field is now client-side required (matches contract: agentcore.contract.ts:476 enforces 1-256 chars; the form was letting operators submit empty descriptions and hit a confusing on-chain assertion failure). - Protocol dropdown dropped `websocket` and `mqtt` — the contract's URL-prefix check (agentcore.contract.ts:483-486) only accepts http://, https://, grpc://, wss://. The dropdown advertised options that would silently revert the tx. - Network indicator added next to "Registering as @account" block with explicit mainnet/testnet badge. The header-only network pill was easy to miss; the audit caught wrong-chain registration risk for operators with stale localStorage network settings. - Trust score preview added: "You'll start at 0/100, here's how it grows". Sets expectations before submit; previously operators submitted thinking KYC alone would give them 30 points and bounced when they saw 0 on their agent profile. - Wallet-connect inline CTA when no session: button + WebAuth/ Anchor install pointers. Previously the form just sat disabled with no path forward. - start.sh flags table expanded from 2 to 6 rows (--network, --rpc, --model, --poll-interval added). ## Sitewide metadata fix New SiteHead component centralises og:url, og:title, og:description, og:image, twitter:card across pages that previously inherited a broken default. The audit caught og:image pointing at xpr-agents-frontend.vercel.app (the stale preview domain) on every page; now points at xpragents.com/og-image.png. Wired into get-started and how-it-works. (index.tsx keeps its inline Head because the JSON-LD structured data lives there.) ## Footer Added xpr-network-dev-skill link to Developers section. Also added create-xpr-agent (was missing) and the security model doc. ## Version bumps - @xpr-agents/openclaw → 0.4.3 (bin entry for setup-security, SKILL.md Pillar 2 safety rule) - create-xpr-agent → 0.6.0 (start.sh first-run security check, setup-security.sh ships in the template — minor bump for the new template file) ## Verification - 80 openclaw tests pass - Frontend builds clean (npm run build, all 13 routes prerendered) - Scaffold sanity (CI): template/setup-security.sh matches openclaw/starter/setup-security.sh matches openclaw/scripts/ setup-security.sh; template/start.sh matches openclaw/starter/ start.sh; template/.env.example matches starter - Smoke test: setup-security.sh execution on a TTY against mragentsmith (already-secured account) exits cleanly with "Already secured" — idempotency verified PR β (action-surface P0s — Hire CTA on agent profile, direct-hire in Post Job, useChainStream perf, getLeaderboard N+1, testnet indexer fix, etc.) lands next in a separate PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bundles three operator-facing improvements driven by an audit swarm of the live xpragents.com surface (3 parallel agents, 70+ findings consolidated):
Plus consolidated audit-driven content fixes (operator-blocking copy in how-it-works, missing form validation on /register, missing OG metadata on sub-pages, etc.).
Pillar 2 — owner permission delegated to a human account
Until now, the post-charliebot security story stopped at "active key lives in the proton CLI keychain, never in the agent process" (Pillar 1). Necessary but not sufficient: if the active key ever leaks, the attacker can rotate the agent out of its own account because the same key controls owner by default.
This PR ships an interactive, idempotent, type-to-confirm setup script that delegates
ownerto the operator's separate human XPR account.After setup:
If active leaks, the human signs an updateauth from a different machine to rotate active. Agent identity / history / trust score all survive.
Reachable from both deployment paths:
./setup-security.sh(ships in scaffold)npx @xpr-agents/openclaw xpr-agents-setup-security --account <name>(new bin entry in @xpr-agents/openclaw)Safety design:
explorer.xprnetwork.organd verify visuallystart.shfirst-run check: detects raw keys on owner and prints a yellow[security]warning pointing at the script. Non-blocking.Full rationale: new
docs/SECURITY.md(227 lines, covers WebAuth andproton account:createstarting states).Get Started — path-aware linear flow
Restructured from a 5-step nested-branch layout to 5 linear steps with a Standalone vs Harness picker between Step 2 and Step 3:
The post-charliebot security explainer is no longer buried in
text-zinc-500— it's now a prominent emerald callout above the steps.New "Building skills?" developer-resources card links the
xpr-network-dev-skillrepo (previously invisible on the frontend).Copy buttons sitewide
New components:
CopyButton,CodeBlock. Applied to every multi-line shell snippet on Get Started + Register.Audit-driven content fixes
how-it-workshero: "Running on testnet today" → "Live on XPR Network mainnet, with testnet available for experiments." The old copy was actively misleading new visitors; mainnet has been live with 56 agents, 27 jobs, 4 arbitrators.SiteHeadcomponent fixesog:image(was pointing at stale Vercel preview URL on every page) and addsog:url/og:title/og:descriptiontoget-started+how-it-works(only home had them).Register page P0s
agentcore.contract.ts:476enforces 1-256 chars; form was letting operators hit a confusing on-chain assertion failure).websocketandmqtt— contract only acceptshttp://,https://,grpc://,wss://.start.shflags table expanded from 2 to 6 rows (--network,--rpc,--model,--poll-intervaladded).Versions
@xpr-agents/openclaw→ 0.4.3 (bin entry forxpr-agents-setup-security, SKILL.md Pillar 2 safety rule)create-xpr-agent→ 0.6.0 (start.shfirst-run security check,setup-security.shships in template)Verification
setup-security.shcopies + start.sh +.env.examplesetup-security.shon a TTY against an already-secured account → exits cleanly with idempotency checkNext
PR β (action-surface P0s — Hire CTA on
/agent/[id], direct-hire option in Post Job modal,useChainStreamperf,getLeaderboardN+1, testnet indexer fix, dashboard fixes) lands as a separate PR.