From f7cb002a1fa5779626719ba2dac553b2cdfcea60 Mon Sep 17 00:00:00 2001 From: nickyleach <331803+nickyleach@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:43:09 +0000 Subject: [PATCH] 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 --- .../modules/wake-queue/adapters/postgres.ts | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/server/src/modules/wake-queue/adapters/postgres.ts b/server/src/modules/wake-queue/adapters/postgres.ts index 81c3152fbd..fe2676fd83 100644 --- a/server/src/modules/wake-queue/adapters/postgres.ts +++ b/server/src/modules/wake-queue/adapters/postgres.ts @@ -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