Add nexus-tool-builder skill + nexus-tool-auditor agent - #31
Open
mike-hanono wants to merge 4 commits into
Open
Conversation
The skill automates Nexus Tool creation from an API spec, wrapping the official `nexus tool new` CLI and rendering canonical Talus tool templates for both off-chain (Rust + nexus-toolkit) and on-chain (Sui Move) tools. Each generated crate ships with: - A stateless reqwest client (no env-var credential reads — credentials arrive in the per-request Input struct, matching the convention used by tools/llm-openai-chat-completion and tools/social-twitter). - Typed error envelope mapping (Stripe-style and generic). - mockito-backed unit tests per endpoint. - GCP Cloud Run deploy YAML for testnet and mainnet, with secret mounts limited to the Tool's own signing key + allowed-leaders list. - GitHub Actions workflows that build, deploy, smoke-test, then idempotently register the tool with Nexus. The nexus-tool-auditor agent runs after verify.sh and produces an AUDIT.md scored against `reference/security-checklist.md`. The checklist covers credential handling (C7-C11), statelessness (C9), Cloud Run secret hygiene (C10), and Stripe-specific error coverage (H8-H10). The scripts/audit.sh script runs the mechanical greps. The skill ships committed to .claude/ so every contributor gets it on git clone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
- chmod +x .claude/skills/nexus-tool-builder/templates/deploy/register.sh.tmpl
(12-executable-scripts: any file with a shebang on line 1 must be
executable in the repo)
- Convert numbered list items to all `1.` in SKILL.md, hosting-options.md
per `MD029` style "one" (markdownlint config sets this)
- Add `text` language tag to three bare fenced code blocks (MD040)
- Add blank lines around lists in nexus-tool-auditor.md (MD032)
- Rephrase SKILL.md verify section to avoid a wrapped `+` that
markdownlint interpreted as a bullet (MD004)
Verified locally:
npx markdownlint-cli2@0.18.1 '.claude/**/*.md' --config .markdownlint.json
Summary: 0 error(s)
for f in $(git ls-files); do …shebang+exec check; done
clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Realigns the skill, its templates, scripts, and the nexus-tool-auditor agent with two changes that landed on `main` after PR #31 was opened: 1. PR #33 restructured the repo: tools/ → offchain/tools/, single shared offchain/Dockerfile, five reusable workflows (.github/workflows/offchain-tools.{discover,prepare,deploy,register,readiness}.yml) that key off each crate's tools.json + build.rs. No per-tool Dockerfile, Cloud Run YAML, register.sh, or workflow file needed anymore. 2. PR #27/#28 (storage-walrus) and PR #29 (memory-memwal) established the env-var credential pattern: upstream API secrets are read once at startup via from_env(), wrapped in zeroize::Zeroizing<String>, with a hand-written Debug that prints `<redacted>`. NEVER put credentials on Input — tool inputs flow through the Nexus DAG on Sui as plaintext. Skill changes: - templates/deploy/ — DELETED (whole dir). Per-tool Dockerfile / Cloud Run YAML / GitHub workflow / register.sh / allowed_leaders.json are superseded by the shared offchain/Dockerfile + offchain-tools.* workflows. - templates/rust/tools.json.tmpl + build.rs.tmpl + env.example.tmpl — NEW. build.rs.tmpl is a verbatim copy of offchain/tools/memory-memwal/build.rs (validates [[bin]].name == tools.json.command, threads TOOL_FQN_VERSION via the Docker build-arg). - templates/rust/client.rs.tmpl — flipped from per-call .with_auth() to startup-env from_env(): Zeroizing<String> bearer, hand-written Debug, shared HTTP pool via OnceLock, #[cfg(test)] for_testing() constructor. - templates/rust/endpoint.rs.tmpl — dropped api_key from Input; clients are authed once at startup; FQNs threaded through env!("TOOL_FQN_VERSION"). - templates/rust/main.rs.tmpl — adopted memwal's pattern: explicit multi-thread tokio runtime, env_logger init, --meta short-circuit (so CI's prepare step can pull /meta from an image with no env), load_dotenv_if_present() + validate_credentials_at_startup() before bootstrap!. - templates/rust/Cargo.toml.tmpl — added [[bin]], [build-dependencies], workspace deps for dotenvy / env_logger / log / anyhow / zeroize. - scripts/new_tool.sh — scaffolds at offchain/tools/<crate>/, drops in tools.json + build.rs from templates, no more deploy/ dir. - scripts/verify.sh — discovers paths via /meta (no paths.json), runs cargo against the offchain workspace, boots binary with a fake env var so validate_credentials_at_startup passes. - scripts/audit.sh — new CRITICAL check `static:input-credential` (C1) refuses crates whose Input struct contains credential-shaped fields (api_key, *_secret, *_token, bearer*, password, private_key, access_token, consumer_key, consumer_secret, client_secret — minus a whitelist for idempotency_key, pagination_token, etc.). Added shape checks for tools.json + build.rs presence, FQN-versioning check, and legacy-plumbing detector. Paths updated to offchain/. Reference + agent updates: - reference/security-checklist.md — promoted no-secrets-in-Input to C1. Renumbered everything else. Rewrote C7 to require startup-env reads. Updated C9 statefulness rule to permit startup-built Arc-wrapped client state. - reference/architecture.md — rewrote layout diagram; added tools.json + build.rs siblings; deploy/ removed; memwal as canonical example. - reference/faq.md — dropped tools/.just entry; added entries for tools.json, BLOCKED_TOOLS, secret-mounting model, FQN versioning via TOOL_FQN_VERSION. - reference/hosting-options.md — clarified that the skill emits no per-tool deploy plumbing; documented the secret-naming convention (nexus-tools-<tool>-v<ver>-…) and the operator-owned upstream-key secretKeyRef binding. - reference/style-guide.md — updated the `api_key` example (now a forbidden Input field; replaced with `payment_intent_id`). - reference/interface.md, reference/onchain-tools.md — no semantic changes (table-separator format only). - SKILL.md — rewrote workflow to reference offchain/tools/, tools.json + build.rs, no deploy artifacts emitted, env-var credential rule. Hard rules section: no credentials in Input (C1) at top. - agents/nexus-tool-auditor.md — added the hard rule: any credential-shaped Input field is an automatic CRITICAL that blocks ready-for-testnet. Paths updated to offchain/tools/. - .markdownlint config: no change; fixed compact-table separators in the touched markdown files (MD060). Verified locally: - bash .claude/skills/nexus-tool-builder/scripts/audit.sh off-chain social-twitter → FAIL static:input-credential (catches bearer_token on Input across 5 files) - bash .claude/skills/nexus-tool-builder/scripts/audit.sh off-chain memory-memwal → PASS static:input-credential (clean Input, env-var pattern) - npx markdownlint-cli2 '**/*.md' '!.git/' --config .markdownlint.json → 0 errors across 27 files Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
mike-hanono
pushed a commit
that referenced
this pull request
May 25, 2026
# Conflicts: # .claude/skills/nexus-tool-builder/reference/security-checklist.md
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.
Summary
Adds a shareable Claude Code skill that automates Nexus tool creation, plus an auditor sub-agent that scores generated crates against an authoritative security checklist. Everything is additive under
.claude/— no existing files touched, no behavior change to current tools.This is PR 1 of 2. PR 2 (
payments-stripetool) is stacked on top of this one and exercises the skill end-to-end.What this adds
.claude/skills/nexus-tool-builder/SKILL.md— entry point with the full skill workflow (off-chain Rust and on-chain Move paths, pre-flight checks, hard rules).reference/— authoritative material the skill loads on demand:architecture.md— canonical tool-crate layoutinterface.md—NexusTooltrait +bootstrap!semanticsstyle-guide.md— port naming, error variants, flatness rulesonchain-tools.md— Move-tool variant (ProofOfUID, witness,TaggedOutput)hosting-options.md— GCP Cloud Run as v1 default; DePIN deferredsecurity-checklist.md— authoritative C1–C11 / H1–H10 / M1–M6 / Move C-M1–C-M6 / H-M1–H-M6 / cross-cutting checksfaq.md— common pitfalls (top-leveloneOf, dedup paths, workspace deps)templates/rust/— Cargo.toml, README, main.rs, error.rs, stateless client.rs, endpoint.rs, models.rs, tools_mod.rstemplates/move/— Move.toml +sources/tool.move.tmpltemplates/deploy/— Dockerfile, Cloud Run testnet/mainnet YAML,register.sh, GitHub Actions workflows for testnet (push to main) and mainnet (tag, gated on testnet green)scripts/new_tool.sh— wrapsnexus tool new, moves intotools/scripts/verify.sh—cargo check/clippy -D warnings/test/fmt --check/ live/health+/metasmokescripts/audit.sh— mechanical static + dynamic checks (cargotoolchain, greps for unwrap/expect/panic in non-test code, env-var credential reads, statefulness sniff,sk_live_leak, Cloud Run secret mounts that don't match the allowed set).claude/agents/nexus-tool-auditor.mdverify.sh(or invoked manually withAgent({ subagent_type: "nexus-tool-auditor", ... })).reference/security-checklist.mdas source of truth.audit.sh, fuzzes/invokewith malformed payloads, optionally backtests againstfixtures/, writestools/<crate>/AUDIT.mdwith severity-graded findings + sign-off recommendation.AdminCapguards, copyable witness, hardcoded addresses, gas-grief loops.Credential model (baked into templates)
The skill's templates enforce the same per-request credential model used today by
tools/llm-openai-chat-completionandtools/social-twitter: upstream API credentials live ONLY in theInputstruct, never in env vars, never on disk, never in Cloud Run secrets. The Cloud Run YAML templates mount only the Tool's own Ed25519 signing key and the allowed-leaders list. The audit script's checks C7, C9, C10, C11 enforce this mechanically.The relevant section of the security checklist:
How a contributor uses this
The skill walks the contributor through endpoint discovery, generates the crate per the templates above, runs
verify.sh, then calls the auditor. PR 2 of 2 is the artifact of running this against Stripe.Test plan
bash -n, YAML parse, JSON parse) — verified locallySKILL.mdfrontmatter is valid YAMLnexus tool new --template rustscaffold (verified by PR 2)scripts/audit.shproduces a clean run on a known-good crate (verified by PR 2)🤖 Generated with Claude Code