Files
weichen 6a3a0dc201 fix(security): harden bypass authz, gate blind spot, command exec, validated_only (review P0/P1)
- 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
2026-09-26 02:00:14 +00:00

157 lines
4.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}
}
}