Skip to content

[P2] AI scope keys declared but unenforced: skill.permissions + agent.knowledge (enforce-or-prune) #3686

Description

@os-zhuang

Split out of the #1878 §3 naming-drift recheck (#3677). The ledger has been made honest about these (#3685 marks both dead + authorWarn); this issue tracks the actual enforce-or-prune decision, which needs a product call and a cloud-side change.

Common shape

Both are declarative scope keys in the AI domain whose declaration face is in the open spec while their enforcement face would live in the closed cloud runtime — and the wire between them was never connected.

1. skill.permissions — no gate

  • Spec: packages/spec/src/ai/skill.zod.ts:121
  • Consumers: skill.form.ts (authoring input) + objectui SkillPreview.tsx:48 (echo). No gate. The cloud SkillRegistry reads active, triggerConditions, tools, labels/instructions/triggerPhrases — never permissions.
  • The Studio form labels the section "Access / Required permissions to use this skill" — a security-shaped promise with nothing behind it.
  • Cloud documents the intent without implementing it — packages/service-ai-studio/src/skills/metadata-authoring-skill.ts:15:

    - Layer permissions via Skill.permissions independent of the agent's permissions.

  • Note the live sibling: agent-level access/permissions are enforced (evaluateAgentAccess → 403, [P0][security] Agent access control is a no-op (permissions/visibility/access) #1884). So the mechanism exists; skill-level was simply never wired.

Decision needed: is skill-level gating a real requirement (the argued case: one agent serving different users should expose different skills — e.g. a refund skill only to managers), or is agent-level gating sufficient?

2. agent.knowledge — declares a scope the runtime ignores

  • Spec: packages/spec/src/ai/agent.zod.ts:35-48 (the topicssources naming drift itself is fixed, [P2] Naming drift → silent no-ops (spec key ≠ consumed key) #1891).
  • The retrieval path takes sourceIds from the LLM's tool-call arguments (cloud service-ai/src/tools/knowledge-tools.ts:96), never from the agent record. So an agent declared with knowledge: { sources: ['public_faq'] } can still search any other source the service exposes.
  • This is arguably not just inert config but a scope gap: the author declared a boundary and the model can step outside it.

Decision needed: wire agent.knowledge.sources as the default/ceiling for sourceIds (small change at the tool seam — but it is a behaviour change: today the LLM chooses freely), or mark it experimental and rely on knowledge-source-level access control.

Also worth scheduling: verify the other ten preview-only live claims

The same 2026-06 sweep marked 13 properties live citing only a preview renderer. Three were re-verified and all three were wrong or misleading (see #3685). The remaining ten are unverified:

action.execute / action.shortcut / action.bulkEnabled, flow.status / flow.active, skill.triggerPhrases, tool.category / tool.requiresConfirmation / tool.active / tool.builtIn

Each needs the same treatment: find a real runtime reader or downgrade to dead + authorWarn.

Refs #1878, #3677, #3685, #1884, #1891.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions