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
spec: ai.requiresConfirmation's describe says REST /actions reads no ai.exposed opt-in, which PR #32912 makes untrue for an AI service account starting a runAs:system flow action #32924
Blocked-by: #32912
Part of: follow-up of #31874 (ruling C, comment 6812617393)
Source: contract review of PR #32912, record 6839053991, should-fix S1 and S2.
Problem
packages/spec/src/ai/tool.zod.ts (the requiresConfirmation.describe() string, around line 96, a published string) defines the confirmation gate's enforced set as "the doors that enforce the author's ai.exposed opt-in — today the action door reached from the MCP run_action tool", and says "REST /actions is NOT ai.exposed-gated". Once PR #32912 lands, the REST actions route DOES read the opt-in for one pair: an AI service account (an agent principal with no onBehalfOf) starting a type: 'flow' action whose flow declares runAs: 'system' is refused unless the action declares ai.exposed: true. The published sentence then gives a wrong reason for that pair.
Decision for the maintainer (S2), before or with item 1: the 403 from fix(runtime, service-automation)!: an AI service account starts a flow that runs as the system only through an action its author opted into AI #32912 points the account at "the REST actions route or the MCP run_action tool" as equals, yet an author's ai.requiresConfirmation: true on the same action is asked only on MCP. Options: (A) keep it so (document the asymmetry in the describe string); (B) the REST route also asks confirm: true of an AI service account on an action declaring ai.requiresConfirmation: true. B widens the REST refusal set (BREAKING for that caller) and needs its own contract review. Not owed by ruling C.
Acceptance
The describe string names no door wrongly; pnpm --filter @objectstack/spec generated artefacts regenerated; prose-only unless the maintainer picks B.
Clause-②: no for item 1 alone (describe text, no accept-set change).
One more prose row for whoever takes this card (docs-drift on PR #32912): content/docs/permissions/system-context.mdx row 57 lists what the system principal bypasses at flowStartRefusal (elevated self-triggered start, requiredPermissions, the start-record check) and does not yet name the AI-service-account rule PR #32912 adds (an account at a runAs: 'system' flow without the action's ai.exposed: true opt-in). Add it to that row once #32912 lands; prose only.
Claim: PM loop round 1 · 2026-11-13T06:00Z
Session: session_01L9qibvfX5bawZKtfa6u7j9 (seat); card thread session_01L9qibyxGyX6L3NhaTF6yiA is the dev
Account: os-tesla
Branch: claude/project-thread-4nuxb0 (the card thread's designated branch; the platform lets a thread push only that branch, so not claude/issue-32924-*)
Worktree: objectstack-issue-32924
Domain: domain:spec
Seat: domain:spec#2
File surface: packages/spec/src/ai/tool.zod.ts and the artefacts its describe string regenerates; content/docs/permissions/system-context.mdx row 57 (comment 6839421711); root .changeset/ (stop on breach; explain in the report)
Container & model: S, mode:thread, model: default tier (describe prose, no accept-set change), effort: medium (fleet token rule 2, maintainer 2026-11-12)
Clause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: 6842399378
Premise: holds at origin/mainc54a23d2: packages/spec/src/ai/tool.zod.ts :102–103 still says REST /actions is NOT ai.exposed-gated, while PR #32912 (merged) makes that route ask the opt-in of an AI service account starting a runAs: 'system' flow action. Scope is item 1 only; item 2 (the S2 choice) is the maintainer's and stays open, so the PR says Part of #32924.
Serial constraints cleared: no open PR touches packages/spec/src/ai/**. PR #32966 (Tier H, awaiting a human) also edits system-context.mdx; this card touches row 57's text only and merges main once if #32966 lands first.
{
"issue": 32924,
"status": "done",
"branch": "claude/project-thread-4nuxb0",
"pr": "https://github.com/objectstack-ai/objectstack/pull/33056",
"session": "session_01L9qibyxGyX6L3NhaTF6yiA",
"premise_still_valid": true,
"summary": "Item 1 only. The tool.requiresConfirmation rejection prescription (TOOL_RETIRED_KEY_GUIDANCE in packages/spec/src/ai/tool.zod.ts) no longer says REST /actions is never ai.exposed-gated: it names the one pair REST reads the opt-in for (an AI service account starting a type: 'flow' action whose flow declares runAs: 'system', flowStartRefusal rule 2) and says that check asks no confirmation; for a person's call REST stays outside the confirmation gate. system-context.mdx row 57 gains the AI-service-account start rule (comment 6839421711). Changeset @objectstack/spec patch. PR says Part of #32924; item 2 untouched.",
"tests": "head 4379cff9: spec build (lock VERDICT command-exit 0); vitest src/ai/ Test Files 16/16, Tests 406/406 incl. tool-confirmation-prescription-tense.pin.test.ts; check:generated all 14 artefacts up to date (the string feeds no generated artefact). Prose only: no new test, no ablation.",
"gates": "dispatch-gates --commands: 99 families, all run </dev/null with exit codes; --ran: 99 run, 0 NOT-MEASURED (derived zero). 6 exited 3 first (prerequisites) and 0 after turbo build of ./packages/** (81/81). Record: /mnt/project-files/spec-seat-2/r2026-11-13/out/32924-gates-ran-4379cff9.list. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (#33056, assignees os-tesla); this os-dev-report comment via post-stamped",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"class: b · reach: exception: release-text · packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts replacement (L15-18) and acceptance text (L57-60) still say REST /actions is not ai.exposed-gated and that an agent holding an API key on that route is yours to put a human in front of; untrue since ADR-0151 D3 rule 3 (AI service account refused at every action door) and #32912. Outside this card's file surface. dedupe words: requiresConfirmation, semantic migration, ai.exposed-gated, tool-requires-confirmation-retired",
"carrier: seat"
],
"deviations": "edited in the container's primary checkout on the platform-designated branch rather than a separate worktree (single-agent container)."
}
Added:packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts (the replacement and acceptanceCriteria sentences that say REST /actions is not ai.exposed-gated) and whatever it projects to (spec-changes.json, upgrade-guide output), regenerated in the same change.
MERGED 2026-11-13T08:09:45Z, landing head a8f3da02 (ACCEPT 6847228135; contract review PASS 6846718400, delta PASS 6847209749); ships with 18.4.0
Item 1
done: the requiresConfirmation guidance, the 17 semantic migration entry and permissions/system-context.mdx row 57 now name the one pair REST /actions asks ai.exposed of
Item 2
open, the maintainer's call: whether REST /actions also asks confirm: true of an AI service account
State: pm:dispatched removed; the card stays open (Part of) for item 2 only.
For the item 2 decision: the reviewer (record 6846718400 ③) reads its premise as overtaken. REST /actions already refuses an AI service account acting for itself at the confirmation gate (packages/runtime/src/action-dispatch.ts ~L460, 428), which is stricter than asking it for confirm: true. If the maintainer agrees, item 2 can close as no change.
Triage: state repair → pm:queue · 2026-11-13T08:46Z
The card lost its pm state when item 1 landed (PR #33056, 08:09Z). The card is still open for its remaining items, so it goes back to pm:queue (domain:spec p2, unchanged).
Release: session_01L9qibvfX5bawZKtfa6u7j9 · seat signs off on the maintainer's 「所有座位当前任务处理完,合并后就下班」; the assignee was left over after item 1 landed (6847673351) and triage's repair to pm:queue (6848307449) · stays in pm:queue for item 2, which is still the maintainer's call
Resume-from: none
Basis (verified on origin/mainfd7b378c by the evaluation):packages/runtime/src/action-dispatch.ts L454–471 asks the confirmation gate when posture === 'ai' || isAiServiceAccountCaller(ec), so REST /actions already refuses an AI service account on an action declaring ai.requiresConfirmation: true with 428 ACTION_CONFIRMATION_REQUIRED, with or without confirm: true (ADR-0151 D3 rule 3). That is stricter than option B; pinned in action-dispatch.test.ts. The prose already says so since item 1 (PR fix(spec): the tool.requiresConfirmation guidance names the one pair REST /actions asks ai.exposed of #33056).
Activity
objectstack-fleet commentedon Nov 12, 2026
domain:server#8 · os-elon-musk · session_016WV4cwqTK71kjQzHae8T5J
One more prose row for whoever takes this card (docs-drift on PR #32912):
content/docs/permissions/system-context.mdxrow 57 lists what the system principal bypasses atflowStartRefusal(elevated self-triggered start,requiredPermissions, the start-record check) and does not yet name the AI-service-account rule PR #32912 adds (an account at arunAs: 'system'flow without the action'sai.exposed: trueopt-in). Add it to that row once #32912 lands; prose only.objectstack-fleet commentedon Nov 13, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Unblocked →
pm:queue· 2026-11-13T02:53ZEvery
Blocked-by:edge on this card (#32912) is now closed. Triage did not change the grade.Generated by Claude Code
objectstack-fleet commentedon Nov 13, 2026
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9
Claim: PM loop round 1 · 2026-11-13T06:00Z
Session:
session_01L9qibvfX5bawZKtfa6u7j9(seat); card threadsession_01L9qibyxGyX6L3NhaTF6yiAis the devAccount:
os-teslaBranch:
claude/project-thread-4nuxb0(the card thread's designated branch; the platform lets a thread push only that branch, so notclaude/issue-32924-*)Worktree:
objectstack-issue-32924Domain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/ai/tool.zod.tsand the artefacts its describe string regenerates;content/docs/permissions/system-context.mdxrow 57 (comment 6839421711); root.changeset/(stop on breach; explain in the report)Container & model: S,
mode:thread,model: default tier(describe prose, no accept-set change),effort: medium(fleet token rule 2, maintainer 2026-11-12)Clause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: 6842399378
Premise: holds at
origin/mainc54a23d2:packages/spec/src/ai/tool.zod.ts:102–103 still says REST/actionsis NOTai.exposed-gated, while PR #32912 (merged) makes that route ask the opt-in of an AI service account starting arunAs: 'system'flow action. Scope is item 1 only; item 2 (the S2 choice) is the maintainer's and stays open, so the PR saysPart of #32924.Serial constraints cleared: no open PR touches
packages/spec/src/ai/**. PR #32966 (Tier H, awaiting a human) also editssystem-context.mdx; this card touches row 57's text only and merges main once if #32966 lands first.objectstack-fleet commentedon Nov 13, 2026
domain:spec#2 · os-tesla · session_01L9qibyxGyX6L3NhaTF6yiA
os-dev-report
{ "issue": 32924, "status": "done", "branch": "claude/project-thread-4nuxb0", "pr": "https://github.com/objectstack-ai/objectstack/pull/33056", "session": "session_01L9qibyxGyX6L3NhaTF6yiA", "premise_still_valid": true, "summary": "Item 1 only. The tool.requiresConfirmation rejection prescription (TOOL_RETIRED_KEY_GUIDANCE in packages/spec/src/ai/tool.zod.ts) no longer says REST /actions is never ai.exposed-gated: it names the one pair REST reads the opt-in for (an AI service account starting a type: 'flow' action whose flow declares runAs: 'system', flowStartRefusal rule 2) and says that check asks no confirmation; for a person's call REST stays outside the confirmation gate. system-context.mdx row 57 gains the AI-service-account start rule (comment 6839421711). Changeset @objectstack/spec patch. PR says Part of #32924; item 2 untouched.", "tests": "head 4379cff9: spec build (lock VERDICT command-exit 0); vitest src/ai/ Test Files 16/16, Tests 406/406 incl. tool-confirmation-prescription-tense.pin.test.ts; check:generated all 14 artefacts up to date (the string feeds no generated artefact). Prose only: no new test, no ablation.", "gates": "dispatch-gates --commands: 99 families, all run </dev/null with exit codes; --ran: 99 run, 0 NOT-MEASURED (derived zero). 6 exited 3 first (prerequisites) and 0 after turbo build of ./packages/** (81/81). Record: /mnt/project-files/spec-seat-2/r2026-11-13/out/32924-gates-ran-4379cff9.list. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (#33056, assignees os-tesla); this os-dev-report comment via post-stamped", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "class: b · reach: exception: release-text · packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts replacement (L15-18) and acceptance text (L57-60) still say REST /actions is not ai.exposed-gated and that an agent holding an API key on that route is yours to put a human in front of; untrue since ADR-0151 D3 rule 3 (AI service account refused at every action door) and #32912. Outside this card's file surface. dedupe words: requiresConfirmation, semantic migration, ai.exposed-gated, tool-requires-confirmation-retired", "carrier: seat" ], "deviations": "edited in the container's primary checkout on the platform-designated branch rather than a separate worktree (single-agent container)." }objectstack-fleet commentedon Nov 13, 2026
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9
File surface amended (claim 6845498057) · 2026-11-13T06:43Z
packages/spec/src/migrations/entries/semantic/17.tool-requires-confirmation-retired.ts(thereplacementandacceptanceCriteriasentences that say REST/actionsis notai.exposed-gated) and whatever it projects to (spec-changes.json, upgrade-guide output), regenerated in the same change.tool.zod.ts, and the entry is what the upgrade guide projects to consumers of the 18.4.0 release.Part of #32924.objectstack-fleet commentedon Nov 13, 2026
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9
Item 1 landed · 2026-11-13T08:11Z
a8f3da02(ACCEPT 6847228135; contract review PASS 6846718400, delta PASS 6847209749); ships with 18.4.0requiresConfirmationguidance, the 17 semantic migration entry andpermissions/system-context.mdxrow 57 now name the one pair REST/actionsasksai.exposedof/actionsalso asksconfirm: trueof an AI service accountState:
pm:dispatchedremoved; the card stays open (Part of) for item 2 only.For the item 2 decision: the reviewer (record 6846718400 ③) reads its premise as overtaken. REST
/actionsalready refuses an AI service account acting for itself at the confirmation gate (packages/runtime/src/action-dispatch.ts~L460,428), which is stricter than asking it forconfirm: true. If the maintainer agrees, item 2 can close as no change.objectstack-fleet commentedon Nov 13, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: state repair →
pm:queue· 2026-11-13T08:46ZThe card lost its pm state when item 1 landed (PR #33056, 08:09Z). The card is still open for its remaining items, so it goes back to
pm:queue(domain:specp2, unchanged).Generated by Claude Code
objectstack-fleet commentedon Nov 14, 2026
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9
Release: session_01L9qibvfX5bawZKtfa6u7j9 · seat signs off on the maintainer's 「所有座位当前任务处理完,合并后就下班」; the assignee was left over after item 1 landed (6847673351) and triage's repair to
pm:queue(6848307449) · stays inpm:queuefor item 2, which is still the maintainer's callResume-from: none
Generated by Claude Code
objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag
Ruled: item 2 closes as no change · card closed completed · 2026-11-14T16:22Z
origin/mainfd7b378cby the evaluation):packages/runtime/src/action-dispatch.tsL454–471 asks the confirmation gate whenposture === 'ai' || isAiServiceAccountCaller(ec), so REST/actionsalready refuses an AI service account on an action declaringai.requiresConfirmation: truewith428 ACTION_CONFIRMATION_REQUIRED, with or withoutconfirm: true(ADR-0151 D3 rule 3). That is stricter than option B; pinned inaction-dispatch.test.ts. The prose already says so since item 1 (PR fix(spec): the tool.requiresConfirmation guidance names the one pair REST /actions asks ai.exposed of #33056).completed.