Verify resolve/normalize/hash stability, policy gating, stale token rejection, and HTTP error mapping for the new duty policy path. Co-authored-by: Cursor <cursoragent@cursor.com>
46 lines
1.1 KiB
Go
46 lines
1.1 KiB
Go
package projectinstance
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/workflowdef"
|
|
)
|
|
|
|
func TestComputePlanHash_LegacySnapshotStableWithoutDutyPolicy(t *testing.T) {
|
|
t.Parallel()
|
|
plan := WorkflowPlan{
|
|
WorkflowDefinitionKey: workflowdef.OfficialKeyMain,
|
|
WorkflowVersion: 1,
|
|
Stages: []StagePlan{{
|
|
StageKey: "s1", Enabled: true,
|
|
DocTasks: []DocTaskPlan{{
|
|
TaskKey: "intake", Enabled: true,
|
|
Duties: DocDuty{AuthorUserID: 1, ReviewerUserID: 2, ApproverUserID: 3},
|
|
}},
|
|
}},
|
|
}
|
|
h1, err := computePlanHash(plan)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// empty DutyPolicy must not appear in JSON (omitempty) — hash must match explicit separated unset
|
|
plan2 := plan
|
|
plan2.Stages[0].DocTasks[0].DutyPolicy = ""
|
|
h2, err := computePlanHash(plan2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h1 != h2 {
|
|
t.Fatalf("empty duty_policy must be hash-stable: %s vs %s", h1, h2)
|
|
}
|
|
plan3 := plan
|
|
plan3.Stages[0].DocTasks[0].DutyPolicy = DutyPolicyAuthorOnly
|
|
h3, err := computePlanHash(plan3)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h3 == h1 {
|
|
t.Fatal("author_only duty_policy must change plan hash")
|
|
}
|
|
}
|