Skip to content

feat: add parseRecapFromSiwe WASM export for capability chain delegation#47

Merged
skgbafa merged 2 commits into
mainfrom
feat/parse-recap-from-siwe
Apr 10, 2026
Merged

feat: add parseRecapFromSiwe WASM export for capability chain delegation#47
skgbafa merged 2 commits into
mainfrom
feat/parse-recap-from-siwe

Conversation

@skgbafa
Copy link
Copy Markdown
Contributor

@skgbafa skgbafa commented Apr 10, 2026

Summary

Adds a new #[wasm_bindgen] export parseRecapFromSiwe(siweString) that decodes the recap capabilities embedded in a signed SIWE message and returns them as an array of { service, space, path, actions } entries.

This is the inverse of what SessionConfig::into_message does today when it builds a session recap, and it is the primitive the JS SDK needs to decide whether a requested delegation is a strict subset of the current session's granted capabilities. When the subset check succeeds, the SDK can issue the delegation via the existing createDelegation WASM path (session-key Ed25519 signature, no wallet prompt). When it fails, the SDK will raise a permission escalation flow.

This is Phase 1 of the capability-chain-delegation feature tracked in the js-sdk and listen repos.

Behavior

  • Recap-less SIWE returns an empty array (not an error); plain auth SIWE is a valid input.
  • Malformed SIWE, tampered recap statements, and unparseable resource URIs all propagate as errors rather than being silently swallowed.
  • Actions are returned in deterministic sorted order (BTreeMap iteration).
  • Multi-space sessions (primary + additional public companion) produce one entry per (space, service, path) triple.
  • Field names (service, space, path, actions) are wire-aligned with the TS SDK's manifest PermissionEntry shape.

Implementation notes

  • Parser lives in tinycloud-sdk-wasm/src/session.rs next to create_delegation, re-exported via lib.rs alongside createDelegation.
  • Uses Capability::<serde_json::Value>::extract_and_verify from siwe-recap, which returns Ok(None) on plain SIWE and Err(...) on tampered statements — we preserve both signals cleanly.
  • Each resource URI is re-parsed as a ResourceId so we can pull space(), service(), path() without brittle string-splitting.

Test plan

  • cargo check -p tinycloud-sdk-wasm passes clean.
  • cargo test -p tinycloud-sdk-wasm --lib passes, including three new tests:
    • parse_recap_roundtrip — builds a multi-service (kv / sql / capabilities) SIWE and verifies every (service, space, path, actions) tuple roundtrips.
    • parse_recap_empty_on_plain_siwe — recap-less SIWE returns an empty Vec, not an error.
    • parse_recap_with_additional_spaces — primary + public companion yields one entry per space.
  • Downstream: js-sdk (@tinycloud/sdk-rs rev bump) will consume this export in Phase 2.

skgbafa added 2 commits April 10, 2026 09:38
Introduces a new `#[wasm_bindgen]` export `parseRecapFromSiwe(siweString)`
that decodes the recap capabilities embedded in a signed SIWE message and
returns them as an array of `{ service, space, path, actions }` entries.

This is the inverse of what `SessionConfig::into_message` produces when it
builds a session recap, and it is the primitive the JS SDK needs to decide
whether a requested delegation is a strict subset of the current session's
granted capabilities. When the subset check succeeds, the SDK can issue the
delegation via the existing `createDelegation` WASM path (session-key Ed25519
signature, no wallet prompt). When it does not, the SDK raises a permission
escalation flow.

Behavior:
- Recap-less SIWE returns an empty array (not an error); plain auth SIWE
  messages are valid inputs.
- Malformed SIWE, tampered recap statements, and unparseable resource URIs
  all propagate as errors instead of being silently swallowed.
- Actions are returned in deterministic sorted order (BTreeMap iteration).
- Multi-space sessions (primary + additional public companion) produce one
  entry per (space, service, path) triple.

Includes three Rust unit tests:
- roundtrip over a multi-service (kv/sql/capabilities) SIWE
- empty-vec behavior on a recap-less plain auth SIWE
- multi-space session yielding distinct entries per space
@skgbafa skgbafa merged commit 3e4b217 into main Apr 10, 2026
14 checks passed
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