⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
src/queue/processors.ts:14636-14673's authorizeFeedbackActor calls isAuthorizedCommandActor
without passing commandName, commandAuthorizationPolicy, commandRateLimitPolicy, or
pullRequestOpenAndNotDraft. isAuthorizedCommandActor defaults commandName to "preflight"
(src/github/commands.ts:394), whose default allowed roles are ["maintainer", "collaborator", "confirmed_miner"] (packages/loopover-engine/src/settings/command-authorization.ts:24) — a
materially different policy from chat's (["maintainer", "collaborator", "pr_author"], gated by
commandRateLimitPolicy === "hold", same file lines 144-150).
Consequence: a PR author who was legitimately authorized to receive a chat answer (via the
pr_author + commandRateLimitPolicy: "hold" path, which never requires confirmed-miner status)
gets their own feedback vote (+1/-1 reaction) on that same answer wrongly denied with
pr_author_not_confirmed_miner, unless they also happen to be a confirmed miner. This also silently
ignores any repo's custom commandAuthorization override entirely for feedback voting, since the
policy objects are never threaded through.
Requirements
authorizeFeedbackActor must pass the real command context (commandName: "chat" or whichever
command the feedback target belongs to, plus commandAuthorizationPolicy,
commandRateLimitPolicy, and pullRequestOpenAndNotDraft) to isAuthorizedCommandActor, matching
how every other command-authorization call site in this file threads that context through.
- Do not change
isAuthorizedCommandActor's own logic — only the caller's missing arguments.
Deliverables
All three Deliverables are required in the same PR.
Test Coverage Requirements
src/** is measured by codecov/patch (99%+ target, branch-counted). Both new tests must exercise
the previously-broken authorization path directly.
Expected Outcome
Feedback voting on a command's answer is authorized against that command's own real policy, not the
unrelated "preflight" default, and respects per-repo commandAuthorization overrides.
Links & Resources
src/queue/processors.ts:14636-14673 (authorizeFeedbackActor)
src/github/commands.ts:394 (isAuthorizedCommandActor's "preflight" default)
packages/loopover-engine/src/settings/command-authorization.ts:24,144-150 (the differing
policies for preflight vs chat)
Context
src/queue/processors.ts:14636-14673'sauthorizeFeedbackActorcallsisAuthorizedCommandActorwithout passing
commandName,commandAuthorizationPolicy,commandRateLimitPolicy, orpullRequestOpenAndNotDraft.isAuthorizedCommandActordefaultscommandNameto"preflight"(
src/github/commands.ts:394), whose default allowed roles are["maintainer", "collaborator", "confirmed_miner"](packages/loopover-engine/src/settings/command-authorization.ts:24) — amaterially different policy from
chat's (["maintainer", "collaborator", "pr_author"], gated bycommandRateLimitPolicy === "hold", same file lines 144-150).Consequence: a PR author who was legitimately authorized to receive a
chatanswer (via thepr_author+commandRateLimitPolicy: "hold"path, which never requires confirmed-miner status)gets their own feedback vote (+1/-1 reaction) on that same answer wrongly denied with
pr_author_not_confirmed_miner, unless they also happen to be a confirmed miner. This also silentlyignores any repo's custom
commandAuthorizationoverride entirely for feedback voting, since thepolicy objects are never threaded through.
Requirements
authorizeFeedbackActormust pass the real command context (commandName: "chat"or whichevercommand the feedback target belongs to, plus
commandAuthorizationPolicy,commandRateLimitPolicy, andpullRequestOpenAndNotDraft) toisAuthorizedCommandActor, matchinghow every other command-authorization call site in this file threads that context through.
isAuthorizedCommandActor's own logic — only the caller's missing arguments.Deliverables
authorizeFeedbackActorpasses the correct command context toisAuthorizedCommandActorinstead of relying on the
"preflight"default.chatanswerin a repo with
commandRateLimitPolicy: "hold"; assert the vote is now recorded(
authorized: true) — currently denied.commandAuthorizationoverride for the relevantcommand is now honored for feedback voting (previously silently ignored).
All three Deliverables are required in the same PR.
Test Coverage Requirements
src/**is measured bycodecov/patch(99%+ target, branch-counted). Both new tests must exercisethe previously-broken authorization path directly.
Expected Outcome
Feedback voting on a command's answer is authorized against that command's own real policy, not the
unrelated
"preflight"default, and respects per-repocommandAuthorizationoverrides.Links & Resources
src/queue/processors.ts:14636-14673(authorizeFeedbackActor)src/github/commands.ts:394(isAuthorizedCommandActor's"preflight"default)packages/loopover-engine/src/settings/command-authorization.ts:24,144-150(the differingpolicies for
preflightvschat)