Files
Agent-System/internal/events/replay.go
T
weichenandCursor 4c34e8a503 fix(server): close security headers, lease clamp, replay digest, double start
Add nosniff, frame denial, referrer policy, and a self-origin CSP. Clamp human and squad lease TTLs and require author edit rights before a human lease. Include DryRun in replay digests so a dry-run approval cannot authorize apply. Stop Server.Start from swallowing a second Runtime.Start.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:12:17 +00:00

95 lines
2.3 KiB
Go

package events
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
)
// ReplayPlan is the application-layer dry-run/apply contract. There is no raw SQL entrypoint.
type ReplayPlan struct {
PlanID string
Operator string
Approver string
Environment string
ProjectID int64
Consumer string
EventIDs []string
Reason string
ApprovalRef string
DryRun bool
}
func (p ReplayPlan) Digest() string {
body, _ := json.Marshal(struct {
PlanID string `json:"plan_id"`
Operator string `json:"operator"`
Approver string `json:"approver"`
Environment string `json:"environment"`
ProjectID int64 `json:"project_id"`
Consumer string `json:"consumer"`
EventIDs []string `json:"event_ids"`
Reason string `json:"reason"`
ApprovalRef string `json:"approval_ref"`
DryRun bool `json:"dry_run"`
}{p.PlanID, p.Operator, p.Approver, p.Environment, p.ProjectID, p.Consumer, p.EventIDs, p.Reason, p.ApprovalRef, p.DryRun})
sum := sha256.Sum256(body)
return hex.EncodeToString(sum[:])
}
func AuthorizeReplayPlan(p ReplayPlan) error {
if strings.TrimSpace(p.Operator) == "" || strings.TrimSpace(p.Reason) == "" || strings.TrimSpace(p.Consumer) == "" {
return ErrReplayScope
}
if strings.TrimSpace(p.Environment) == "" || p.ProjectID <= 0 {
return ErrReplayScope
}
if len(p.EventIDs) == 0 {
return ErrReplayScope
}
if p.DryRun {
return nil
}
if strings.TrimSpace(p.ApprovalRef) == "" {
return ErrReplayApply
}
if strings.EqualFold(p.Operator, p.Approver) || strings.TrimSpace(p.Approver) == "" {
return ErrReplayApply
}
return nil
}
type ReplayRequest struct {
Consumer string
EventID string
ProjectID int64
DryRun bool
Reason string
Operator string
}
func AuthorizeReplay(req ReplayRequest) error {
if !req.DryRun {
return ErrReplayScope
}
if strings.TrimSpace(req.Consumer) == "" || strings.TrimSpace(req.Operator) == "" || strings.TrimSpace(req.Reason) == "" {
return ErrReplayScope
}
return nil
}
func ApplyReplay(p ReplayPlan, dryRunDigest string) error {
if p.DryRun {
return AuthorizeReplayPlan(p)
}
if err := AuthorizeReplayPlan(p); err != nil {
return err
}
if dryRunDigest == "" || p.Digest() != dryRunDigest {
return fmt.Errorf("%w: plan digest mismatch", ErrReplayApply)
}
return nil
}