Skip to content

fix(operator-path): audit-driven blockers from 0.4.0 / 0.5.0 ship#21

Merged
paulgnz merged 1 commit into
mainfrom
fix/audit-blockers-0.4.1
May 13, 2026
Merged

fix(operator-path): audit-driven blockers from 0.4.0 / 0.5.0 ship#21
paulgnz merged 1 commit into
mainfrom
fix/audit-blockers-0.4.1

Conversation

@paulgnz
Copy link
Copy Markdown
Collaborator

@paulgnz paulgnz commented May 13, 2026

Three parallel operator-path audits (npm openclaw page, npx create-xpr-agent flow, docs/PINATA.md) traced what an operator actually hits when following the docs we just published. They surfaced one code bug, three drift-driven config bugs, the wrong tool list on the npm page, and several blocking omissions. Bundle for fast turnaround so the corrected READMEs land on npm immediately.

Operator-blocking bugs

  • Plugin manifest's indexerUrl default was http://localhost:3001 — any harness that pre-populated config from the schema hit ECONNREFUSED localhost:3001 on all 4 indexer-backed read tools. Fixed → public indexer.
  • starter/start.sh:157 keychain check used a case-insensitive substring grep against raw proton key:list JSON. False-positived on PUB_K1_… substrings, false-negatived when chain lookup at key:add time was stale. Replaced with "account": "<name>" exact match + a fallback that distinguishes "no keys" from "keys but not yet linked."
  • POLL_INTERVAL had three sources of truth: 30s (start.sh), 14400s = 4h (agent runner code default), 30s (QUICKSTART). 30s hammered shared RPC; 4h was legacy. Aligned to 60s.
  • MAX_TRANSFER_AMOUNT mismatch: start.sh wrote 1000000 (100 XPR) to .env while .env.example and README said 10000000 (1000 XPR). 10× silent cap. Aligned to 10000000.
  • XPR_NETWORK default split: 4 code sites fell back to testnet, 2 to mainnet, .env.example and start.sh disagreed. Aligned everything to mainnet.
  • Stale "Check .env" error message after auto-registration pointed operators at .env for a private key the agent refuses to start with. Rewrote with proton key:list / key:add and an explicit "do NOT add XPR_PRIVATE_KEY" callout.

Removed misfeatures

  • start.sh recursive find ~/Documents/projects -name .env hunting for TELEGRAM_BOT_TOKEN. Undocumented, surprised operators, leaked tokens across projects on multi-tenant boxes. Now strict opt-in.
  • HYPERION_ENDPOINTS documented in three READMEs but referenced nowhere in code. Ghost variable, rows removed.

Documentation rebuilds

openclaw/README.md (the npm landing page):

  • Replaced the "Tools (72 total)" section. Old list contained 18 tool names that don't exist in shipped code (xpr_stake_agent, xpr_add_plugin, xpr_approve_job, xpr_resolve_dispute, etc.). Wired against those names = "tool not found" with no debug path. New list generated from grep -hE "name: 'xpr_" openclaw/src/tools/*.ts. Per-category counts now correct. Added the missing Shellbook section (15 tools).
  • Replaced Quick Start with a "Pick your path" table so harness operators stop running npx create-xpr-agent by mistake.
  • Expanded harness-install with the verify-by-log-line check and the diagnostic for the "I see 72 tools but no writes work" case ([xpr-agents] Read-only mode: XPR_ACCOUNT not set).
  • Configuration section now covers PATH fix, key:list verify, proton account:create / webauth fallback, and the keychain-unlock case. INDEXER_URL, MAX_TRANSFER_AMOUNT, confirmHighRisk, A2A_SIGNING_KEY, SHELLBOOK_API_KEY impacts surfaced explicitly.

docs/PINATA.md:

  • Added Step 2a with explicit XPR_ACCOUNT requirement and the read-only-mode diagnostic.
  • Step 2b now includes the verify-by-log-line check and an honest "Pinata's exact plugin-registration mechanism is unverified by this guide" callout.
  • Added indexerUrl to the example config.

Template + starter README env-var tables:

  • Dropped ghost HYPERION_ENDPOINTS.
  • Added INDEXER_URL, AGENT_MODE, AGENT_PUBLIC_URL with real operator impact.
  • Aligned all defaults (XPR_NETWORK=mainnet, POLL_INTERVAL=60, MAX_TRANSFER_AMOUNT=10000000).

Versions

  • @xpr-agents/openclaw0.4.1
  • create-xpr-agent0.5.1

Verification

  • 80 openclaw tests pass
  • Agent runner builds clean
  • Scaffold sanity: template files match starter byte-for-byte
  • New keychain check verified locally: matches real account names, rejects substring false-positives against PUB_K1_… keys

Three parallel operator-path audits (npm openclaw page, npx
create-xpr-agent flow, docs/PINATA.md) traced what an operator
actually hits when following the docs we just published. They
surfaced one code bug, three drift-driven config bugs, a number of
stale doc claims, and several blocking omissions. Bundle:

## Code bugs

- **Plugin manifest's `indexerUrl` default was `http://localhost:3001`**
  while the code default fell back to the public indexer only when
  unset. Any OpenClaw harness that pre-populated config from the
  schema would have hit `ECONNREFUSED localhost:3001` on all 4
  indexer-backed read tools. Fixed default →
  `https://indexer.xpragents.com`.
