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
{{ message }}
Repository navigation
Commit 0bd1491
Browse filesBrowse the repository at this point in the historyBrowse files
feat(platform-objects): the identity actions an agent may reach declare it, by risk
Bucket E actions declare ai.exposed with a model-facing description;
bucket C actions also declare requiresConfirmation: true; human-only
actions carry no ai block. ADR-0011 gains a dated addendum recording the
three buckets and the H rule. The MCP dogfood drives one action per
bucket with an OAuth-connected agent, and two tests whose premise was
"no platform identity action declares ai" follow the declarations.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4czk9umSFBVoz5cijzX
feat(platform-objects): the platform identity actions an agent may reach declare it — additive acts exposed, destructive lifecycle acts exposed behind confirmation, credential and ownership acts human-only
6
+
7
+
Clause-②: no
8
+
Metadata-protocol: none
9
+
10
+
The `sys_*` identity objects' actions now carry the ADR-0011 `ai` block by risk, as ADR-0011's 2026-10-30 addendum records (58 actions assessed, 38 declared):
11
+
12
+
-**Exposed (21).** Additive or self-scoped acts declare `ai: { exposed: true, description }`: the four `invite_user` mirrors, resending and accepting an invitation, adding a member to an organization or a team, creating, editing and renaming a team or an organization, switching the active organization, re-enabling an OAuth application, enabling two-factor authentication, updating your own profile, resending the verification email, and requesting SSO domain verification.
13
+
-**Exposed, confirmation required (17).** Destructive or privilege-changing lifecycle acts also declare `requiresConfirmation: true`, so MCP `run_action` refuses them `428 ACTION_CONFIRMATION_REQUIRED`, with nothing run, until the call carries `confirm: true`: banning, unbanning and unlocking a user, setting a user's manager, revoking an API key or a session, signing out other devices, cancelling or declining an invitation, removing a member or a team member, deleting a team, an OAuth application or an SSO provider, disabling an OAuth application, leaving an organization, and unlinking a sign-in provider.
14
+
-**Human-only (20).** Acts that mint a credential or a session, change ownership, a role or a sign-in factor, or destroy an account or an organization (impersonating a user, setting a password, creating a user or an API key, transferring ownership, changing a member's role, deleting an organization, and the rest the addendum names) declare no `ai` block and are not listed over MCP. `sys_invitation.copy_invitation_link` declares none either; it was not part of the assessment.
15
+
16
+
Over MCP these actions are listed and run behind every existing gate: the capability gate, the installation's action switch, the param contract, the confirmation gate and the identity route's own authorization. They are `type: 'api'` actions forwarded to identity routes that accept a signed-in session only, so an agent connected over OAuth sees them listed and is refused at the route when it runs one.
Copy file name to clipboardExpand all lines: docs/adr/0011-actions-as-ai-tools.md
+80Lines changed: 80 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -305,6 +305,86 @@ ships next.
305
305
306
306
---
307
307
308
+
## Addendum (2026-10-30): the platform identity actions an agent may reach
309
+
310
+
> Status of this addendum: **ruled** (ruling of record `6523087116` on #27900, letter A+), executing
311
+
> parameter 2 of ruling `6513869839` on #27681. The maintainer, verbatim:
312
+
> 「所以我说评估标准对象的意思,就是允许放开的动作,是不是就应该把申明加上」.
313
+
> It changes no rule of this ADR: it records how the platform's own `sys_*` identity actions apply the
314
+
> opt-in, and the declarations that follow from it.
315
+
316
+
The opt-in binds the platform's `sys_*` actions exactly as it binds an app's: an action reaches an
317
+
agent only when it declares `ai: { exposed: true, description }`. The named actions on the twelve
318
+
identity objects in `packages/platform-objects/src/identity/` were assessed once, as one set, into
319
+
three buckets, and the declarations were written in the same change as this addendum.
320
+
321
+
| Bucket | Test | What the action declares |
322
+
|:--|:--|:--|
323
+
|**H** human-only | it mints a credential or a session, changes who owns or who can sign in, or destroys an account or an organization | no `ai` block. ⛔ No `ai.exposed` on one of these without a maintainer ruling that names the action. |
324
+
|**C** exposed, confirmed | a destructive or privilege-changing lifecycle act that is reversible or bounded |`ai: { exposed: true, description, requiresConfirmation: true }`. ⛔ The confirmation is never relaxed. |
325
+
|**E** exposed | an additive or self-scoped act with no credential and no privilege escalation |`ai: { exposed: true, description }`; confirmation is the author's choice (none is declared today). |
// ADR-0011 identity-actions note, bucket C: exposed, and the
78
+
// confirmation is never relaxed.
79
+
ai: {
80
+
exposed: true,
81
+
description:
82
+
'Unlink an external sign-in provider from the user\'s account (the record; param: its accountId): they can no longer sign in with that provider until they link it again. Ask the human to confirm before calling.',
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
110
+
ai: {
111
+
exposed: true,
112
+
description:
113
+
'Invite a person by email address to join the current organization with a role (params: email, role). They join when they accept the invitation. Use when the user asks to invite someone who is not a member yet; the role options are only the roles the caller may grant.',
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
170
+
ai: {
171
+
exposed: true,
172
+
description:
173
+
'Send a pending invitation (the record) again (params: its email and role, copied from the invitation; the stored role is kept). Its expiry date starts over. Use when the invitee lost the invitation or never received it.',
174
+
},
155
175
},
156
176
{
157
177
// [#27843, ruling E on #27797] The pending invitation's accept link, for
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
240
+
ai: {
241
+
exposed: true,
242
+
description:
243
+
'Accept an invitation addressed to the current user (the record), joining its organization with the invited role. Works only on a pending invitation sent to the caller\'s own email address.',
confirmText: 'Decline this invitation? The inviter will be notified and you will need a new invitation to join.',
231
257
successMessage: 'Invitation declined',
232
258
refreshAfter: true,
259
+
// ADR-0011 identity-actions note, bucket C: exposed, and the
260
+
// confirmation is never relaxed.
261
+
ai: {
262
+
exposed: true,
263
+
description:
264
+
'Decline an invitation addressed to the current user (the record). The inviter is notified, and joining later needs a new invitation. Ask the human to confirm before calling.',
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
134
+
ai: {
135
+
exposed: true,
136
+
description:
137
+
'Invite a person by email address to join the current organization with a role (params: email, role). They join when they accept the invitation. Use when the user asks to invite someone who is not a member yet; the role options are only the roles the caller may grant.',
138
+
},
133
139
},
134
140
{
135
141
// Admin-only: directly attach an existing user to the active org,
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
210
+
ai: {
211
+
exposed: true,
212
+
description:
213
+
'Add an existing user straight into an organization with a role, without an invitation (params: userId, role, and optionally organizationId, which defaults to the active organization). Platform administrators only.',
// ADR-0011 identity-actions note, bucket C: exposed, and the
117
+
// confirmation is never relaxed.
118
+
ai: {
119
+
exposed: true,
120
+
description:
121
+
'Disable an OAuth application (the record; param: its client_id): its tokens are rejected and integrations using it stop working until it is re-enabled. Platform administrators only. Ask the human to confirm before calling.',
// ADR-0011 identity-actions note, bucket E: exposed by plain declaration.
146
+
ai: {
147
+
exposed: true,
148
+
description:
149
+
'Re-enable a disabled OAuth application (the record; param: its client_id), so token issuance, authorization and introspection resume for that client. Platform administrators only.',
// ADR-0011 identity-actions note, bucket C: exposed, and the
264
+
// confirmation is never relaxed.
265
+
ai: {
266
+
exposed: true,
267
+
description:
268
+
'Permanently delete an OAuth application (the record; param: its client_id): all tokens and consents issued to it are invalidated and its integrations stop working. This cannot be undone. Ask the human to confirm before calling.',
0 commit comments