Commit 0fda046
feat: RequestGenerator WASM bindings for Cedar authorization requests (#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>1 parent 34b211a commit 0fda046
4 files changed
Lines changed: 948 additions & 17 deletions
File tree
- rust
- cedar-policy-mcp-schema-generator-wasm/src
- cedar-policy-mcp-schema-generator/src
- generator
0 commit comments