- **`starter/start.sh:157` keychain check used a case-insensitive
  substring grep** against `proton key:list` raw JSON. Worked by
  accident when the operator's account name didn't collide with any
  `PUB_K1_…` substring, false-positived when it did, and false-
  negatived when the chain lookup at `key:add` time hadn't populated
  the `accounts[]` array yet. Replaced with `"account": "<name>"`
  exact match + a fallback that distinguishes "no keys at all" from
  "keys loaded but not yet linked to this account."
- **`POLL_INTERVAL` had three sources of truth**: 30s (start.sh),
  14400s = 4h (agent runner code default), 30s (QUICKSTART). 30s
  hammered shared RPC; 4h was the legacy webhook-era safety-net
  default. Aligned everything to **60s**.
- **`MAX_TRANSFER_AMOUNT` mismatch:** start.sh wrote 1000000 (100 XPR)
  to .env while .env.example and the README said 10000000 (1000 XPR).
  10× silent cap. Aligned everything to 10000000.
- **`XPR_NETWORK` default split:** 4 code sites fell back to
  `'testnet'`, 2 to `'mainnet'`, .env.example and start.sh disagreed.
  Aligned everything to `mainnet` (matches what `.env.example` already
  said and matches how published agents actually run).
- **Stale "Check .env" error message** after auto-registration
  failure pointed operators at `.env` for a "private key" the agent
  refuses to start with. Rewrote to suggest `proton key:list` and
  `proton key:add` with an explicit "do NOT add XPR_PRIVATE_KEY"
  callout.

## Removed misfeatures

- **`start.sh` recursive `find ~/Documents/projects -name .env`**
  hunting for `TELEGRAM_BOT_TOKEN` to auto-reuse. Undocumented;
  surprised operators; on multi-tenant boxes leaked bot tokens
  between unrelated projects. Replaced with strict opt-in (env var,
  .env, or interactive prompt).
- **`HYPERION_ENDPOINTS` env var documented in three READMEs** but
  not referenced anywhere in the agent runner code. Ghost variable —
  removed the rows.

## Documentation rebuilds

- **`openclaw/README.md` (npm landing page):**
  - Replaced the "Tools (72 total)" section. Old list contained
    **18 tool names that don't exist in shipped code**
    (`xpr_stake_agent`, `xpr_add_plugin`, `xpr_approve_job`,
    `xpr_resolve_dispute`, `xpr_register_arbitrator`, etc.). An
    operator wiring a workflow against those names would hit
    "tool not found" with no debug path. New list generated from
    `grep -hE "name: 'xpr_" openclaw/src/tools/*.ts`. Per-category
    counts now correct (11 + 7 + 9 + 21 + 4 + 5 + 15 = 72). Added
    the missing **Shellbook section (15 tools)** — the README never
    listed `shell_*` tools despite 0.4.0 registering them.
  - Replaced the Quick Start block with a "Pick your path" table
    (standalone host vs harness) so harness operators stop running
    `npx create-xpr-agent` by mistake.
  - Expanded harness-install steps with the actual register-with-
    harness pattern, the verify-by-log-line check, and the
    diagnostic for the "I see 72 tools but no writes work" case
    (the read-only `[xpr-agents] Read-only mode: XPR_ACCOUNT not
    set` log line is the symptom).
  - Configuration section now covers PATH fix, `key:list` verify,
    `proton account:create` / webauth.com fallback, the keychain-
    unlock case, and a separate Required / Optional env block that
    spells out the impact of skipping each one (the previous
    block bundled everything together and made the operator guess).
  - Surfaced `INDEXER_URL`, `MAX_TRANSFER_AMOUNT`, `confirmHighRisk`,
    `A2A_SIGNING_KEY`, `SHELLBOOK_API_KEY` impacts explicitly.

- **`docs/PINATA.md`:**
  - Added Step 2a with explicit `XPR_ACCOUNT` requirement and the
    read-only-mode diagnostic.
  - Step 2b now includes the verify-by-log-line check
    (`[xpr-agents] Plugin loaded:`) and an honest acknowledgement
    that Pinata's exact plugin-registration mechanism is unverified
    by this guide (auditors confirmed the prior JSON example was
    generic OpenClaw, not Pinata-specific).
  - Step 2b adds the missing `indexerUrl` to the example config.

- **Template + starter README env-var tables:**
  - Removed ghost `HYPERION_ENDPOINTS` row.
  - Added `INDEXER_URL`, `AGENT_MODE`, `AGENT_PUBLIC_URL` rows with
    the actual operator impact (A2A discovery fails silently if
    `AGENT_PUBLIC_URL` unset).
  - Aligned defaults shown (XPR_NETWORK=mainnet, POLL_INTERVAL=60,
    MAX_TRANSFER_AMOUNT=10000000) with what start.sh and
    .env.example actually write.

## Version bumps

- `@xpr-agents/openclaw` → **0.4.1** (README rewrite + schema
  `indexerUrl` default + code error-message fix)
- `create-xpr-agent` → **0.5.1** (start.sh + .env.example sync — the
  source-of-truth changes propagate via the template)

## Verification

- All 80 openclaw tests pass
- Agent runner builds clean (`tsc` no errors)
- Scaffold sanity: template/start.sh and template/.env.example match
  openclaw/starter/{start.sh,.env.example} byte-for-byte; no
  template/setup.sh
- New keychain check verified locally: matches real account names,
  rejects substring false-positives against `PUB_K1_…` keys, falls
  back gracefully on stale `accounts[]` lookups
@paulgnz paulgnz merged commit 28b8165 into main May 13, 2026
5 checks passed
@paulgnz paulgnz deleted the fix/audit-blockers-0.4.1 branch May 13, 2026 23:25
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