Additional
Permission System
Synced from github.com/CoWork-OS/CoWork-OS/docs
CoWork OS now uses a layered permission engine instead of a single risk-only approval gate. The goal is to make every tool decision explainable, persistent when needed, and reversible from the UI.
What The Engine Decides
Each tool request resolves to one of three outcomes:
allow- execute immediatelydeny- block executionask- prompt the user for approval
The decision includes:
- an exact reason code
- the matched rule or mode
- the scope that matched
- optional persistence targets for workspace or profile rules
Evaluation Order
Permission evaluation runs in this order:
- hard task restrictions and explicit task denylists
- hard guardrails and dangerous-command blocks
- coarse workspace capability gates
- workspace policy script results
- explicit permission rules
- mode defaults
- denial fallback escalation
Later stages never override earlier hard blocks.
Rule Sources
Permission rules can come from several places:
session- temporary grants and session-local rules stored inSessionRuntimeworkspace_db- workspace-local rules stored in SQLiteworkspace_manifest- checked-in workspace policy file at.cowork/policy/permissions.jsonprofile- encrypted profile-level rules in secure settingslegacy_guardrails- compatibility rules derived from older trusted-command patternslegacy_builtin_settings- compatibility rules derived from earlier settings models
When rules overlap, the more specific rule wins first. If specificity ties, the source priority is:
session > workspace_db > workspace_manifest > profile > legacy_* > mode
If source priority also ties, the effect priority is:
deny > ask > allow
Scope Types
The engine supports four explicit rule scopes:
tool- match a single tool by namepath- match a tool and absolute path prefixcommand_prefix- match a normalized shell command prefixmcp_server- match a specific MCP server backend
Path scopes are normalized to absolute paths. Command prefixes are whitespace-normalized before comparison. MCP server names are normalized for stable matching.
Permission Modes
Default behavior depends on the selected permission mode:
default- allow safe reads, ask on writes, deletes, shell, external services, and side-effecting MCP toolsplan- allow read-only tools, deny mutating and external tools by defaultaccept_edits- allow in-workspace file edits and reads, ask on deletes, shell, network side effects, and external servicesdont_ask- allow anything not hard-blocked or explicitly deniedbypass_permissions- skip prompts and ask-rules, but still enforce hard guardrails, task restrictions, workspace capability gates, and explicit deny rules
Denial Fallback
Soft denials are not always the end of the story.
CoWork tracks denial counts per permission fingerprint in SessionRuntime:
3consecutive soft denials trigger fallback escalation20total soft denials trigger fallback escalation
When a fingerprint crosses the threshold, the next evaluation can surface a direct prompt instead of silently repeating the same denial path.
Hard denials from guardrails, workspace capability gates, and explicit deny rules are never overridden by fallback.
Persistence Destinations
Different rule sources persist in different places:
- session rules and temporary grants live in
SessionRuntimesnapshots - workspace-local rules are stored in SQLite and mirrored to
.cowork/policy/permissions.json - profile rules are stored in encrypted secure settings
Workspace-local rule removal updates both the database row and the manifest mirror. If the manifest write fails, the database removal still succeeds and the UI reports the partial state.
User Surfaces
Users can manage permission state from two places:
- approval prompts, which can create one-shot or persisted rules
- Settings > System & Security, which manages default mode, profile rules, and workspace-local rules
The workspace-rule panel lets users browse and remove workspace-local rules directly without having to wait for another approval prompt.
Runtime Integration
SessionRuntime owns the session-local permission state and snapshot persistence.
TaskExecutor delegates permission decisions to the runtime and keeps only task bootstrap,
finalization, and UI projection responsibilities.