You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Model Directory Permissions via User-Defined Trust Tiers
Important
Decision Surface
Problem: All LLM providers currently share identical file access permissions. Users who work with multiple providers (Anthropic, OpenAI, Meta, etc.) have no way to restrict what directories or actions a specific model can access — even though providers have different data-handling policies and some models within the same provider (e.g., Meta Muse vs Meta Llama) have different privacy tiers.
Approach: Add a Provider Permission Layer with user-defined trust tiers. Users create named tiers (e.g., "Trusted", "Limited", "Untrusted"), assign models to tiers, and configure directory × action permission matrices per tier. Ships with 3 presets + a default "Unassigned" tier. Enforced at tool-call time AND context assembly — strict privacy filtering including history redaction on model switch.
Approaches Considered:
(A) Provider Permission Layer with trust tiers (selected) — clean separation, wraps existing permission system, maps well to the UI, keeps single-session model
(B) Extended Rule Schema — extends existing Permission.Rule with an optional provider field; minimal new abstractions but harder to present in UI and rule evaluation becomes complex
(C) Sandboxed Provider Sessions — strongest isolation (virtual filesystem scoping per provider) but heaviest implementation, breaks single-conversation model
Scope: New "Permissions" tab in settings dialog. Schema + config changes. Enforcement hook in permission system. Source-path tagging on tool results. Context filtering + history redaction on model switch.
Assumptions:
Permissions are global (not per-project)
Provider permission grants suppress normal ask prompts (authoritative layer)
A model belongs to exactly one tier at a time
The "Unassigned" default tier cannot be deleted
Acceptance Criteria
A new "Permissions" tab appears in the settings dialog (6th tab)
Users can create, rename, reorder, and delete trust tiers (except "Unassigned")
3 preset tiers ship by default: Trusted (full access), Limited (read-only), Untrusted (no access), plus a non-deletable "Unassigned" (ask-all) default
Each tier has a directory × action matrix with per-cell allow/deny/ask toggles
Models are assigned to tiers via a multi-select picker inside each tier card
A model can only belong to one tier; reassignment removes it from the previous tier
Unassigned models fall through to the "Unassigned" default tier
At tool-call time, the active model's tier permissions are resolved BEFORE the existing global permission system
A tier "allow" for an action+directory suppresses the normal permission ask prompt
A tier "deny" blocks the tool call immediately (no prompt, no fallthrough)
On model switch mid-session, permissions re-evaluate immediately against the new model's tier
Context filtering: file contents from directories denied by the active tier are never included in the system prompt or auto-context
History redaction: on model switch, file contents in message history from now-denied directories are replaced with [Content from {path} filtered — trust tier "{tierLabel}" does not have read access]
Source-path metadata is preserved on all tool results that return file content
Dangerous actions (Execute, Network) are visually highlighted with warning styling when set to "allow"
Each tier card shows a computed summary badge: "Full Access" (⚠️), "Read Only", "No Access", "Ask Everything", or "Custom"
Config persists to ~/.config/opencode/opencode.jsonc under providerPermissions AND interactive "always" grants persist to SQLite (keyed by tier)
Directory rules support glob patterns (e.g., ~/secrets/**, src/private/**)
Key Decisions
#
Decision
Rationale
1
Trust tiers (not per-provider or per-model directly)
Handles intra-provider variance (Meta Muse ≠ Meta Llama); fewer configs than N models; conceptually familiar (RBAC-like)
2
4 action groups, not 8+ individual toggles
Cognitively manageable in a checkbox matrix; covers the real privacy boundaries (read vs mutate vs execute vs exfiltrate)
3
Strict context filtering + history redaction
The privacy guarantee must be real — filtering only tool execution while leaking content in context defeats the purpose
4
Global scope only (not per-project)
Simpler mental model; users set trust once. Per-project tightening can be a follow-up
5
Provider grant is authoritative (suppresses ask)
Avoids double-prompting; if you've explicitly trusted a tier with read access, the per-tool ask is redundant noise
6
Source-path tagging on tool results
Required for redaction; also enables future audit/lineage features
Tier resolution must be O(1) per tool call (map lookup, not list scan)
History redaction must not mutate the stored message history — it filters at send-time only (the original messages remain for re-evaluation if the model switches back)
Source-path metadata adds zero runtime cost when no model switch occurs
Prior Art
Existing Permission system in packages/core/src/permission.ts — action × resource × effect rules with assert() + SQLite persistence
LocationMutation in packages/core/src/location-mutation.ts — external directory detection and boundary enforcement
Per-agent permission rulesets in packages/schema/src/agent.ts — precedent for scoped permission evaluation
type: spec
date: 2026-08-10
status: draft
priority: p2
platform: opencode
tags: [spec, permissions, privacy, settings-ui, multi-provider]
linked_plan: null
Model Directory Permissions via User-Defined Trust Tiers
Important
Decision Surface
Problem: All LLM providers currently share identical file access permissions. Users who work with multiple providers (Anthropic, OpenAI, Meta, etc.) have no way to restrict what directories or actions a specific model can access — even though providers have different data-handling policies and some models within the same provider (e.g., Meta Muse vs Meta Llama) have different privacy tiers.
Approach: Add a Provider Permission Layer with user-defined trust tiers. Users create named tiers (e.g., "Trusted", "Limited", "Untrusted"), assign models to tiers, and configure directory × action permission matrices per tier. Ships with 3 presets + a default "Unassigned" tier. Enforced at tool-call time AND context assembly — strict privacy filtering including history redaction on model switch.
Approaches Considered:
Permission.Rulewith an optionalproviderfield; minimal new abstractions but harder to present in UI and rule evaluation becomes complexScope: New "Permissions" tab in settings dialog. Schema + config changes. Enforcement hook in permission system. Source-path tagging on tool results. Context filtering + history redaction on model switch.
Assumptions:
Acceptance Criteria
[Content from {path} filtered — trust tier "{tierLabel}" does not have read access]~/.config/opencode/opencode.jsoncunderproviderPermissionsAND interactive "always" grants persist to SQLite (keyed by tier)~/secrets/**,src/private/**)Key Decisions
Data Contract
Constraints & Invariants
Prior Art
Permissionsystem inpackages/core/src/permission.ts— action × resource × effect rules withassert()+ SQLite persistenceLocationMutationinpackages/core/src/location-mutation.ts— external directory detection and boundary enforcementpackages/schema/src/agent.ts— precedent for scoped permission evaluationpackages/app/src/components/settings-v2/— existing settings dialog with 5 tabs (General, Shortcuts, Servers, Providers, Models)Vertical Slices
resolveProviderPermission()intopermission.tsbefore existingassert()redactHistory()on model switch, filter denied content at send-timeSource
Brainstorming session — model directory permissions for privacy-conscious multi-provider usage.