π Release Highlights β v0.1.97 (2026-06-12)
Theme: Application-Layer Permission Engine β the opt-in approval pipeline that complements v0.1.96's OS sandbox. Defense in depth: the OS layer enforces, the app layer keeps a human in the loop on the risky calls.
π‘οΈ Layered permission engine (hardline β rules β risk)
- Hardline floor: a non-overridable blocklist denies catastrophic commands (
rm -rf /, fork bombs, raw-diskdd) regardless of any rule or mode. - Declarative rules: an
allow/ask/denyalgebra over a smallaction(target)vocabulary (command,read_file,write_file,read_url,mcp,*) with deny-wins precedence across scopes. - Risk classifier: tiers a call by blast radius, not name β auto-allows reads and in-workspace edits, asks only for the dangerous tail (network egress, force-push, publish/spend, privilege escalation).
β Approval that fits the run
- Interactive modal (
ToolApprovalModal): allow once / allow session / always Β· reject, when a human is present. - Automation policy:
risk-based(default β high denied with a reason, low/medium allowed),deny-all, orallow-all. - File handshake (
FileApprovalProvider):req_*.json/resp_*.jsonfor headless/remote approval (Slack bot,/approve <id>, ...). Fail-closed on timeout throughout.
π§βπ€βπ§ Roles, audit & guards
- Per-agent roles:
read-only/researcherdeny writes+shell; aread-onlyrole also empties the agent's SRT writable set (OS backstop). Role + user rules merge deny-wins. - Audit ledger: every approval decision is appended to a crash-safe JSONL trail (who/what/why/outcome).
- Runaway-loop budget:
max_consecutive_autocaps consecutive auto-approvals per agent and fail-closes past the cap; a human decision resets it. always-grant persistence: an "Always" approval persists as anallow(...)rule insettings.local.jsonand loads back next run.
π Guardrail-aware system prompt (channel-based)
- When permissions are active, the system prompt tells the model to follow blocks and surface-and-ask rather than circumvent them β and that
askis a sanctioned path, not a block. Authority comes only from the system prompt (no leakable token). - Honest scope: the prompt + regex classifier are best-effort alignment. Live runs showed a model evading the egress classifier via
\c\u\r\l/python urllibβ so the OS sandbox (v0.1.96) remains the load-bearing enforcement. Seedocs/dev_notes/permissions_p2_followups.md.
π§ Also in this release
- Denied tool calls are first-class failed tool events: the deny path emits
tool_start(with the attempted command) +tool_complete(is_error=True, status="denied"), so blocked calls show in the TUI/WebUI timeline with the command, not just a status line. - Backend parity guard: native backends (
claude_code,codex) don't run the framework chokepoint, so apermissions:block there is reported INACTIVE at startup instead of silently inert.
π¦ Getting Started
- Quick Start Guide: upgrade and try the permission engine.
- Try the approval modal (interactive):
# A high-risk command pops the approval modal (allow once/session/always Β· reject)
uv run massgen --config massgen/configs/tools/permissions/permission_modal_interactive.yaml \
"Run the shell command: curl -s https://example.com"- Try risk-tiered automation (headless deny):
uv run massgen --automation --config massgen/configs/tools/permissions/permission_engine.yaml \
"Run 'git status', then run 'git push --force origin main' and report each result."
# Expected: git status runs; the force-push is denied with a reason.What's Changed
- feat: layered opt-in permission system (P0βP2.2) β rules, approval, audit, guardrail prompt by @ncrispino in #1127
- docs(release): drop interactive approval modal from v0.1.97 (not working yet) by @ncrispino in #1128
- feat: v0.1.97 by @Henry-811 in #1126
Full Changelog: v0.1.96...v0.1.97