feat(core): add location-based permission service (#30287)

This commit is contained in:
Dax 2026-06-01 21:32:50 -04:00 committed by GitHub
commit 9b815bcbd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 4971 additions and 553 deletions

View file

@ -104,23 +104,23 @@ export const Plugin = PluginV2.define({
const worktree = location.directory
const whitelistedDirs = [TRUNCATION_GLOB, path.join(Global.Path.tmp, "*")]
const readonlyExternalDirectory: PermissionV2.Ruleset = [
{ permission: "external_directory", pattern: "*", action: "ask" },
{ action: "external_directory", resource: "*", effect: "ask" },
...whitelistedDirs.map(
(pattern): PermissionV2.Rule => ({ permission: "external_directory", pattern, action: "allow" }),
(resource): PermissionV2.Rule => ({ action: "external_directory", resource, effect: "allow" }),
),
]
const defaults: PermissionV2.Ruleset = [
{ permission: "*", pattern: "*", action: "allow" },
{ action: "*", resource: "*", effect: "allow" },
...readonlyExternalDirectory,
{ permission: "question", pattern: "*", action: "deny" },
{ permission: "plan_enter", pattern: "*", action: "deny" },
{ permission: "plan_exit", pattern: "*", action: "deny" },
{ permission: "repo_clone", pattern: "*", action: "deny" },
{ permission: "repo_overview", pattern: "*", action: "deny" },
{ permission: "read", pattern: "*", action: "allow" },
{ permission: "read", pattern: "*.env", action: "ask" },
{ permission: "read", pattern: "*.env.*", action: "ask" },
{ permission: "read", pattern: "*.env.example", action: "allow" },
{ action: "question", resource: "*", effect: "deny" },
{ action: "plan_enter", resource: "*", effect: "deny" },
{ action: "plan_exit", resource: "*", effect: "deny" },
{ action: "repo_clone", resource: "*", effect: "deny" },
{ action: "repo_overview", resource: "*", effect: "deny" },
{ action: "read", resource: "*", effect: "allow" },
{ action: "read", resource: "*.env", effect: "ask" },
{ action: "read", resource: "*.env.*", effect: "ask" },
{ action: "read", resource: "*.env.example", effect: "allow" },
]
yield* agent.update((editor) => {
@ -129,8 +129,8 @@ export const Plugin = PluginV2.define({
item.mode = "primary"
item.permissions.push(
...PermissionV2.merge(defaults, [
{ permission: "question", pattern: "*", action: "allow" },
{ permission: "plan_enter", pattern: "*", action: "allow" },
{ action: "question", resource: "*", effect: "allow" },
{ action: "plan_enter", resource: "*", effect: "allow" },
]),
)
})
@ -140,15 +140,15 @@ export const Plugin = PluginV2.define({
item.mode = "primary"
item.permissions.push(
...PermissionV2.merge(defaults, [
{ permission: "question", pattern: "*", action: "allow" },
{ permission: "plan_exit", pattern: "*", action: "allow" },
{ permission: "external_directory", pattern: path.join(Global.Path.data, "plans", "*"), action: "allow" },
{ permission: "edit", pattern: "*", action: "deny" },
{ permission: "edit", pattern: path.join(".opencode", "plans", "*.md"), action: "allow" },
{ action: "question", resource: "*", effect: "allow" },
{ action: "plan_exit", resource: "*", effect: "allow" },
{ action: "external_directory", resource: path.join(Global.Path.data, "plans", "*"), effect: "allow" },
{ action: "edit", resource: "*", effect: "deny" },
{ action: "edit", resource: path.join(".opencode", "plans", "*.md"), effect: "allow" },
{
permission: "edit",
pattern: path.relative(worktree, path.join(Global.Path.data, "plans", "*.md")),
action: "allow",
action: "edit",
resource: path.relative(worktree, path.join(Global.Path.data, "plans", "*.md")),
effect: "allow",
},
]),
)
@ -159,7 +159,7 @@ export const Plugin = PluginV2.define({
"General-purpose agent for researching complex questions and executing multi-step tasks. Use this agent to execute multiple units of work in parallel."
item.mode = "subagent"
item.permissions.push(
...PermissionV2.merge(defaults, [{ permission: "todowrite", pattern: "*", action: "deny" }]),
...PermissionV2.merge(defaults, [{ action: "todowrite", resource: "*", effect: "deny" }]),
)
})
@ -172,14 +172,14 @@ export const Plugin = PluginV2.define({
...PermissionV2.merge(
defaults,
[
{ permission: "*", pattern: "*", action: "deny" },
{ permission: "grep", pattern: "*", action: "allow" },
{ permission: "glob", pattern: "*", action: "allow" },
{ permission: "list", pattern: "*", action: "allow" },
{ permission: "bash", pattern: "*", action: "allow" },
{ permission: "webfetch", pattern: "*", action: "allow" },
{ permission: "websearch", pattern: "*", action: "allow" },
{ permission: "read", pattern: "*", action: "allow" },
{ action: "*", resource: "*", effect: "deny" },
{ action: "grep", resource: "*", effect: "allow" },
{ action: "glob", resource: "*", effect: "allow" },
{ action: "list", resource: "*", effect: "allow" },
{ action: "bash", resource: "*", effect: "allow" },
{ action: "webfetch", resource: "*", effect: "allow" },
{ action: "websearch", resource: "*", effect: "allow" },
{ action: "read", resource: "*", effect: "allow" },
],
readonlyExternalDirectory,
),
@ -190,21 +190,21 @@ export const Plugin = PluginV2.define({
item.mode = "primary"
item.hidden = true
item.system = PROMPT_COMPACTION
item.permissions.push(...PermissionV2.merge(defaults, [{ permission: "*", pattern: "*", action: "deny" }]))
item.permissions.push(...PermissionV2.merge(defaults, [{ action: "*", resource: "*", effect: "deny" }]))
})
editor.update(AgentV2.ID.make("title"), (item) => {
item.mode = "primary"
item.hidden = true
item.system = PROMPT_TITLE
item.permissions.push(...PermissionV2.merge(defaults, [{ permission: "*", pattern: "*", action: "deny" }]))
item.permissions.push(...PermissionV2.merge(defaults, [{ action: "*", resource: "*", effect: "deny" }]))
})
editor.update(AgentV2.ID.make("summary"), (item) => {
item.mode = "primary"
item.hidden = true
item.system = PROMPT_SUMMARY
item.permissions.push(...PermissionV2.merge(defaults, [{ permission: "*", pattern: "*", action: "deny" }]))
item.permissions.push(...PermissionV2.merge(defaults, [{ action: "*", resource: "*", effect: "deny" }]))
})
})
}),