Skip to content

Commit e8cedec

Browse files
os-zhuangclaude
andauthored
docs: correct agent permission-model framing to match shipped D10 (#2856)
The agent docs described MCP OAuth as "runs as you / scopes narrow tool families" — inaccurate after the ADR-0090 D10 agent work shipped (#2838/#2843/#2845). An OAuth client is now an agent acting ON BEHALF OF the user, bounded by the INTERSECTION of the consent scopes and the user's own permissions/RLS, and scopes are a real data-layer ceiling (a data:read token can never write, even where the user could) — not just a tool-family filter. - packages/mcp/src/skill.ts (SKILL.md served to every connecting agent): fix "runs as you" → agent-on-behalf + scope-ceiling intersection. - content/docs/ai/agents.mdx: same correction, user-facing. - docs/design/permission-model.md: mark the overlap rule *enforced* (#2838/#2843/#2845); honestly mark the three still-PLANNED agent guardrails — the grant-ceiling *lint* (runtime intersection already caps it; the bind-time lint is #2849), destructive-action co-sign, and the double-signature audit provenance (writer stamps only the delegator today). - docs/adr/0090: status note that D10 evaluation semantics landed. mcp suite 66 green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a6db6e2 commit e8cedec

5 files changed

Lines changed: 44 additions & 15 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@objectstack/mcp': patch
3+
---
4+
5+
Docs accuracy: correct how the MCP SKILL.md describes an agent's authority to match the shipped ADR-0090 D10 model. An OAuth-connected client is an **agent acting on behalf of** the signing-in user — every call is bounded by the **intersection** of the consent scopes and that user's own permissions/RLS (a `data:read` token can never write, even where the user could), not simply "runs as you". (Companion doc-only edits to `content/docs/ai/agents.mdx` and `docs/design/permission-model.md` correct the same framing and honestly mark the still-planned agent guardrails — the grant-ceiling lint, destructive-action co-sign, and double-signature audit provenance.)

content/docs/ai/agents.mdx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ SKILL.md download (`GET /api/v1/mcp/skill`), and API-key minting.
5656
discovery metadata, clients self-register via Dynamic Client Registration
5757
(RFC 7591) and run an authorization-code + PKCE flow. Nothing is
5858
pre-registered with Anthropic or any central service, so **self-hosted and
59-
private deployments work out of the box**. You log in through the browser
60-
as yourself; every tool call runs under your permissions and RLS. Consent
61-
scopes (`data:read`, `data:write`, `actions:execute`) narrow which tool
62-
families the client gets.
59+
private deployments work out of the box**. You authorize the client in the
60+
browser; it then acts as an **agent on your behalf** (`principalKind: 'agent'`),
61+
bounded by the **intersection** of the consent scopes and your own
62+
permissions/RLS — it can never exceed either. The consent scopes
63+
(`data:read`, `data:write`, `actions:execute`) are a real ceiling, not just a
64+
tool-family filter: they narrow the exposed tools **and** cap what the agent
65+
can do at the data layer — a `data:read` token can never write a record even
66+
where you could, and `actions:execute` lets the agent invoke the business
67+
actions you are entitled to run.
6368
- **API key (headless).** Mint a key (`POST /api/v1/keys`, shown once) and
6469
send it as `x-api-key` — for CI, scripts, and agents without a browser.
6570

docs/adr/0090-permission-model-v2-concept-convergence.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ package-owned sets:
312312

313313
### D10 — Principal taxonomy; agents act on intersected authority
314314

315+
> **Status (2026-07):** the P1 ctx *shape* shipped pre-launch as written below; the agent
316+
> **evaluation semantics** have since landed — the intersection at every layer (#2838), the
317+
> producer that resolves an MCP OAuth client to `principalKind:'agent'` + `onBehalfOf` with a
318+
> scope-derived ceiling (#2843), and delegated action capabilities (#2845). Follow-ups tracked in
319+
> #2849 (agent action-body boundary / grant-ceiling lint) and the agent audit-provenance gap.
320+
315321
ExecutionContext principals gain an explicit taxonomy:
316322

317323
```

docs/design/permission-model.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,15 +270,24 @@ Every request carries a **principal** — who (or what) is asking. Five kinds, i
270270
**both** the assistant is allowed to do **and** 张三 is allowed to do — the overlap, never the
271271
union. Why: if an assistant with big permissions simply obeyed whoever prompts it, any intern
272272
could ask it to fetch the CEO's records. The overlap rule makes that structurally impossible.
273+
*Status: enforced.* The evaluator intersects the agent's own grants with the delegator's at every
274+
layer — object CRUD, FLS, depth, row-level `using`/`check`, and RLS — and the producer resolves an
275+
MCP OAuth client to `principalKind:'agent'` + `onBehalfOf` with a scope-derived ceiling
276+
(#2838 / #2843 / #2845). An agent's own View-All is stripped unless the delegator also holds it.
273277

274278
Three more agent guardrails:
275279

276-
1. **Ceiling** — sets held by agents may never contain super-user bits (View/Modify All, purge,
277-
transfer, system permissions). Lint rejects the binding, not the request.
278-
2. **Human co-sign for destructive actions** — an agent may *start* a deletion or mass change,
279-
but a human must confirm it, regardless of grants.
280-
3. **Double signature in the audit log** — every agent write records both "performed by:
281-
assistant-X" and "on behalf of: 张三", plus the run that did it.
280+
1. **Ceiling** — an agent can never wield super-user bits (View/Modify All, purge, transfer, system
281+
permissions) it does not *also* hold via the delegator: the intersection above caps it at
282+
runtime today. *Planned:* a dedicated authoring lint that rejects **binding** such a set to an
283+
agent up front (defense-in-depth on top of the runtime cap) — see #2849.
284+
2. **Human co-sign for destructive actions** — an agent may *start* a deletion or mass change, but a
285+
human confirms it, regardless of grants. *Planned* (HITL signal exists on actions; the enforced
286+
co-sign gate is not yet wired).
287+
3. **Double signature in the audit log** — every agent write should record both "performed by:
288+
assistant-X" and "on behalf of: 张三", plus the run that did it. *Planned:* the audit writer
289+
currently stamps only the delegating user; agent provenance (principal kind + client) is not yet
290+
captured.
282291

283292
## 10. Running a large organization
284293

packages/mcp/src/skill.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ description: ${OBJECTSTACK_SKILL_DESCRIPTION}
6060
6161
${intro} An ObjectStack environment exposes its data **objects** (tables) and
6262
its business **actions** (registered app logic: approvals, conversions, flow
63-
triggers) as tools over the Model Context Protocol (MCP). Every operation runs **as you** —
64-
under your account's permissions and row-level security — so you may see a
65-
subset of rows, or get a permission error on a write. That is expected
63+
triggers) as tools over the Model Context Protocol (MCP). Every operation runs
64+
under the permissions and row-level security of the identity that connected you
65+
— and, for an OAuth connection, **within the consent scopes you were granted**
66+
(a read-only scope can never write, even where that user could). So you may see
67+
a subset of rows, or get a permission error on a write. That is expected
6668
governance, not a failure.
6769
6870
## When to use
@@ -88,8 +90,10 @@ Two authentication tracks are supported:
8890
server with no credentials; the deployment is its own OAuth 2.1 authorization
8991
server, so an OAuth-capable client (claude.ai custom connectors, Claude
9092
Desktop, Claude Code) discovers it automatically, registers itself, and opens
91-
a browser login. You sign in as yourself and every tool call runs under your
92-
own permissions. Example (Claude Code):
93+
a browser login. You authorize the connection in the browser; the client then
94+
acts as an agent **on your behalf** — every tool call is bounded by the
95+
intersection of the consent scopes you grant and your own permissions/RLS (it
96+
can never exceed either). Example (Claude Code):
9397
9498
\`\`\`
9599
claude mcp add --transport http objectstack ${url}

0 commit comments

Comments
 (0)