docs(server): fix the authorization-read claim in the recovery comment

The comment said no authorization read uses the responsibleUserId
column for a queued or a cancelled run. That claim is false. The
issue-thread interaction attribution check is an authorization read.
It looks up a run with no status filter, so it can observe a queued
or a cancelled row. It denies when the caller carries a responsible
user, because a null column value never equals one. It skips that
check when the caller carries no responsible user.

Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
nickyleach 2026-09-10 16:43:09 +00:00
parent ab3eaa7c68
commit f7cb002a1f
1 changed files with 17 additions and 13 deletions

View File

@ -461,19 +461,23 @@ function buildTransaction(tx: Db, deps: WakeQueuePostgresAdapterDeps): WakeQueue
// responsible user permanently. A claimed row still needs
// initializeRunIdentity to overwrite the value again, from the run
// identity chain; if execution ends before that overwrite runs, the
// claimed value stays. One reader can observe a null value: runsForIssue
// projects the column with no status filter, so the issue run ledger
// can show a recovery run with no responsible user. That projection
// displays attribution and makes no authorization decision. No
// authorization read uses this column for a queued or a cancelled run.
// Each one keys on a running or an authenticated run. The audit feed is
// the other reader that can observe a cancelled run: claimQueuedRun
// cancels a queued run when an active subtree pause hold holds the
// issue, and it writes an activity log event for that cancelled run.
// agentActionAuditService prefers the responsible user that the activity
// log row carries. resolveResponsibleUserIdForActivity sets that value,
// and it finds no responsible user on the cancelled run. It falls back
// to the issue, then to the agent API key, then to the company default.
// claimed value stays. Readers can observe a null value here.
// runsForIssue projects the column with no status filter, so the issue
// run ledger can show a recovery run with no responsible user. That
// projection displays attribution and makes no authorization decision.
// The issue-thread interaction attribution check is an authorization
// read that can also observe a null value. It looks up a
// caller-supplied run id with no status filter, and it compares this
// column against the responsible user of the caller. It makes that
// comparison only when the caller carries a responsible user, and a
// null value never equals one, so the check denies. The audit feed can
// observe a cancelled run: claimQueuedRun cancels a queued run when an
// active subtree pause hold holds the issue, and it writes an activity
// log event for that cancelled run. agentActionAuditService prefers the
// responsible user that the activity log row carries.
// resolveResponsibleUserIdForActivity sets that value, and it finds no
// responsible user on the cancelled run. It falls back to the issue,
// then to the agent API key, then to the company default.
// The immediate-recovery writer takes an already-resolved
// responsibleUserId as an input parameter, because its caller must
// resolve one before it can call that writer. This writer's input