fix(harness): atomic claim for auto-approval and rejected proposals stay rejected
보안 리뷰 반영. 자동 승인은 approved_at·executed_at·rejected_at 이 비어 있고 만료 전인 행만 조건부 UPDATE 로 선점한 경우에만 실행하므로, 사람의 승인·실행·거절이 먼저 오면 이중 실행이 없다. proposals 에 rejected_at 열을 추가해 거절 경로가 기록하고, approve/authorize/자동 승인이 거절된 제안을 거부한다.
This commit is contained in:
1 parent
ca933a646e
commit
85d99324a1
5 files changed
+34
-8
No files matched your search
@@ -94,6 +94,9 @@ func (a *App) handleProposalApprove(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case p.RejectedAt != nil:
|
||||
writeErr(w, 409, errors.New("proposal rejected"))
|
||||
return
|
||||
case p.ApprovedAt != nil:
|
||||
writeErr(w, 409, errors.New("proposal already approved"))
|
||||
return
|
||||
@@ -122,6 +125,7 @@ func (a *App) handleProposalReject(w http.ResponseWriter, r *http.Request) {
|
||||
writeErr(w, 404, errors.New("unknown proposal"))
|
||||
return
|
||||
}
|
||||
_ = a.store.RejectProposal(r.Context(), token) // blocks a later approval (button, API or auto-approval)
|
||||
a.store.Event(r.Context(), p.RunID, p.ScenarioID, "note", req.RejectedBy, map[string]any{"rejected": true, "action_id": p.ActionID, "reason": req.Reason, "token_suffix": token[len(token)-6:]})
|
||||
writeJSON(w, 200, map[string]any{"token": token, "rejected": true})
|
||||
}
|
||||
Reference in new issue
Block a user