Files
weichen c07d4020d0 feat(intentflow): I2 shadow tier, project allowlist, and rollout metrics
Persist validated_only shadow plans without executing, gate elevated tiers
behind INTENT_PLAN_PROJECT_ALLOWLIST, and keep legacy chat routing for shadow.
2026-09-23 15:10:26 +00:00

64 lines
1.4 KiB
Go

package intentflow
import (
"strconv"
"strings"
)
// AllowAllProjects is the wildcard sentinel for INTENT_PLAN_PROJECT_ALLOWLIST=*.
const AllowAllProjects int64 = -1
// ParseProjectAllowlist parses a comma-separated project ID list.
// Empty string → deny elevated tiers. "*" → allow all. Invalid tokens are skipped.
func ParseProjectAllowlist(raw string) []int64 {
raw = strings.TrimSpace(raw)
if raw == "" {
return nil
}
if raw == "*" {
return []int64{AllowAllProjects}
}
parts := strings.Split(raw, ",")
out := make([]int64, 0, len(parts))
seen := map[int64]struct{}{}
for _, p := range parts {
p = strings.TrimSpace(p)
if p == "" || p == "*" {
if p == "*" {
return []int64{AllowAllProjects}
}
continue
}
id, err := strconv.ParseInt(p, 10, 64)
if err != nil || id <= 0 {
continue
}
if _, ok := seen[id]; ok {
continue
}
seen[id] = struct{}{}
out = append(out, id)
}
return out
}
// ProjectAllowed reports whether elevated plan tiers may act for projectID.
// Legacy tier always returns true (no allowlist gate). Empty allowlist denies.
func (f FeatureFlags) ProjectAllowed(projectID int64) bool {
if f.PlanTier == TierLegacy || f.PlanTier == "" {
return true
}
if len(f.ProjectAllowlist) == 0 {
return false
}
for _, id := range f.ProjectAllowlist {
if id == AllowAllProjects {
return true
}
if id == projectID {
return true
}
}
return false
}