fix(state): typed Permission on SetPermission#440
Merged
intendednull merged 1 commit intoApr 27, 2026
Merged
Conversation
SetPermission.permission was String. Took anything. "FrobnicateWidgets" sail past apply, land in role.permissions set. Same role.permissions also String-typed — pollution sticks. Now: SetPermission.permission: Permission. Role.permissions: BTreeSet<Permission>. Type system bars unknown names from ever entering DAG. Back-compat: custom Deserialize maps unknown legacy string-form names (JSON / MCP boundary) to hidden __UnknownLegacy sentinel. apply_event drops sentinel as no-op + tracing::warn — DAG signature stays intact, bad name dropped. Bincode wire path emits typed enum directly; pre-1.0, no production storage round-trips legacy String form, so binary cutover safe (storage SQLite holds bincode bytes, not JSON). Agent MCP tool keeps string param on wire, parses via Permission::from_name at boundary, errors on unknown. Runner-up: hard cutover (Deserialize accepts only typed enum). Rejected — a rogue / future client emitting unknown name would currently break the chain on insert; sentinel keeps DAG resilient with no security loss. Refs #240
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.
Why
SetPermission.permission was String. Anything stored. "FrobnicateWidgets"
walks past apply, lands in role.permissions. Role.permissions also
String — pollution sticks. Compare GrantPermission, already typed.
Fix
hidden Permission::__UnknownLegacy sentinel. apply_event drops
sentinel + warns — DAG sig + chain stays intact, bad perm dropped
Permission::from_name at boundary, errors on unknown
Migration choice
Custom Deserialize back-compat (a) over hard cutover (b). Bincode wire
path is pre-1.0 — no production SQLite storage round-trips
String-form events to disk (storage holds bincode bytes for typed
enum, JSON path retained for MCP / future snapshots). Sentinel keeps
DAG resilient against rogue / future clients.
Tests
cargo test --workspacegreen, clippy clean, WASM check clean.Refs #240
Generated by Claude Code