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
approvals: an admin override of a staffed approver slate is recorded as an ordinary approval — no override marker anywhere #4466
Found while verifying the 17.0.0-rc.1 checklist on #3909 (section C, "admin override for unstaffed approver #3424"). Verified on main @ 1ee48bc60, showcase under os serve --dev.
What happened
Driving the showcase_dynamic_approval flow (#3447's specimen), stage 2 (co_sign) resolved its expression approvers correctly to exactly one designated user:
{"id":"areq_5a2a0b05…","status":"pending","step":"co_sign",
"pending_approvers":"QcKhACD4LXgVxGMluaOfqxU9T2VBzfZH"} ← the member, not the admin
The admin, who is not in that slate, approved it anyway (the privileged-override path, #3424) — and the designated approver then got 409 INVALID_STATE: request is approved.
The override itself is defensible: isOverrideActor's own docstring says an admin "may always act on a PENDING request to release it". The problem is what the audit trail records:
sys_approval_action has no override column at all — its full field list is request_id, step_name, step_index, action, actor_id, comment, reassign_from, reassign_to, attachments, created_at, …. So an admin overriding a properly-staffed approver slate is byte-for-byte indistinguishable from the designated approver approving normally.
Why it matters
The whole point of an approval record is to answer "who authorized this, and were they entitled to?". Right now:
A reader of the timeline sees approve by the admin and cannot tell whether the admin was an approver or overrode the ones who were.
The designated approver's 409 is the only trace that a slate was bypassed, and it exists only if they happen to try.
The platform knows at decision time — it took the isOverrideActor branch to allow the call — so this is dropped information, not unavailable information.
This also sits oddly against the sibling work this train shipped: #3800 made decisions attribute to the authenticated caller, #3783 made the status mirror name the human, and #4366 gave flow system-writes audit attribution. The override flag is the one bit of "who really decided this" that still isn't recorded.
Note the gap between the docstring's justification and the implemented rule: the comment motivates the override with a stuck request (routed to a position with no holders), but isOverrideActor only tests whether the actor is an admin — it never tests whether the slate is actually unresolvable. Whether that breadth is intended is worth confirming separately; either way the decision should say it was an override.
Expected
sys_approval_action carries an override marker (e.g. via_override: boolean, or an action: 'approve_override' variant) set on exactly the decisions that took the privileged path, surfaced in the timeline. If the breadth is intended, the record is what makes it auditable rather than silent.
Part of the #3909 rc.0/rc.1 verification (section C).
Activity
baozhoutao commentedon Aug 1, 2026
Tracked under the v17 verification tracker #3909 (section C).
baozhoutao commentedon Aug 1, 2026
Rolled up in #4482 (all 17 defects from the v17 verification, grouped by severity with a suggested RC-exit triage).
fix(approvals): record an admin override of a staffed approver slate …
fix(automation,approvals): 屏幕流 resume 服务端校验 + 审批越权可审计 (objectstack-ai…
docs(automation): 屏幕流 resume 契约与审批越权标记的文档 + 两份 changeset(objectstack-…