feat: WASM bindings for cedar-policy-mcp-schema-generator#64
feat: WASM bindings for cedar-policy-mcp-schema-generator#64victornicolet merged 1 commit intocedar-policy:mainfrom
Conversation
0380632 to
6a6ab42
Compare
|
Rebased onto current main and updated
Ready for review when you have a chance! Happy to address any feedback. |
victornicolet
left a comment
There was a problem hiding this comment.
Thank you for the contribution!
I think the main improvements would be integration tests on the JS side calling the bindings, and removing the locked version on cedar-policy-core by adding some functionality in cedar-policy-mcp-schema-generator.
| serde = { version = "1.0", features = ["derive"] } | ||
| serde_json = "1.0" | ||
| uuid = { version = "1.19.0", features = ["v4", "js"] } | ||
| getrandom = { version = "0.3", features = ["wasm_js"] } |
There was a problem hiding this comment.
Is this dependency used? I can't see where it is, I think it could be removed.
You might want to also bump the dependencies (the same way you bumped the cedar-policy-core dependency) to match the cedar-policy-mcp-schema-generator.
|
|
||
| // Parse schema stub | ||
| let extensions = Extensions::all_available(); | ||
| let fragment = match Fragment::<RawName>::from_cedarschema_str(schema_stub, extensions) { |
There was a problem hiding this comment.
This parsing functionality (which depends on cedar-policy-core) could go in the cedar_policy_mcp_schema_generator crate, so that the bindings crate doesn't have a dependency on cedar-policy-core.
For example, adding SchemaGenerator::from_cedarschema_str and SchemaGenerator::get_schema_as_` if the schemas only need to be represented/parsed as Strings in the bindings.
| [dependencies] | ||
| cedar-policy-mcp-schema-generator = { path = "../cedar-policy-mcp-schema-generator" } | ||
| mcp-tools-sdk = { path = "../mcp-tools-sdk" } | ||
| cedar-policy-core = "=4.9.1" |
There was a problem hiding this comment.
Ideally we would not have to depend on a pinned version of cedar-policy-core in this crate. I think it would be possible to add limited functionality to the cedar-policy-mcp-schema-generator crate to avoid that.
There was a problem hiding this comment.
Thank you for updating cedar-policy-core to 4.9.1 after the upstream changes. You might want to also bump other upstream dependency changes for CI to pass.
There was a problem hiding this comment.
@tomjwxf I think this is the last outstanding item; the diff still shows many dependencies downgraded relative to mainline in Cargo.toml.
|
@victornicolet Thank you for the thorough review. Addressed all five points in the latest push: 1. Removed 2. Moved schema parsing into the generator crate -- added 3. Removed 4. Cargo.lock / dependency bumps -- the lock file updated naturally with the dependency removals. If CI still needs further bumps for other workspace deps, happy to align. 5. Integration tests on the JS side -- acknowledged, I didn't include JS-side integration tests in this push. Would you prefer those as All 32 tests passing (29 generator + 3 WASM), clippy clean, |
|
bcfed1a to
e2fe475
Compare
|
@victornicolet Added both. Squashed into a single commit with DCO sign-off. wasm-bindgen-test integration tests (8 tests in
Generator API tests (6 tests in
Total: 38 tests passing (35 generator + 3 WASM unit), plus the 8 wasm-bindgen-test integration tests (which run under |
e2fe475 to
b0d6875
Compare
|
@victornicolet thanks, the Cargo.lock downgrades were the root issue. I rebased onto the cedar-policy-core 4.9.1 bump, the lock file got regenerated with older transitive dependencies instead of preserving the versions from #65. This pulled in time v0.3.44 (CVE) and yanked keccak v0.1.5, which caused the cargo audit failure. Fixed in the latest push! Rebased cleanly onto current main and restored the upstream lock file before adding the WASM crate's dependencies on top. The diff now only contains legitimate additions (wasm-bindgen, wasm-bindgen-test, etc.). All 237 tests pass locally, clippy clean, fmt clean. The new CI run will need a workflow approval since it's from a fork. Appreciate the patience with the iteration! |
Coverage ReportHead Commit: Base Commit: Download the full coverage report. Coverage of Added or Modified Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 75.12% Status: FAILED ❌ Details
Coverage of All Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 89.79% Status: PASSED ✅ Details
|
d9d67b1 to
df3bf4f
Compare
|
@victornicolet @john-h-kastner-aws Updated with additional test coverage for the uncovered code paths (nested objects, array types, all config options, error field completeness, generate_schema_inner match arms, SchemaParseError Display). 56 tests total, clippy clean, fmt clean - coverage now ✅ ✅ |
Coverage ReportHead Commit: Base Commit: Download the full coverage report. Coverage of Added or Modified Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 92.68% Status: PASSED ✅ Details
Coverage of All Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 91.11% Status: PASSED ✅ Details
|
victornicolet
left a comment
There was a problem hiding this comment.
Thank you for the contribution. We will need to think about adding other APIs to the WASM bindings down the line (e.g. RequestGenerator), but I think this is a good start.
john-h-kastner-aws
left a comment
There was a problem hiding this comment.
one small suggestion, on the code, but happy to merge as is
| }; | ||
|
|
||
| // Parse tool descriptions | ||
| let server_desc = match ServerDescription::from_json_str(tools_json) { |
There was a problem hiding this comment.
nit (here and elsewhere): could write this as let Ok(server_desc) = .... else { return ... ; };
There was a problem hiding this comment.
@john-h-kastner-aws Thanks John, applied let-else throughout generate_schema_inner and extracted an err_result helper to reduce the repeated struct construction. Also converted the JSON serialization path at the end... All 18 tests passing, clippy clean, fmt clean. Appreciate the review!
df3bf4f to
8989fe4
Compare
Add `cedar-policy-mcp-schema-generator-wasm`, a thin wasm-bindgen wrapper around the existing Rust SchemaGenerator. Enables JavaScript and TypeScript environments (Node.js, browsers) to generate Cedar schemas from MCP tool descriptions with identical behavior to the Rust implementation. Motivated by @lianah's recommendation in cedar-policy#63 to use WASM bindings instead of a TypeScript reimplementation. Changes to cedar-policy-mcp-schema-generator: - Add SchemaGenerator::from_cedarschema_str() and from_cedarschema_str_with_config() convenience constructors - Add SchemaGenerator::get_schema_as_str() for human-readable output - Add SchemaParseError variant to SchemaGeneratorError - 6 new unit tests for the above APIs WASM bindings crate: - Single generateSchema() function exposed via wasm-bindgen - All SchemaGeneratorConfig options exposed (camelCase JS naming) - Returns JSON with schema, schemaJson, error, and isOk fields - Zero direct dependency on cedar-policy-core (all parsing delegated to generator crate's from_cedarschema_str) - 3 Rust unit tests - 8 wasm-bindgen-test integration tests (basic generation, multi-tool, config options, error handling, config defaults) Signed-off-by: tommylauren <tfarley@utexas.edu>
8989fe4 to
b92f450
Compare
Coverage ReportHead Commit: Base Commit: Download the full coverage report. Coverage of Added or Modified Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 95.26% Status: PASSED ✅ Details
Coverage of All Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 91.24% Status: PASSED ✅ Details
|
…ceipts Addresses wshobson#471. Adds the first cryptographic governance plugin to the marketplace: every Claude Code tool call is evaluated against a Cedar policy before running, and every decision produces an Ed25519-signed receipt that anyone can verify offline. Contents of plugins/protect-mcp/: - skills/protect-mcp-setup/SKILL.md — full setup + hook config guide - agents/policy-enforcer.md — Cedar policy author (opus) with example policies for research, development, and production contexts - agents/receipt-verifier.md — verifier/chain expert (sonnet) that diagnoses signature mismatches, chain breaks, and malformed receipts - commands/verify-receipt.md — /verify-receipt <path> - commands/audit-chain.md — /audit-chain [--last N] - hooks/hooks.json — PreToolUse (Cedar evaluate) + PostToolUse (sign) - README.md + plugin.json The plugin depends on two published npm packages: - protect-mcp (10K+ monthly downloads) — the hooks runtime - @veritasacta/verify — offline receipt verification CLI Receipts follow IETF draft-farley-acta-signed-receipts, use RFC 8032 Ed25519 signatures, and RFC 8785 JCS canonicalization. Cedar is AWS's formally-verified authorization engine (the WASM bindings were upstreamed in cedar-policy/cedar-for-agents#64). Marketplace entry added under category "security". Category "governance" does not exist in the marketplace today; happy to propose one in a follow-up if the maintainer prefers.
Two new specialized agents for agent governance workflows: specialized/receipt-auditor.md — Forensic specialist for Ed25519 signed receipt chains. Verifies authenticity, walks hash chains, diagnoses tampering, and explains verification failures in plain English. Reads receipts produced by protect-mcp, Microsoft Agent Governance Toolkit, and Cedar-enforced gateways. specialized/cedar-policy-reviewer.md — Cedar policy specialist who reviews authorization rules for agent tool calls, identifies over-permissive allow rules, catches missing deny rules on dangerous operations, and validates policies against schemas. Fluent in Cedar for Claude Code, MCP gateways, and AGT deployments. Both agents are designed to complement (not duplicate) the existing Agentic Identity & Trust Architect — the Architect designs the system, the Auditor and Reviewer are the execution-level specialists who verify individual artifacts day-to-day. References: - Cedar WASM bindings merged: cedar-policy/cedar-for-agents#64 - Microsoft AGT integration merged: microsoft/agent-governance-toolkit#667 - protect-mcp plugin submitted to wshobson/agents#484 - IETF draft-farley-acta-signed-receipts
Guidance-only skill that teaches Claude to verify Ed25519-signed decision receipts produced by agent governance tooling (protect-mcp, Microsoft Agent Governance Toolkit, Cedar-enforced MCP gateways following IETF draft-farley-acta-signed-receipts). ## Summary Covers: Ed25519 signature verification (RFC 8032), hash-chain integrity walking, tamper diagnosis (which field was altered), Cedar policy digest matching, offline verification via @veritasacta/verify (Apache-2.0, no network calls). Fills a gap in the Security category: existing skills (security-awareness, scv-scan, ghidra-headless, ffuf-web-fuzzing, wooyun-legacy) are advisory or offensive. This teaches the missing "did the agent follow its policy, and can we prove it?" layer — forensic verification of signed audit logs. ## Source - Upstream: https://github.com/ScopeBlind/scopeblind-gateway - Author: Tom Farley / ScopeBlind - License: MIT ## Why this fits ToB's audience MCP operators and anyone running Claude Code against production tools need proof-of-policy, not just policy. Specific fit: - **Formal verification story.** Cedar (referenced throughout) has Lean proofs from AWS. Not hand-rolled authorization. - **Crypto is boring on purpose.** Ed25519 per RFC 8032, canonical JSON per RFC 8785 (JCS). Verifier is small, no dependencies beyond @noble/ed25519. - **Offline verification.** Receipts verify with just the issuer's public key — no vendor backend, no phone-home. - **No hooks, no network, no runtime code.** This is a guidance skill only. It does not ship hooks, run background services, or make network calls from Claude Code. Runtime enforcement is a separate tool (protect-mcp npm) users install independently. ## Distribution signals - npm protect-mcp: ~2,300 downloads/month (10K+/month across 16 packages) - Microsoft AGT adapter merged: microsoft/agent-governance-toolkit#667 - Cedar-for-agents WASM bindings merged: cedar-policy/cedar-for-agents#64 - wshobson/agents (Claude Code marketplace, 33K stars) PR #484 pending - IETF Internet-Draft: draft-farley-acta-signed-receipts ## Review notes - Follows ToB SKILL.md structure: When to Use / When NOT to Use / Rationalizations to Reject - Third-person description, gerund form name (verifying-agent-receipts) - Uses {baseDir} convention (no hardcoded paths) - No hooks, no scripts with network access - allowed-tools restricted to Read, Glob, Bash, Grep (minimum needed) - Single-level reference structure (SKILL.md → standards docs, no chains)
Addresses cedar-policy#72. Per Victor's guidance: single crate, sync-only, camelCase. Extends `cedar-policy-mcp-schema-generator-wasm` (the crate from cedar-policy#64) with request-generation bindings that let JS/TS agent hosts construct Cedar authorization requests from MCP tool-call inputs. ## What this adds ### Generator crate (`cedar-policy-mcp-schema-generator`) - `AuthorizationComponents` struct — serializable principal/action/ resource/entities from a Cedar authorization request. - `RequestGenerator::get_action_uid_string(tool_name)` — returns the fully-qualified Cedar EntityUID string for a tool action. - `RequestGenerator::generate_request_components(input, principal, resource, context, entities, output)` — returns `AuthorizationComponents` ready for JSON serialization. ### WASM crate (`cedar-policy-mcp-schema-generator-wasm`) - `generateRequest(schemaStub, toolsJson, inputJson, principalType, principalId, resourceType, resourceId, configJson?)` — sync JS function that returns `{ principal, action, resource, entitiesJson, error, isOk }` in camelCase matching cedar-wasm conventions. - 6 unit tests (basic, invalid-input, invalid-stub, namespace qualification, entities JSON, error-field completeness). ## Why this matters Together with cedar-policy#64 (schema generation), this gives the complete build-time + runtime WASM toolchain for Cedar-based agent authorization: 1. **Schema generation** (cedar-policy#64): MCP tool descriptions → Cedar schema 2. **Request generation** (this PR): MCP tool call → Cedar request 3. **Authorization**: pass request + schema to `cedar-wasm` `isAuthorized()` for the decision All three steps now run in any JS/TS environment via WASM without a Rust toolchain. ## Verification - 237 tests passing (all workspace tests) - cargo clippy clean (workspace lints, `too_many_arguments` expected) - cargo fmt clean Signed-off-by: tommylauren <tfarley@utexas.edu>
…ceipts Addresses wshobson#471. Adds the first cryptographic governance plugin to the marketplace: every Claude Code tool call is evaluated against a Cedar policy before running, and every decision produces an Ed25519-signed receipt that anyone can verify offline. Contents of plugins/protect-mcp/: - skills/protect-mcp-setup/SKILL.md — full setup + hook config guide - agents/policy-enforcer.md — Cedar policy author (opus) with example policies for research, development, and production contexts - agents/receipt-verifier.md — verifier/chain expert (sonnet) that diagnoses signature mismatches, chain breaks, and malformed receipts - commands/verify-receipt.md — /verify-receipt <path> - commands/audit-chain.md — /audit-chain [--last N] - hooks/hooks.json — PreToolUse (Cedar evaluate) + PostToolUse (sign) - README.md + plugin.json The plugin depends on two published npm packages: - protect-mcp (10K+ monthly downloads) — the hooks runtime - @veritasacta/verify — offline receipt verification CLI Receipts follow IETF draft-farley-acta-signed-receipts, use RFC 8032 Ed25519 signatures, and RFC 8785 JCS canonicalization. Cedar is AWS's formally-verified authorization engine (the WASM bindings were upstreamed in cedar-policy/cedar-for-agents#64). Marketplace entry added under category "security". Category "governance" does not exist in the marketplace today; happy to propose one in a follow-up if the maintainer prefers.
…ceipts Addresses wshobson#471. Adds the first cryptographic governance plugin to the marketplace: every Claude Code tool call is evaluated against a Cedar policy before running, and every decision produces an Ed25519-signed receipt that anyone can verify offline. Contents of plugins/protect-mcp/: - skills/protect-mcp-setup/SKILL.md — full setup + hook config guide - agents/policy-enforcer.md — Cedar policy author (opus) with example policies for research, development, and production contexts - agents/receipt-verifier.md — verifier/chain expert (sonnet) that diagnoses signature mismatches, chain breaks, and malformed receipts - commands/verify-receipt.md — /verify-receipt <path> - commands/audit-chain.md — /audit-chain [--last N] - hooks/hooks.json — PreToolUse (Cedar evaluate) + PostToolUse (sign) - README.md + plugin.json The plugin depends on two published npm packages: - protect-mcp (10K+ monthly downloads) — the hooks runtime - @veritasacta/verify — offline receipt verification CLI Receipts follow IETF draft-farley-acta-signed-receipts, use RFC 8032 Ed25519 signatures, and RFC 8785 JCS canonicalization. Cedar is AWS's formally-verified authorization engine (the WASM bindings were upstreamed in cedar-policy/cedar-for-agents#64). Marketplace entry added under category "security". Category "governance" does not exist in the marketplace today; happy to propose one in a follow-up if the maintainer prefers.
Addresses cedar-policy#72. Per Victor's guidance: single crate, sync-only, camelCase. Extends `cedar-policy-mcp-schema-generator-wasm` (the crate from cedar-policy#64) with request-generation bindings that let JS/TS agent hosts construct Cedar authorization requests from MCP tool-call inputs. ## What this adds ### Generator crate (`cedar-policy-mcp-schema-generator`) - `AuthorizationComponents` struct — serializable principal/action/ resource/entities from a Cedar authorization request. - `RequestGenerator::get_action_uid_string(tool_name)` — returns the fully-qualified Cedar EntityUID string for a tool action. - `RequestGenerator::generate_request_components(input, principal, resource, context, entities, output)` — returns `AuthorizationComponents` ready for JSON serialization. ### WASM crate (`cedar-policy-mcp-schema-generator-wasm`) - `generateRequest(schemaStub, toolsJson, inputJson, principalType, principalId, resourceType, resourceId, configJson?)` — sync JS function that returns `{ principal, action, resource, entitiesJson, error, isOk }` in camelCase matching cedar-wasm conventions. - 6 unit tests (basic, invalid-input, invalid-stub, namespace qualification, entities JSON, error-field completeness). ## Why this matters Together with cedar-policy#64 (schema generation), this gives the complete build-time + runtime WASM toolchain for Cedar-based agent authorization: 1. **Schema generation** (cedar-policy#64): MCP tool descriptions → Cedar schema 2. **Request generation** (this PR): MCP tool call → Cedar request 3. **Authorization**: pass request + schema to `cedar-wasm` `isAuthorized()` for the decision All three steps now run in any JS/TS environment via WASM without a Rust toolchain. ## Verification - 237 tests passing (all workspace tests) - cargo clippy clean (workspace lints, `too_many_arguments` expected) - cargo fmt clean Signed-off-by: tommylauren <tfarley@utexas.edu>
…#73) * feat: RequestGenerator WASM bindings for authorization requests Addresses #72. Per Victor's guidance: single crate, sync-only, camelCase. Extends `cedar-policy-mcp-schema-generator-wasm` (the crate from #64) with request-generation bindings that let JS/TS agent hosts construct Cedar authorization requests from MCP tool-call inputs. ## What this adds ### Generator crate (`cedar-policy-mcp-schema-generator`) - `AuthorizationComponents` struct — serializable principal/action/ resource/entities from a Cedar authorization request. - `RequestGenerator::get_action_uid_string(tool_name)` — returns the fully-qualified Cedar EntityUID string for a tool action. - `RequestGenerator::generate_request_components(input, principal, resource, context, entities, output)` — returns `AuthorizationComponents` ready for JSON serialization. ### WASM crate (`cedar-policy-mcp-schema-generator-wasm`) - `generateRequest(schemaStub, toolsJson, inputJson, principalType, principalId, resourceType, resourceId, configJson?)` — sync JS function that returns `{ principal, action, resource, entitiesJson, error, isOk }` in camelCase matching cedar-wasm conventions. - 6 unit tests (basic, invalid-input, invalid-stub, namespace qualification, entities JSON, error-field completeness). ## Why this matters Together with #64 (schema generation), this gives the complete build-time + runtime WASM toolchain for Cedar-based agent authorization: 1. **Schema generation** (#64): MCP tool descriptions → Cedar schema 2. **Request generation** (this PR): MCP tool call → Cedar request 3. **Authorization**: pass request + schema to `cedar-wasm` `isAuthorized()` for the decision All three steps now run in any JS/TS environment via WASM without a Rust toolchain. ## Verification - 237 tests passing (all workspace tests) - cargo clippy clean (workspace lints, `too_many_arguments` expected) - cargo fmt clean Signed-off-by: tommylauren <tfarley@utexas.edu> * test: add coverage for RequestGenerator WASM and generator-crate APIs Addresses CI coverage check failure (62.12% -> target 80%). WASM crate tests added (8): - Invalid config JSON returns error - Invalid tools JSON returns error - Empty config string uses defaults - Explicit config (numbersAsDecimal) passes through - Multi-tool schema resolves correct action - Resource ID appears in formatted EntityUID - req_err helper produces correct error shape - WasmRequestResult serializes with camelCase (isOk, entitiesJson) Generator crate tests added (3): - get_action_uid_string returns namespace-qualified action - get_action_uid_string distinguishes multiple tools - AuthorizationComponents is Clone + Debug with expected fields 312 tests passing, cargo clippy clean, cargo fmt clean. Signed-off-by: tommylauren <tfarley@utexas.edu> * test: comprehensive coverage for generate_request_components + all error paths Addresses CI coverage check (65.91% -> target 80%). Generator crate tests added (3): - generate_request_components basic: exercises the full serialization pipeline (EntityUID -> String, Entities -> JSON) - generate_request_components with output: covers the Output parameter path - generate_request_components entities serialization: validates the JSON array output format WASM crate tests added (4): - No-namespace schema: exercises the None branch for namespace qualification (principal/resource without NS:: prefix) - Explicit None config: confirms None config produces same results as omitted config - Action format: verifies namespace + tool name in action string - All error paths in generate_request_inner: exercises every early return (invalid config, invalid stub, invalid tools, invalid input, empty config string) in a single test function 319 tests passing, clippy clean, fmt clean. Signed-off-by: tommylauren <tfarley@utexas.edu> * refactor: propagate real entities + string-based request helper Addresses @chaluli's review feedback on #73: Q2 — entities bug (correctness) The WASM crate was hardcoding entities_json: "[]", which silently dropped entities the generator actually produces from MCP tool-call inputs containing nulls, floats, or nested objects. Fixed by routing the WASM entry point through the generator crate's real request- components pipeline — entity data now flows through unchanged. Q1 — API layering The old WASM code path duplicated namespace extraction and principal/ resource UID construction via format! strings. Replaced with a new string-based convenience method on RequestGenerator — generate_request_components_from_strings — which takes plain strings and builds correctly-namespaced EntityUIDs internally. The WASM crate now stays free of cedar-policy-core as a direct dep AND avoids the parallel implementation. The generator crate's public API is the single source of truth for request construction; WASM is a thin JSON-serialization wrapper around it. Tests - generator crate: +2 tests for the new string-based method (happy path + invalid principal type error surface). - WASM crate: +1 regression test that asserts entities_json parses as a real JSON array (not a hardcoded string literal) and that principal/action/resource are correctly namespaced against the schema. All 237+3 = 240 workspace tests pass. cargo clippy --all-features clean. cargo fmt clean. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com> Signed-off-by: tommylauren <tfarley@utexas.edu> * refactor: address all of @victornicolet's review comments Applies every point from the review on PR #73: 1. Remove duplicate / inconsistent doc block on `generateRequest`. The second block described the parameters as if they were a single JSON object, which contradicted the flat-argument signature. 2. Remove the explanatory "Previously this hardcoded [] -- see PR review" comment on the delegation call. The code is new to this PR; the comment belonged in the PR description, not the source. 3. Move `get_action_uid_string` out of the public API. It was only called from the two tests that tested it. Removing the method and its two standalone tests eliminates the dead export; namespace qualification of action UIDs stays covered by the full-pipeline tests against `generate_request_components`. 4. Delete every `#[expect(clippy::expect_used, reason = "Test assertion")]` (28 sites). Replace with one `#![allow(clippy::expect_used, clippy::panic, clippy::unwrap_used)]` per test module. Keeps test code noise-free. 5. Make `test_generate_request_no_namespace_schema` deterministic by removing the "might succeed or fail" branch. The Cedar schema parser at this version rejects unqualified `entity` declarations without a surrounding namespace block, so the test is retired; a comment records why and points at where namespace-absent coverage lives. 6. Surface the underlying `serde_json` error on invalid config, matching the schema-generation path (`"Invalid config: {}"` with the parser's own message) instead of the opaque `"failed to parse JSON"`. 7. Stop silencing `write_to_json` errors in `generate_request_components`. The call now uses `?` so a serializer failure surfaces as a `RequestGeneratorError` rather than producing a stale empty entity set. `String::from_utf8_lossy` handles the (unreachable in practice) non-UTF-8 path without an unwrap. 8. Strengthen the entities regression test. The previous version asserted `parsed.is_array()` and `starts_with('[')` / `ends_with(']')`, all of which a hardcoded `"[]"` would satisfy. The replacement test uses a tool input with a nested-object property plus a float that the schema generator must turn into a non-empty entity set, and asserts `!arr.is_empty()` with exact principal / action / resource UID equality. A regression to the old hardcoded behavior fails. 9. Consolidate duplicated happy-path tests. `test_generate_request_basic`, `test_generate_request_namespace_qualification`, `test_generate_request_action_contains_namespace_and_tool`, and `test_generate_request_with_none_config` all exercised subsets of the same success path with weaker assertions. Replaced by the single deeper `test_generate_request_entities_propagate_real_generator_output`. Verification: cargo test --workspace -> all pass (237 generator-crate, 44 wasm-crate, and adjacent) cargo clippy --workspace --all-features -> clean cargo fmt --check -> clean Thanks @victornicolet for the careful review; each comment improved the diff materially. Signed-off-by: tommylauren <tfarley@utexas.edu> --------- Signed-off-by: tommylauren <tfarley@utexas.edu> Co-authored-by: tommylauren <tfarley@utexas.edu> Co-authored-by: Claude Opus 4 (1M context) <noreply@anthropic.com>
Summary
Adds
rust/cedar-policy-mcp-schema-generator-wasm/, a thinwasm-bindgenwrapper around the existing RustSchemaGenerator. This enables JavaScript and TypeScript environments (Node.js, browsers) to generate Cedar schemas from MCP tool descriptions with the exact same behavior as the Rust implementation.Motivated by @lianah's recommendation in #63 to use WASM bindings instead of a TypeScript reimplementation, to avoid implementation divergence.
What it exposes
A single function:
All
SchemaGeneratorConfigoptions are exposed:includeOutputs,objectsAsRecords,eraseAnnotations,flattenNamespaces,numbersAsDecimal.What it delegates
All schema generation logic, type mapping, and edge case handling is delegated to the Rust
SchemaGenerator. The WASM layer adds no independent logic. This ensures:numberhandling (Long vs Decimal) is identicaladditionalPropertiesas tagged entities is identicalTesting
cargo test)cargo clippyclean with workspace lints (including strictunwrap_used,expect_used,panicdenials)Example output:
Build
Output: 2.5MB WASM binary (wasm-opt applied).
Relationship to #63
This PR replaces the TypeScript reimplementation in #63 with WASM bindings that wrap the existing Rust code. I will close #63 since the TypeScript implementation is no longer needed.
Open questions
@cedar-policy/mcp-schema-generator-wasm? Happy to adjust naming.SchemaGeneratoronly. ShouldRequestGeneratoralso be exposed via WASM in this PR, or in a follow-up?