- FIND-SEC-01: GetUserContext requires session ownership (handler 403 + SQL/memory owner filter); in-memory HTTP + isolated-PG regressions - FIND-ARCH-01: archtest fails closed on untracked table writes (+noise exemption) and registers 50 existing writer tables in table_owners - FIND-SEC-02: Authorizer without pool denies by default; explicit NewInMemoryAuthorizer seam opt-in via ALLOW_IN_MEMORY at composition - FIND-SEC-03: swboot commands run argv-exec (no sh -c) with exact basename allowlist match; prefix-spoof and no-shell-eval tests - FIND-FLOW-01: confirm rejects validated_only plans; ExecuteClaimed hard-refuses validated_only steps (new error codes + HTTP mapping) - FIND-QUAL-01: intentflow.ValidateFlagConsistency fail-fast at Assemble
157 lines
4.8 KiB
Go
157 lines
4.8 KiB
Go
package intentflow
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"chat-agent-system/internal/intent"
|
||
)
|
||
|
||
func TestDefaultPlanTierIsLegacy(t *testing.T) {
|
||
t.Setenv("MULTI_INTENT_PLAN_TIER", "")
|
||
ResetFeatureFlagsForTest()
|
||
if got := CurrentFeatureFlags().PlanTier; got != TierLegacy {
|
||
t.Fatalf("default tier = %s, want legacy", got)
|
||
}
|
||
}
|
||
|
||
func TestUnknownPlanTierFailsClosedToLegacy(t *testing.T) {
|
||
if parsePlanTier("definitely-not-a-tier") != TierLegacy {
|
||
t.Fatal("unknown MULTI_INTENT_PLAN_TIER must fail closed to legacy")
|
||
}
|
||
}
|
||
|
||
func TestPlanTierIndependentOfLegacyMultiIntentFlag(t *testing.T) {
|
||
t.Setenv("MULTI_INTENT_ENABLED", "true")
|
||
t.Setenv("MULTI_INTENT_PLAN_TIER", "")
|
||
ResetFeatureFlagsForTest()
|
||
if CurrentFeatureFlags().PlanTier != TierLegacy {
|
||
t.Fatal("MULTI_INTENT_ENABLED must not promote plan tier")
|
||
}
|
||
}
|
||
|
||
func TestPlanTierIndependentOfExpansionFlags(t *testing.T) {
|
||
t.Setenv("MULTI_INTENT_PLAN_TIER", "")
|
||
t.Setenv("MULTI_INTENT_U9_SEGMENT", "true")
|
||
t.Setenv("MULTI_INTENT_U10_MUTATE", "true")
|
||
t.Setenv("MULTI_INTENT_U11_DOCGOV", "true")
|
||
t.Setenv("MULTI_INTENT_U12_RUN_CONTROL", "true")
|
||
ResetFeatureFlagsForTest()
|
||
if CurrentFeatureFlags().PlanTier != TierLegacy {
|
||
t.Fatal("U9–U12 flags must not raise MULTI_INTENT_PLAN_TIER")
|
||
}
|
||
}
|
||
|
||
func TestPlanTierEnv(t *testing.T) {
|
||
if parsePlanTier("shadow") != TierShadow {
|
||
t.Fatal("shadow")
|
||
}
|
||
if parsePlanTier("auto_read") != TierAutoRead {
|
||
t.Fatal("auto_read")
|
||
}
|
||
if parsePlanTier("confirm") != TierConfirm {
|
||
t.Fatal("confirm")
|
||
}
|
||
if parsePlanTier("full") != TierFull {
|
||
t.Fatal("full")
|
||
}
|
||
if !TierConfirm.Allows(TierAutoRead) || TierShadow.Allows(TierConfirm) {
|
||
t.Fatal("tier rank")
|
||
}
|
||
}
|
||
|
||
func TestProjectAllowlistParseAndGate(t *testing.T) {
|
||
if got := ParseProjectAllowlist(""); len(got) != 0 {
|
||
t.Fatalf("empty = %+v", got)
|
||
}
|
||
if got := ParseProjectAllowlist("*"); len(got) != 1 || got[0] != AllowAllProjects {
|
||
t.Fatalf("star = %+v", got)
|
||
}
|
||
got := ParseProjectAllowlist("42, 100,42,bad")
|
||
if len(got) != 2 || got[0] != 42 || got[1] != 100 {
|
||
t.Fatalf("list = %+v", got)
|
||
}
|
||
legacy := FeatureFlags{PlanTier: TierLegacy}
|
||
if !legacy.ProjectAllowed(99) {
|
||
t.Fatal("legacy must not require allowlist")
|
||
}
|
||
denied := FeatureFlags{PlanTier: TierShadow}
|
||
if denied.ProjectAllowed(42) {
|
||
t.Fatal("empty allowlist must deny elevated")
|
||
}
|
||
ok := FeatureFlags{PlanTier: TierAutoRead, ProjectAllowlist: []int64{42}}
|
||
if !ok.ProjectAllowed(42) || ok.ProjectAllowed(7) {
|
||
t.Fatal("id allowlist")
|
||
}
|
||
all := FeatureFlags{PlanTier: TierConfirm, ProjectAllowlist: []int64{AllowAllProjects}}
|
||
if !all.ProjectAllowed(1) {
|
||
t.Fatal("wildcard")
|
||
}
|
||
}
|
||
|
||
func TestDefaultAllowlistEmpty(t *testing.T) {
|
||
t.Setenv("MULTI_INTENT_PLAN_TIER", "shadow")
|
||
t.Setenv("INTENT_PLAN_PROJECT_ALLOWLIST", "")
|
||
ResetFeatureFlagsForTest()
|
||
f := CurrentFeatureFlags()
|
||
if f.PlanTier != TierShadow {
|
||
t.Fatal(f.PlanTier)
|
||
}
|
||
if len(f.ProjectAllowlist) != 0 {
|
||
t.Fatalf("default allowlist must be empty deny, got %+v", f.ProjectAllowlist)
|
||
}
|
||
}
|
||
|
||
func TestErrorCodes(t *testing.T) {
|
||
if ErrorCode(ErrPlanNotFoundOrHidden) != "PLAN_NOT_FOUND_OR_HIDDEN" {
|
||
t.Fatal(ErrorCode(ErrPlanNotFoundOrHidden))
|
||
}
|
||
if ErrorCode(ErrPlanStaleRevision) != "PLAN_STALE_REVISION" {
|
||
t.Fatal("stale")
|
||
}
|
||
if ErrorCode(ErrPlanExpired) != "PLAN_EXPIRED" {
|
||
t.Fatal("expired")
|
||
}
|
||
if ErrorCode(ErrPlanDecisionConflict) != "PLAN_DECISION_CONFLICT" {
|
||
t.Fatal("conflict")
|
||
}
|
||
if ErrorCode(ErrPlanDependencyInvalid) != "PLAN_DEPENDENCY_INVALID" {
|
||
t.Fatal("dep")
|
||
}
|
||
if ErrorCode(ErrPlanActionForbidden) != "PLAN_ACTION_FORBIDDEN" {
|
||
t.Fatal("forbidden")
|
||
}
|
||
if ErrorCode(ErrPlanActionVersionConflict) != "PLAN_ACTION_VERSION_CONFLICT" {
|
||
t.Fatal("version")
|
||
}
|
||
}
|
||
|
||
func TestRESTPathsFrozen(t *testing.T) {
|
||
if PathActivePlan != "/api/v1/intent-plans/active" {
|
||
t.Fatal(PathActivePlan)
|
||
}
|
||
if PathPlanByID != "/api/v1/intent-plans/{plan_id}" {
|
||
t.Fatal(PathPlanByID)
|
||
}
|
||
if PathPlanDecisions != "/api/v1/intent-plans/{plan_id}/decisions" {
|
||
t.Fatal(PathPlanDecisions)
|
||
}
|
||
}
|
||
|
||
// TestValidateFlagConsistency FIND-QUAL-01 回归:PlanTier 升档但多意图识别
|
||
// 关闭时组合根必须 fail-fast,不允许静默漂移配置。
|
||
func TestValidateFlagConsistency(t *testing.T) {
|
||
base := intent.FeatureFlags{MultiIntentEnabled: true}
|
||
if err := ValidateFlagConsistency(base, FeatureFlags{PlanTier: TierFull}); err != nil {
|
||
t.Fatalf("elevated tier with multi-intent on should pass: %v", err)
|
||
}
|
||
if err := ValidateFlagConsistency(base, FeatureFlags{PlanTier: TierLegacy}); err != nil {
|
||
t.Fatalf("legacy tier should always pass: %v", err)
|
||
}
|
||
drifted := intent.FeatureFlags{MultiIntentEnabled: false}
|
||
for _, tier := range []PlanTier{TierShadow, TierAutoRead, TierConfirm, TierFull} {
|
||
if err := ValidateFlagConsistency(drifted, FeatureFlags{PlanTier: tier}); err == nil {
|
||
t.Fatalf("tier %s with multi-intent off must fail fast", tier)
|
||
}
|
||
}
|
||
}
|