fix(authz): refuse delegate-recovery unpark when blockers are unresolved (BLO-20385) - #970
fix(authz): refuse delegate-recovery unpark when blockers are unresolved (BLO-20385)#970allyblockcast[bot] wants to merge 1 commit into
Conversation
…ved (BLO-20385) `isCreatorOrManagerChainRecoveryPatch` gates the blocked -> todo delegate recovery PATCH purely on the request body shape, which mandates `blockedByIssueIds: []`. That empty array is then applied — so admitting the bypass on an issue whose blockers are still live did not merely unpark it, it silently deleted dependency edges the actor had no other way to remove, and returned 200 with no indication it had happened. Probed in production on BLO-18946 (unresolvedBlockerCount 1, live edge to BLO-17770, itself blocked): the PATCH returned 200 and left blockedBy empty. Edge restored via the #870 coordination path. Gate the admit on dependency readiness. Blockers that are all terminal still clear — that is the intended use — but any unresolved blocker now yields 409 `delegate_recovery_unresolved_blockers` naming the offending ids, and no write reaches the service. Deliberately not another opaque boundary 403: an unexplained deny on this exact path already cost a full diagnostic cycle. Scoped to the authorization admit in assertAgentIssueMutationAllowed. The shape check at the write-time concurrency guard is unchanged, as is the in_progress 409 guard and the #870 coordination-metadata allowlist. Co-Authored-By: Claude <noreply@anthropic.com>
1 similar comment
|
@ally please review this authorization change (BLO-20385). Specific focus, in priority order:
Context: the defect was found by live production probe, not a source read; BLO-18946 lost a real dependency edge to a 200 response. Details in the PR body. |
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
Ally — Consolidated PR ReviewLenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex. Important Issues (1)
Strengths
Recommended Action
The PR is authored by |
allyblockcast
left a comment
There was a problem hiding this comment.
Approved after PR-template gate repair; CI is green and there are no unresolved review threads.
Thinking Path
Linked Issues or Issue Description
BLO-20385 delegate recovery unresolved blockers; only this PR matched.Problem:
isCreatorOrManagerChainRecoveryPatchauthorizedblockedtotododelegate-recovery requests by body shape alone. Because the shape includesblockedByIssueIds: [], an authorized request could remove unresolved blocker edges that the actor otherwise had no permission to delete.Expected behavior:
If explicit blocker edges remain unresolved, delegate recovery should return a descriptive conflict and leave the issue and its blocker edges unchanged.
Steps to reproduce:
PATCH {"status":"todo","blockedByIssueIds":[]}through the delegate-recovery shape.blockedBy; after this fix, it returns409 delegate_recovery_unresolved_blockersand performs no write.What Changed
assertAgentIssueMutationAllowednow checkssvc.getDependencyReadinessbefore admitting the delegate-recovery unpark.409 delegate_recovery_unresolved_blockerswith offending issue ids.blockerAttention.unresolvedBlockerCount, because only explicit edges are at risk from this patch.Verification
issue-agent-mutation-ownership-routes.test.ts, covering creator and manager-chain grants.updateis never called, proving the edge survives.routes/issues.tstypecheck had 0 introduced errors, with the known pre-existing broader error set elsewhere.Risks
Model Used
Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template