Skip to content

feat(cli): add chain scaffold kit for supported-chain contributions#162

Open
okwn wants to merge 2 commits intoopen-wallet-standard:mainfrom
okwn:feat/chain-plugin-kit
Open

feat(cli): add chain scaffold kit for supported-chain contributions#162
okwn wants to merge 2 commits intoopen-wallet-standard:mainfrom
okwn:feat/chain-plugin-kit

Conversation

@okwn
Copy link
Copy Markdown

@okwn okwn commented Apr 1, 2026

Summary

Adds a contributor-focused Chain Plugin Kit scaffold command to make adding a new supported chain easier and more consistent.

What this PR adds

  • CLI scaffold command for generating a new chain template
  • generated chain profile / CAIP mapping / derivation rules templates
  • signing and serialization stubs
  • test-vectors folder and docs skeleton
  • tests covering generation flow, invalid input, overwrite validation, and an Aptos golden path

Why

OWS is explicitly multi-chain and already documents supported chains, canonical identifiers, and derivation rules. This PR improves contributor ergonomics by standardizing the first step of new-chain work.

Scope

This PR focuses on scaffolding only.
It does not implement dynamic runtime plugin loading.

Validation

  • cargo run -p ows-cli -- dev scaffold-chain --slug release-check --family evm --display-name "Release Check" --write --force --output ".ows-dev/release-check-c"
  • deterministic regeneration verified with no tree/hash differences
  • invalid slug handling verified
  • overwrite protection verified
  • cd ows && cargo fmt --all --check
  • cd ows && cargo clippy --workspace -- -D warnings
  • cd ows && cargo test --workspace

Notes

Two minimal portability fixes were included so the documented workspace verification passes cleanly:

  • process_hardening.rs
  • policy_engine.rs

Note

Medium Risk
Adds a new CLI command that validates user input and can create/overwrite files on disk (with --force), so path-safety and deletion logic need careful review; no runtime chain support or signing behavior is changed.

Overview
Adds a new ows dev scaffold-chain CLI subcommand that dry-runs by default and can --write a self-contained “Chain Plugin Kit” under .ows-dev/chain-plugin-kit/<slug>/, generating templated TOML profiles, CAIP placeholders, signing/serialization stubs, docs skeletons, and JSON test-vector fixtures.

Implements slug/token validation plus safe output-path/--force overwrite restrictions to keep writes and deletions confined to the .ows-dev scaffold area, with unit tests including an Aptos “golden path”. Updates contributor docs to describe the workflow, ignores .ows-dev/, and includes small Unix/Windows portability fixes for policy-engine tests and Unix-gating of cleanup hooks.

Written by Cursor Bugbot for commit d39fc0c. This will update automatically on new commits. Configure here.

@okwn okwn requested a review from njdawn as a code owner April 1, 2026 23:09
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 1, 2026

@okwn is attempting to deploy a commit to the MoonPay Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Contributor

@njdawn njdawn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found three issues that should be fixed before merging:

  1. --output + --force can recursively delete any existing directory inside the repo, including the repo root.
    ScaffoldChain accepts any repository-relative output path, and write_plan() unconditionally calls remove_dir_all() / remove_file() on that target when --force is passed. In an isolated worktree, cargo run -p ows-cli -- dev scaffold-chain --slug root-test --family evm --output . --force dry-ran successfully and reported that the repository root would be replaced, so a real --write would attempt to wipe the checkout.

  2. The repository-boundary check is bypassable via symlinks.
    resolve_output_dir() only normalizes path components lexically; it does not resolve symlink components. I reproduced this by creating .ows-dev/outside-link -> /tmp/ows-pr162-escape-target and running --output .ows-dev/outside-link/escape-test. The scaffold wrote all generated files outside the repository into /tmp/ows-pr162-escape-target/escape-test. With --force, the same path can also delete external content.

  3. User-provided text is injected into TOML and Rust templates without escaping.
    validate_display_name() / validate_optional_text() reject control characters, but they still allow quotes and backslashes, and render_template() does raw string replacement. I verified this with --display-name 'Foo "Bar"': the generated chain-profile.toml contained display_name = "Foo "Bar"", and the Rust stubs contained broken string literals too.

I validated these in an isolated worktree with cargo run -p ows-cli -- dev scaffold-chain ....

@okwn
Copy link
Copy Markdown
Author

okwn commented Apr 2, 2026

Addressed the reported safety issues:

  • restricted scaffold output to a dedicated safe base under .ows-dev/chain-plugin-kit/
  • blocked symlink-based path escapes by resolving existing ancestors and revalidating before delete/write
  • added context-aware escaping for TOML, JSON, and Rust string literals

Also added regression tests for:

  • unsafe --output targets
  • symlink escape attempts
  • --force safety boundaries
  • quote/backslash escaping in generated templates

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

"Ed25519"
} else {
"Secp256k1"
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Template variables computed but never used in templates

Low Severity

The curve_variant and family_variant fields in ScaffoldContext are computed (via chain_type_variant() and a string comparison) and processed in render_template with .replace("{{curve_variant}}", ...) and .replace("{{family_variant}}", ...), but no template file actually contains {{curve_variant}} or {{family_variant}}. A grep across templates/chain-plugin-kit/ confirms zero matches. This is dead code — computation and replacement that produces no visible effect.

Additional Locations (2)
Fix in Cursor Fix in Web

@njdawn
Copy link
Copy Markdown
Contributor

njdawn commented Apr 3, 2026

this is a useful feature -> that being said, would like the architecture of this PR to be as isolated as possible from all source code, since this is for dev-ex and not a feature.

Alternatively, can think about a refactor that makes a chain registry, so that there are less places where chain prs need to change.

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.

2 participants