package unifiedresources // Unified Resources Architecture — Code Standards Enforcement // // END STATE (State Read Consolidation — SRC): // // The Unified Resources Registry is the PRIMARY read surface for all // internal business logic. StateSnapshot is the write/ingest buffer and // frontend wire DTO only. // // Architecture: // // 1. StateSnapshot (models.StateSnapshot) // WRITE-ONLY ingest buffer. Monitoring/polling populates typed arrays. // The registry reads from it via IngestSnapshot(). Frontend reads via // ToFrontend()/WebSocket. Internal business logic MUST NOT read from // StateSnapshot directly — use the ReadState interface instead. // // 2. Unified Resources Registry (unifiedresources.ResourceRegistry) // The canonical read model. Provides cross-source identity resolution, // deduplication, typed views, and a normalized resource model. // Implements the ReadState interface with typed accessor methods // (VMs(), Containers(), Nodes(), etc.) backed by cached per-type // indexes that are O(1) to read and invalidated per ingest cycle. // // Consumer package policy: // // - internal/ai/*, internal/api/*, internal/infradiscovery/, // internal/servicediscovery/: MUST use ReadState. Direct state reads // are banned for all migrated resource types. // // - internal/monitoring/, internal/mock/, internal/models/, // internal/websocket/: Exempt (producer/wire-format packages). // Monitoring remains a producer package, but snapshot-shaped export // helpers are progressively derived from ReadState-backed canonical data // rather than treated as state-owned truth. Workload export helpers // (VMsSnapshot/ContainersSnapshot) now also derive from ReadState-backed // canonical data instead of from StateSnapshot-owned guest arrays. PBS // instance export helpers now follow the same rule via // ReadState.PBSInstances(). Backup-alert guest lookup assembly now also // derives VM/container identity from ReadState workload views instead of // from snapshot-owned guest arrays. Backup polling and recovery ingest // guest-context assembly now also derive workload node/name/type data from // ReadState instead of from snapshot-owned guest arrays. Storage-backup // preservation now also derives node/storage membership from // ReadState.StoragePools() instead of from snapshot-owned storage arrays. // Physical-disk refresh/merge paths now also derive disk, node, and linked // host context from ReadState instead of from snapshot-owned physical-disk // arrays. // // - All state.* field access patterns and GetState() calls are // enforced as hard bans (SRC-04b). Migration is complete — zero // direct state access remains in consumer packages. // // See: docs/architecture/state-read-consolidation-plan-2026-02.md // Progress: docs/architecture/state-read-consolidation-progress-2026-02.md // // The tests below enforce these rules by scanning consumer packages for // banned direct-state access patterns. import ( "os" "path/filepath" "reflect" "regexp" "strings" "testing" ) // readConsumerGoFiles returns the contents of all non-test .go files in the // specified directory (relative to the repo internal/ root). func readConsumerGoFiles(t *testing.T, relDir string) map[string]string { t.Helper() // Walk up from unifiedresources/ to internal/ internalDir := filepath.Join("..", relDir) files := make(map[string]string) err := filepath.Walk(internalDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } if filepath.Ext(path) != ".go" || strings.HasSuffix(path, "_test.go") { return nil } data, readErr := os.ReadFile(path) if readErr != nil { t.Fatalf("failed to read %s: %v", path, readErr) } files[path] = string(data) return nil }) if err != nil { t.Fatalf("failed to walk %s: %v", relDir, err) } return files } // bannedPattern defines a state access pattern that should not appear in // consumer code because the resource type has been migrated to the registry. type bannedPattern struct { re *regexp.Regexp message string } var migratedResourcePatterns = []bannedPattern{ { re: regexp.MustCompile(`state\.PhysicalDisks\b`), message: "use unified resources registry (GetByType/ListByType with ResourceTypePhysicalDisk) instead of state.PhysicalDisks", }, { re: regexp.MustCompile(`state\.CephClusters\b`), message: "use unified resources registry (GetByType/ListByType with ResourceTypeCeph) instead of state.CephClusters", }, { re: regexp.MustCompile(`GetCephClusters\(\)`), message: "GetCephClusters() was removed — use unified resources registry instead", }, { re: regexp.MustCompile(`StorageProvider\b`), message: "StorageProvider was removed — storage pools are accessed via unified resources registry", }, // SRC-04b hard bans: state.* field access patterns and GetState() calls. // Converted from ratchet ceilings (all reached 0) to hard bans on 2026-03-01. // Consumer packages must use ReadState typed accessors exclusively. { re: regexp.MustCompile(`state\.VMs\b`), message: "use ReadState.VMs() instead of state.VMs — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.Containers\b`), message: "use ReadState.Containers() instead of state.Containers — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.Nodes\b`), message: "use ReadState.Nodes() instead of state.Nodes — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.DockerHosts\b`), message: "use ReadState.DockerHosts() instead of state.DockerHosts — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.Hosts\b`), message: "use ReadState.Hosts() instead of state.Hosts — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.Storage\b`), message: "use ReadState.StoragePools() instead of state.Storage — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.KubernetesClusters\b`), message: "use ReadState.K8sClusters() instead of state.KubernetesClusters — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.PBSInstances\b`), message: "use ReadState.PBSInstances() instead of state.PBSInstances — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`state\.PMGInstances\b`), message: "use ReadState.PMGInstances() instead of state.PMGInstances — direct state access banned (SRC-04b)", }, { re: regexp.MustCompile(`\.GetState\(\)`), message: "use ReadState interface instead of GetState() — direct state access banned (SRC-04b)", }, } // consumerPackage defines a package directory to scan and any files that are // exempt from the banned patterns (e.g., adapters that bridge between layers). type consumerPackage struct { dir string exemptFiles map[string]bool } var consumerPackages = []consumerPackage{ {dir: "ai/tools", exemptFiles: nil}, {dir: "ai/chat", exemptFiles: nil}, {dir: "ai", exemptFiles: nil}, {dir: "api", exemptFiles: nil}, {dir: "servicediscovery", exemptFiles: nil}, } // TestNoDirectStateAccessForMigratedResources ensures that consumer packages // do not directly access state.* fields, call GetState(), or use removed // provider interfaces. All resource types have been migrated to the unified // resources registry and ReadState interface (SRC-04b). func TestNoDirectStateAccessForMigratedResources(t *testing.T) { // Collect all consumer file contents, deduplicating across overlapping // package entries (e.g., "ai" walks into "ai/tools" and "ai/chat"). // Track exempt files so per-package exemptions are preserved. allFiles := make(map[string]string) exemptFiles := make(map[string]bool) for _, pkg := range consumerPackages { for path, content := range readConsumerGoFiles(t, pkg.dir) { allFiles[path] = content if pkg.exemptFiles[filepath.Base(path)] { exemptFiles[path] = true } } } for path, content := range allFiles { if exemptFiles[path] { continue } for _, bp := range migratedResourcePatterns { if matches := bp.re.FindAllStringIndex(content, -1); len(matches) > 0 { for _, m := range matches { line := 1 + strings.Count(content[:m[0]], "\n") t.Errorf("%s:%d: %s", path, line, bp.message) } } } } } func TestDockerSwarmEvidenceGuardStaysInAdapter(t *testing.T) { data, err := os.ReadFile("adapters.go") if err != nil { t.Fatalf("failed to read adapters.go: %v", err) } source := string(data) requiredSnippets := []string{ "func hasReportableDockerSwarmInfo(info *models.DockerSwarmInfo) bool", `state == "inactive"`, "func convertSwarm(info *models.DockerSwarmInfo) *DockerSwarmInfo", "if !hasReportableDockerSwarmInfo(info) {", "return nil", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("adapters.go must contain %q", snippet) } } } func TestAPIResourcesKeepsOwnedSupplementalGapFillAndVMwareAlias(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "api", "resources.go")) if err != nil { t.Fatalf("failed to read ../api/resources.go: %v", err) } source := string(data) requiredSnippets := []string{ "seedSources := unifiedSeedSources(seed.resources)", "!sourceOwnedBySupplementalProvider(source, ownedSources) || unifiedSeedIncludesSource(seedSources, source)", `case "vmware", "vmware-vsphere":`, } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("../api/resources.go must contain %q", snippet) } } } func TestResourceAPIUsesCanonicalTenantUnifiedSeed(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "api", "resources.go")) if err != nil { t.Fatalf("failed to read resources.go: %v", err) } source := string(data) if strings.Contains(source, "GetStateForTenant(") { t.Fatalf("internal/api/resources.go must not fall back to tenant StateSnapshot seeding") } if !strings.Contains(source, "UnifiedResourceSnapshotForTenant(orgID)") { t.Fatalf("internal/api/resources.go must use tenant unified resource snapshots as the canonical seed") } } func TestCanonicalStorageMetadataPreservesBackingPoolField(t *testing.T) { requiredSnippets := map[string][]string{ "types.go": { "Pool string `json:\"pool,omitempty\"`", }, "adapters.go": { "Pool: storage.Pool,", }, "views.go": { "func (v StoragePoolView) Pool() string {", "return v.r.Storage.Pool", }, filepath.Join("..", "..", "frontend-modern", "src", "types", "resource.ts"): { "pool?: string;", }, filepath.Join("..", "..", "frontend-modern", "src", "hooks", "useUnifiedResources.ts"): { "pool?: string;", }, } for path, snippets := range requiredSnippets { data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } source := string(data) for _, snippet := range snippets { if !strings.Contains(source, snippet) { t.Fatalf("%s must contain %q", path, snippet) } } } } func TestCephPoolsProjectThroughCanonicalStoragePath(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join("..", "models", "models.go"): { "func CephPoolStorageID(instanceName, poolName string) string", "func StorageFromCephPool(cluster CephCluster, pool CephPool) Storage", `Type: "ceph",`, "ID: CephPoolStorageID(cluster.Instance, name),", }, "registry.go": { "models.CephPoolStorage(cluster)", "rr.ingestStorage(storage)", }, filepath.Join("..", "monitoring", "ceph.go"): { "m.checkCephPoolStorage(cluster)", "models.CephPoolStorage(cluster)", `m.metricsStore.Write("storage", storage.ID, "usage", storage.Usage, timestamp)`, "m.alertManager.CheckStorage(storage)", }, } for path, snippets := range requiredSnippets { data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } source := string(data) for _, snippet := range snippets { if !strings.Contains(source, snippet) { t.Fatalf("%s must keep Ceph pool storage on canonical storage identity via %q", path, snippet) } } } } func TestResourceAPIExposesDedicatedFacetReads(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "api", "resources.go")) if err != nil { t.Fatalf("failed to read resources.go: %v", err) } source := string(data) requiredSnippets := []string{ "HandleGetResourceFacets", "HandleGetResourceTimeline", "unified.ParseResourceChangeFilters(r.URL.Query()[\"kind\"], r.URL.Query()[\"sourceType\"], r.URL.Query()[\"sourceAdapter\"])", "filters.IncludeRelated = true", "GetRecentChangesFiltered(resourceID, since, limit, filters)", "CountRecentChangesFiltered(resourceID, since, filters)", "CountRecentChangesByKindFiltered(resourceID, since, filters)", "CountRecentChangesBySourceTypeFiltered(resourceID, since, filters)", "sourceAdapter", "strings.HasSuffix(r.URL.Path, \"/facets\")", "strings.HasSuffix(r.URL.Path, \"/timeline\")", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/api/resources.go must expose canonical facet read snippet %q", snippet) } } } func TestActionExecutionContractStaysAPIOwned(t *testing.T) { requiredSnippets := map[string][]string{ // Single map entry per file: Go map literals silently drop // duplicate keys, so two entries for the same file would // erase the first. Keeping all actions.go pins together // guarantees every snippet actually runs. filepath.Join(".", "actions.go"): { "func BeginActionExecution(record ActionAuditRecord, actor string, now time.Time)", "func CompleteActionExecution(record ActionAuditRecord, result *ExecutionResult, actor string, now time.Time)", "func ValidateActionExecutionStart(record ActionAuditRecord, now time.Time) error", // ErrActionPlanDrift is the canonical error returned when the // payload at execute time does not match the PlanHash recorded // at approval time. Pinning it here keeps the broker contract // honest: drift refusal cannot silently turn into another error // kind that callers fail to detect. "ErrActionPlanDrift = errors.New(", // ErrResourceRemediationLocked is the canonical error returned // when the operator has set NeverAutoRemediate=true on the // target resource. Pin it here so the broker contract stays // honest: per-resource lock refusal cannot silently turn into // another error kind that callers fail to detect. "ErrResourceRemediationLocked = errors.New(", // ActionVerificationResult is the canonical post-execution // read-after-write outcome carrier. The broker writes it onto // ExecutionResult.Verification; pinning the type here keeps the // shape stable across refactors so frontend audit surfaces and // any other consumers can rely on it. "type ActionVerificationResult struct", "Verification *ActionVerificationResult `json:\"verification,omitempty\"`", }, filepath.Join(".", "store.go"): { "RecordActionExecutionStart(record ActionAuditRecord, event ActionLifecycleEvent) error", "RecordActionExecutionResult(record ActionAuditRecord, event ActionLifecycleEvent) error", "func (s *SQLiteResourceStore) RecordActionExecutionStart(record ActionAuditRecord, event ActionLifecycleEvent) error", "func (s *SQLiteResourceStore) RecordActionExecutionResult(record ActionAuditRecord, event ActionLifecycleEvent) error", // Audit-log secret redaction must run at every persistence // boundary so operator-authored reasons and command output do // not leak credentials into the plaintext SQL audit history. // Pin the call sites in store.go to keep redaction wired even // across future refactors. "record = RedactAuditRecord(normalized)", "normalizedRecord = RedactAuditRecord(normalizedRecord)", // SQLite audit reads must also pass through the shared // redaction boundary so legacy rows cannot expose verification // command/output/note details after read-time normalization. "func redactActionAuditRecordFromStore(record ActionAuditRecord) ActionAuditRecord", "return redactActionAuditRecordFromStore(record), nil", "func (s *SQLiteResourceStore) migrateActionAuditRedaction() error", }, filepath.Join(".", "audit_redaction.go"): { "func RedactAuditText(s string) string", "func RedactAuditRecord(record ActionAuditRecord) ActionAuditRecord", "func redactActionExecutionResult(result *ExecutionResult) *ExecutionResult", }, filepath.Join("..", "api", "actions.go"): { "type ActionExecutor interface", "func (h *ResourceHandlers) HandleExecuteAction(w http.ResponseWriter, r *http.Request)", "func (h *ResourceHandlers) validateActionPlanFresh(orgID string, record unified.ActionAuditRecord) error", "func recordRefusedActionExecution(store unified.ResourceStore, record unified.ActionAuditRecord", "func (h *ResourceHandlers) publishActionCompleted(record unified.ActionAuditRecord)", "store.RecordActionExecutionStart(started, startEvent)", "store.RecordActionExecutionResult(completed, doneEvent)", "action_plan_drift", "action_executor_unavailable", }, filepath.Join("..", "api", "resources.go"): { "actionExecutor ActionExecutor", "actionCompleted func(unified.ActionAuditRecord)", "func (h *ResourceHandlers) SetActionExecutor(executor ActionExecutor)", "func (h *ResourceHandlers) SetActionCompletedPublisher(", }, filepath.Join("..", "api", "agent_events.go"): { "func (b *AgentEventBroadcaster) PublishActionCompletedRecord(record unifiedresources.ActionAuditRecord)", "payload := AgentEventActionCompletedPayload{", "b.PublishActionCompleted(payload)", }, filepath.Join("..", "api", "router.go"): { "r.resourceHandlers.SetActionCompletedPublisher(r.agentEventBroadcaster.PublishActionCompletedRecord)", }, filepath.Join("..", "api", "router_routes_monitoring.go"): { `"POST /api/actions/{id}/execute"`, "RequireScope(config.ScopeAIExecute, r.resourceHandlers.HandleExecuteAction)", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } source := string(data) for _, snippet := range snippets { if !strings.Contains(source, snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestResourcePolicySummaryContractOmitsRawSignals(t *testing.T) { policy := ResourcePolicy{ Sensitivity: ResourceSensitivityRestricted, Routing: ResourceRoutingPolicy{ Scope: ResourceRoutingScopeLocalOnly, Redact: []ResourceRedactionHint{ ResourceRedactionHostname, }, }, } summary := strings.Join(ResourcePolicySummaryLines(&policy), "\n") if strings.Contains(summary, "Raw Signals") || strings.Contains(summary, "allowCloudRawSignals") || strings.Contains(summary, "cloud_summary=") { t.Fatalf("resource policy summary leaked raw-signals wording: %q", summary) } } func TestResourceChangeFilterParsingIsOwnedByUnifiedResources(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join(".", "change_filters.go"): { "func ParseResourceChangeFilters(kinds, sourceTypes, sourceAdapters []string) (ResourceChangeFilters, error)", "func parseResourceChangeKinds(values []string) ([]ChangeKind, error)", "func parseResourceChangeSourceTypes(values []string) ([]ChangeSourceType, error)", "func parseResourceChangeSourceAdapters(values []string) ([]ChangeSourceAdapter, error)", }, filepath.Join("..", "api", "resources.go"): { "unified.ParseResourceChangeFilters(r.URL.Query()[\"kind\"], r.URL.Query()[\"sourceType\"], r.URL.Query()[\"sourceAdapter\"])", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestPlatformActivityTimelineContractStaysCanonical(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join(".", "changes.go"): { `ChangeActivity ChangeKind = "activity"`, `AdapterVMware ChangeSourceAdapter = "vmware_adapter"`, }, filepath.Join(".", "activity_changes.go"): { "type PlatformActivityChange struct {", "func BuildPlatformActivityChange(resourceID string, activity PlatformActivityChange) *ResourceChange {", "Kind: ChangeActivity,", "SourceType: SourcePlatformEvent,", "func platformActivityChangeID(resourceID string, sourceAdapter ChangeSourceAdapter, activityType, nativeID string, occurredAt time.Time, title, message string) string {", }, filepath.Join(".", "change_filters.go"): { "case string(ChangeActivity):", "case string(AdapterVMware):", }, filepath.Join(".", "change_presentation.go"): { "case ChangeActivity:", }, filepath.Join(".", "store.go"): { "ON CONFLICT(id) DO NOTHING", "if existing.ID == change.ID && change.ID != \"\" {", }, filepath.Join("..", "monitoring", "monitor.go"): { "type MonitorSupplementalChangesProvider interface {", "recordSupplementalResourceChanges(store, supplementalChanges)", "func recordSupplementalResourceChanges(store ResourceStoreInterface, changes []unifiedresources.ResourceChange) {", }, filepath.Join("..", "monitoring", "vmware_poller.go"): { "cachedChangesByOrg map[string]map[string][]unifiedresources.ResourceChange", "p.cachedChangesByOrg[entry.orgID][entry.connectionID] = changes", "func (p *VMwarePoller) SupplementalChanges(_ *Monitor, orgID string) []unifiedresources.ResourceChange {", }, filepath.Join("..", "vmware", "activity_changes.go"): { "func (p *Provider) ActivityChanges() []unifiedresources.ResourceChange {", `ActivityType: "vmware_task",`, `ActivityType: "vmware_event",`, }, filepath.Join("..", "..", "frontend-modern", "src", "types", "resource.ts"): { "| 'activity'", "| 'vmware_adapter'", }, filepath.Join("..", "..", "frontend-modern", "src", "utils", "resourceChangePresentation.ts"): { "activity: {", "vmware_adapter: {", "case 'activity':", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestResourcePolicyPresentationUsesCanonicalLabels(t *testing.T) { data, err := os.ReadFile(filepath.Join(".", "policy_presentation.go")) if err != nil { t.Fatalf("failed to read policy_presentation.go: %v", err) } source := string(data) requiredSnippets := []string{ "ResourceSensitivityOrder", "ResourceRoutingScopeOrder", "ResourceRedactionHintOrder", "ResourceSensitivityLabel(", "ResourceRoutingScopeLabel(", "ResourceRedactionHintLabel(", "ResourcePolicyRedactionLabels(", "ResourcePolicyRedactionLabelsFromCounts(", "ResourcePolicySensitivitySummaryFromCounts(", "ResourcePolicyRoutingSummaryFromCounts(", "ResourcePolicySummaryLines(", "ResourcePolicyRedacts(", "ResourcePolicyUsesAISafeSummary(", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("policy_presentation.go must contain %q", snippet) } } } func TestResourcePolicyCloneHelperUsedByAIConsumers(t *testing.T) { requiredFiles := []string{ filepath.Join("..", "ai", "chat", "context_prefetch.go"), filepath.Join("..", "ai", "tools", "tools_query.go"), filepath.Join(".", "policy_metadata.go"), } requiredSnippets := map[string]string{ filepath.Join("..", "ai", "chat", "context_prefetch.go"): "unifiedresources.CanonicalGovernanceMetadata(resource)", filepath.Join("..", "ai", "tools", "tools_query.go"): "unifiedresources.CanonicalGovernanceMetadata(resource)", filepath.Join(".", "policy_metadata.go"): "func CanonicalGovernanceMetadata(resource *Resource) (*ResourcePolicy, string)", } for _, name := range requiredFiles { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } snippet := requiredSnippets[name] if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } func TestAISafeSummarySuffixHelperIsOwnedByUnifiedResources(t *testing.T) { data, err := os.ReadFile(filepath.Join(".", "policy_metadata.go")) if err != nil { t.Fatalf("failed to read policy_metadata.go: %v", err) } source := string(data) requiredSnippets := []string{ "func resourceAISafeSummaryPolicySuffix(sensitivity ResourceSensitivity) string", "return \"redacted for cloud summary\"", "return \"local-only context\"", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("policy_metadata.go must contain %q", snippet) } } } func TestCanonicalMetadataRefreshHelperUsedByConsumers(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join(".", "policy_metadata.go"): { "func RefreshCanonicalMetadata(resource *Resource)", "func RefreshCanonicalMetadataSlice(resources []Resource) []Resource", }, filepath.Join(".", "clone.go"): { "RefreshCanonicalMetadata(&out)", }, filepath.Join("..", "api", "resources.go"): { "unified.RefreshCanonicalMetadata(&resourceCopy)", "unified.RefreshCanonicalMetadataSlice(paged)", "unified.RefreshCanonicalMetadataSlice(children)", }, filepath.Join("..", "ai", "resource_context.go"): { "unifiedresources.RefreshCanonicalMetadataSlice(urp.GetInfrastructure())", "unifiedresources.RefreshCanonicalMetadataSlice(urp.GetWorkloads())", "unifiedresources.RefreshCanonicalMetadataSlice(urp.GetAll())", }, filepath.Join("..", "ai", "intelligence.go"): { "unifiedresources.RefreshCanonicalMetadataSlice(unifiedResourceProvider.GetAll())", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestResourcePolicyLabelHelpersUsedByAIConsumers(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join("..", "ai", "intelligence.go"): { "func (i *Intelligence) HasCorrelationsSource() bool", "func (i *Intelligence) GetCorrelations(resourceID string) []*correlation.Correlation", "func (i *Intelligence) FormatCorrelationsContext(resourceID string) string", }, filepath.Join("..", "ai", "service.go"): { "intel.FormatCorrelationsContext(resourceID)", }, filepath.Join("..", "ai", "patrol_ai.go"): { "intelFacade.GetCorrelations(\"\")", }, filepath.Join("..", "api", "ai_intelligence_handlers.go"): { "intel.HasCorrelationsSource()", "intel.GetCorrelations(resourceID)", }, filepath.Join("..", "ai", "chat", "knowledge_extractor.go"): { "unifiedresources.ResourcePolicyLabel(", "unifiedresources.ResourcePolicyRedactedValue(", }, filepath.Join("..", "ai", "chat", "context_prefetch.go"): { "tools.CanonicalDiscoveryResourceType(", "tools.DiscoveryProviderResourceType(", "tools.CanonicalDiscoveryTargetID(", "unifiedresources.ResourcePolicyRequiresGovernedSummary(mention.Policy)", "unifiedresources.FormatResourcePolicyGovernedSummary(mention.AISafeSummary, mention.Policy)", }, filepath.Join("..", "ai", "tools", "tools_discovery.go"): { "func CanonicalDiscoveryResourceType(raw string) string", "func DiscoveryProviderResourceType(canonical string) string", "func CanonicalDiscoveryTargetID(discovery *ResourceDiscoveryInfo, fallbackTargetID string) string", }, filepath.Join("..", "ai", "resource_export.go"): { "unifiedresources.ResourceRedactionLabelsFromHints(redactionHints)", }, filepath.Join("..", "ai", "resource_context.go"): { "unifiedresources.ResourcePolicyLabel(", "unifiedresources.ResourcePolicyRedactedText(", "unifiedresources.ResourceDisplayName(", "unifiedresources.ResourceClusterName(", "unifiedresources.ResourceIPSummary(", }, filepath.Join("..", "ai", "chat", "service.go"): { "unifiedresources.ResourcePolicyRedactedTextWithReferences(", "unifiedresources.ResourcePolicyReference(", }, filepath.Join("..", "unifiedresources", "unified_ai_adapter.go"): { "ResourceDisplayName(results[i])", "ResourceDisplayName(results[j])", }, filepath.Join(".", "policy_presentation.go"): { "func ResourcePolicyLabel(name, aiSafeSummary string, policy *ResourcePolicy) string", "if ResourcePolicyRequiresGovernedSummary(policy) {", "return ResourcePolicyRedactedLabel", "return ResourcePolicyRequiresGovernedSummary(policy)", "Policy: sensitivity=%s, routing=%s", "func ResourcePolicyRedactedValue(value string, policy *ResourcePolicy, hints ...ResourceRedactionHint) string", "func ResourcePolicyRedactedText(value string, resource Resource) string", "func ResourcePolicyRedactedTextWithReferences(value string, resource Resource, references ...ResourcePolicyRedactionReference) string", "func ResourcePolicyReference(value string, hints ...ResourceRedactionHint) ResourcePolicyRedactionReference", "const ResourcePolicyRedactedLabel = \"redacted by policy\"", "func ResourceRedactionLabelsFromHints(hints []ResourceRedactionHint) []string", "func ResourceClusterName(resource Resource) string", "func ResourceIPSummary(resource Resource, limit int) string", "func ResourcePolicyRequiresGovernedSummary(policy *ResourcePolicy) bool", "func ResourcePolicyGovernedSummaryPreamble() string", "func ResourcePolicyGovernedSummaryFooter() string", "func FormatResourcePolicyGovernedSummary(summary string, policy *ResourcePolicy) string", "func ResourceDisplayName(resource Resource) string", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestPolicyPostureSummaryIsOwnedByUnifiedResources(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join(".", "policy_posture.go"): { "type PolicyPostureSummary struct {", "func SummarizePolicyPosture(resources []Resource) *PolicyPostureSummary", "type ResourcePolicyPostureSummary struct {", "func ResourcePolicyPostureContract(summary *PolicyPostureSummary) *ResourcePolicyPostureSummary", }, filepath.Join("..", "ai", "intelligence.go"): { "unifiedresources.PolicyPostureSummary", "unifiedresources.SummarizePolicyPosture(", }, filepath.Join("..", "ai", "resource_context.go"): { "unifiedresources.SummarizePolicyPosture(allResources)", }, filepath.Join("..", "api", "resources.go"): { "resourcePolicyPostureAggregation(allResources)", "unified.ResourcePolicyPostureContract(unified.SummarizePolicyPosture(canonicalResources))", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestExportDecisionHelpersUsedByAIConsumers(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "ai", "resource_export.go")) if err != nil { t.Fatalf("failed to read resource_export.go: %v", err) } source := string(data) requiredSnippets := []string{ "unifiedresources.ExportSensitivityFloor(sensitivityCounts)", "unifiedresources.ExportDecisionForContext(sensitivityFloor, localOnlyCount, len(redactions))", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/ai/resource_export.go must pin canonical export decision snippet %q", snippet) } } } func TestExportDecisionHelpersCanonicalInUnifiedResources(t *testing.T) { data, err := os.ReadFile(filepath.Join("privacy.go")) if err != nil { t.Fatalf("failed to read privacy.go: %v", err) } source := string(data) requiredSnippets := []string{ "func ExportSensitivityFloor(counts map[ResourceSensitivity]int) DataSensitivity", "func ExportDecisionForContext(sensitivityFloor DataSensitivity, localOnlyCount int, redactionCount int) (ExportDecision, string)", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/unifiedresources/privacy.go must pin canonical export helper snippet %q", snippet) } } } func TestRootCauseEngineUsesCanonicalRelationshipModel(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "ai", "correlation", "rootcause.go")) if err != nil { t.Fatalf("failed to read rootcause.go: %v", err) } source := string(data) requiredSnippets := []string{ "type RelationshipType = unifiedresources.RelationshipType", "type ResourceRelationship = unifiedresources.ResourceRelationship", "GetRelationships(resourceID string) []ResourceRelationship", "score += relationshipScore(rel.Type)", "func relationshipScore(t RelationshipType) float64", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/ai/correlation/rootcause.go must pin canonical relationship snippet %q", snippet) } } } func TestResourceDisplayNameUsedByInfrastructureConsumers(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join("..", "monitoring", "connected_infrastructure.go"): { "unifiedresources.ResourceDisplayName(resource)", }, filepath.Join(".", "monitored_systems.go"): { "if name := ResourceDisplayName(*resource); name != \"\" {", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } for _, snippet := range snippets { if !strings.Contains(string(data), snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestTopLevelSystemResolverPinsCanonicalInfrastructureCounting(t *testing.T) { requiredSnippets := map[string][]string{ filepath.Join(".", "monitored_systems.go"): { "resolveMonitoredSystemTopLevelSystems(rs).Count()", "ResolveTopLevelSystems(resources)", }, filepath.Join(".", "top_level_systems.go"): { "ResolveTopLevelSystems(resources []Resource) TopLevelSystemResolver", "match.Confidence < HighConfidenceThreshold", "topLevelSystemGroupingExplanation(", "monitoredSystemCandidateAllowsHostAttachment(candidate)", "When adding a new top-level monitored-system source, update:", }, } for name, snippets := range requiredSnippets { data, err := os.ReadFile(name) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } source := string(data) for _, snippet := range snippets { if !strings.Contains(source, snippet) { t.Fatalf("%s must contain %q", name, snippet) } } } } func TestResourceTimelineStoreIndexesSupportFilteredReads(t *testing.T) { data, err := os.ReadFile(filepath.Join("store.go")) if err != nil { t.Fatalf("failed to read store.go: %v", err) } source := string(data) requiredSnippets := []string{ "idx_resource_changes_kind_time", "idx_resource_changes_source_type_time", "idx_resource_changes_source_adapter_time", "ensureResourceChangesIndexes", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/unifiedresources/store.go must pin filtered timeline index snippet %q", snippet) } } } func TestResourceChangeEmissionCoversRelationshipAndCapabilityChanges(t *testing.T) { data, err := os.ReadFile(filepath.Join("change_emission.go")) if err != nil { t.Fatalf("failed to read change_emission.go: %v", err) } source := string(data) requiredSnippets := []string{ "change.RelatedResources = relatedResourceIDs(change.ResourceID, before, after)", "case resourceRestartChanged(before, after):", "case resourceIncidentChanged(before, after):", "if !reflect.DeepEqual(before.Relationships, after.Relationships) {", "changed = append(changed, \"relationships\")", "if resourceIncidentChanged(before, after) {", "changed = append(changed, \"incidents\")", "if dockerRestartChanged(before, after) {", "changed = append(changed, \"docker.restartCount\", \"docker.uptimeSeconds\")", "if kubernetesRestartChanged(before, after) {", "changed = append(changed, \"kubernetes.restarts\", \"kubernetes.uptimeSeconds\")", "if !reflect.DeepEqual(before.Capabilities, after.Capabilities) {", "changed = append(changed, \"capabilities\")", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/unifiedresources/change_emission.go must pin canonical relationship/capability change detection snippet %q", snippet) } } } func TestResourceChangePresentationUsesCanonicalLabels(t *testing.T) { data, err := os.ReadFile(filepath.Join("change_presentation.go")) if err != nil { t.Fatalf("failed to read change_presentation.go: %v", err) } source := string(data) requiredSnippets := []string{ "func ChangeKindLabel(kind ChangeKind) string", "func DescribeChange(change ResourceChange) ChangePresentation", "func FormatResourceChangeSummary(change ResourceChange) string", "func resourceRelationshipSummary(relationships []ResourceRelationship) string", "resourceStateSummary(resource Resource) string", "resourceRestartSummary(resource Resource) string", "resourceIncidentSummary(resource Resource) string", "resourceIncidentSummaryFromSlice(incidents []ResourceIncident) string", "resourceIncidentLabel(incident ResourceIncident) string", "resourceConfigSummary(resource Resource) string", "KindLabel: ChangeKindLabel(change.Kind)", "presentation.SourceType = strings.TrimSpace(string(change.SourceType))", "presentation.SourceAdapter = strings.TrimSpace(string(change.SourceAdapter))", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/unifiedresources/change_presentation.go must pin canonical change presentation snippet %q", snippet) } } } func TestResourceRelationshipContextUsesCanonicalRelationshipPresentation(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "ai", "service.go")) if err != nil { t.Fatalf("failed to read service.go: %v", err) } source := string(data) requiredSnippets := []string{ "func (s *Service) buildResourceRelationshipContext(resourceID string) string", "if relationshipContext := s.buildResourceRelationshipContext(resourceID); relationshipContext != \"\" {", "Get canonical relationship context from unified resources.", "unifiedresources.FormatResourceRelationshipContext(resource, 3)", "unifiedresources.FormatResourceRecentChangesContext(changes, false, \"###\")", "type canonicalResourceGetter interface {", "intel.FormatCorrelationsContext(resourceID)", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/ai/service.go must pin canonical relationship presentation snippet %q", snippet) } } } func TestResourceRelationshipModelUsesCanonicalEdgeComment(t *testing.T) { data, err := os.ReadFile(filepath.Join("relationships.go")) if err != nil { t.Fatalf("failed to read relationships.go: %v", err) } source := string(data) requiredSnippets := []string{ "// ResourceRelationship represents a typed relationship edge between two unified resources.", "type ResourceRelationship struct {", "const parentRelationshipDiscoverer = \"resource_registry\"", "func ResourceRelationshipsWithCanonicalParent(resource Resource) []ResourceRelationship", "relationshipType := parentRelationshipType(resource.Type)", "Metadata: map[string]any{", "func parentRelationshipType(resourceType ResourceType) RelationshipType", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/unifiedresources/relationships.go must pin canonical relationship edge snippet %q", snippet) } } } func TestPatrolSeedCorrelationContextUsesCanonicalSummaryFormatter(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "ai", "patrol_ai.go")) if err != nil { t.Fatalf("failed to read patrol_ai.go: %v", err) } source := string(data) requiredSnippets := []string{ "# Known Resource Correlations", "correlation.FormatCorrelationSummary(c)", "memory.ChangeFromUnifiedResourceChange(change)", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/ai/patrol_ai.go must pin canonical correlation presentation snippet %q", snippet) } } } func TestIntelligenceRecentChangesUseCanonicalSummaryFormatter(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "ai", "intelligence.go")) if err != nil { t.Fatalf("failed to read intelligence.go: %v", err) } source := string(data) requiredSnippets := []string{ "func (i *Intelligence) GetRecentChanges(since time.Time, limit int) []unifiedresources.ResourceChange", "func (i *Intelligence) DescribeResource(resourceID string) (string, string)", "func (i *Intelligence) HasRecentChangesSource() bool", "unifiedresources.FormatResourceRecentChangesContext(recent, includeResourcePrefix, \"##\")", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/ai/intelligence.go must pin canonical recent-change snippet %q", snippet) } } } func TestMemoryChangeConversionHelpersAreSharedAcrossAIConsumers(t *testing.T) { requiredFiles := map[string][]string{ filepath.Join("..", "ai", "patrol_ai.go"): { "memory.ChangeFromUnifiedResourceChange(change)", }, filepath.Join("..", "ai", "intelligence.go"): { "memory.ResourceChangeFromMemoryChange(change)", }, filepath.Join("..", "ai", "memory", "presentation.go"): { "func ChangeFromUnifiedResourceChange(change unifiedresources.ResourceChange) Change", "func ResourceChangeFromMemoryChange(change Change) unifiedresources.ResourceChange", }, } for path, snippets := range requiredFiles { data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } source := string(data) for _, snippet := range snippets { if !strings.Contains(source, snippet) { t.Fatalf("%s must pin canonical memory conversion snippet %q", path, snippet) } } } } func TestAIRecentChangesHandlerUsesCanonicalIntelligencePath(t *testing.T) { data, err := os.ReadFile(filepath.Join("..", "api", "ai_intelligence_handlers.go")) if err != nil { t.Fatalf("failed to read ai_intelligence_handlers.go: %v", err) } source := string(data) requiredSnippets := []string{ "intel := patrol.GetIntelligence()", "intel.HasRecentChangesSource()", "intel.GetRecentChanges(since, 100)", "intel.DescribeResource(change.ResourceID)", "unifiedresources.FormatResourceChangeSummary(change)", "Recent changes not initialized", } for _, snippet := range requiredSnippets { if !strings.Contains(source, snippet) { t.Fatalf("internal/api/ai_intelligence_handlers.go must pin canonical recent-changes snippet %q", snippet) } } } func TestResourcePresentationsUseSharedDurationHelper(t *testing.T) { requiredFiles := []string{ "change_presentation.go", "relationship_presentation.go", } for _, name := range requiredFiles { data, err := os.ReadFile(filepath.Join(name)) if err != nil { t.Fatalf("failed to read %s: %v", name, err) } if !strings.Contains(string(data), "utils.FormatDurationAgo(") { t.Fatalf("%s must use the shared utils.FormatDurationAgo helper", name) } } } func TestResourceFacetCountsAreCanonicalResourceFields(t *testing.T) { typesData, err := os.ReadFile(filepath.Join("types.go")) if err != nil { t.Fatalf("failed to read types.go: %v", err) } typesSource := string(typesData) if !strings.Contains(typesSource, "FacetCounts ResourceFacetCounts") { t.Fatalf("internal/unifiedresources/types.go must expose Resource.FacetCounts on the canonical resource model") } if !strings.Contains(typesSource, "json:\"facetCounts,omitempty\"") { t.Fatalf("internal/unifiedresources/types.go must keep the facetCounts JSON contract") } if !strings.Contains(typesSource, "RecentChangeKinds map[ChangeKind]int") { t.Fatalf("internal/unifiedresources/types.go must expose grouped timeline counts on the canonical facet model") } if !strings.Contains(typesSource, "RecentChangeSourceTypes map[ChangeSourceType]int") { t.Fatalf("internal/unifiedresources/types.go must expose grouped timeline source-type counts on the canonical facet model") } if !strings.Contains(typesSource, "RecentChangeSourceAdapters map[ChangeSourceAdapter]int") { t.Fatalf("internal/unifiedresources/types.go must expose grouped timeline source-adapter counts on the canonical facet model") } cloneData, err := os.ReadFile(filepath.Join("clone.go")) if err != nil { t.Fatalf("failed to read clone.go: %v", err) } cloneSource := string(cloneData) requiredSnippets := []string{ "out.FacetCounts = resourceFacetCounts(out)", "func resourceFacetCounts(resource Resource) ResourceFacetCounts", } for _, snippet := range requiredSnippets { if !strings.Contains(cloneSource, snippet) { t.Fatalf("internal/unifiedresources/clone.go must derive canonical facet counts via %q", snippet) } } } func TestCanonicalIdentityIsCanonicalResourceField(t *testing.T) { typesData, err := os.ReadFile(filepath.Join("types.go")) if err != nil { t.Fatalf("failed to read types.go: %v", err) } typesSource := string(typesData) requiredSnippets := []string{ "json:\"canonicalIdentity,omitempty\"", "type CanonicalIdentity struct {", "DisplayName string `json:\"displayName,omitempty\"`", "Aliases []string `json:\"aliases,omitempty\"`", } for _, snippet := range requiredSnippets { if !strings.Contains(typesSource, snippet) { t.Fatalf("internal/unifiedresources/types.go must keep the canonical identity contract snippet %q", snippet) } } cloneData, err := os.ReadFile(filepath.Join("clone.go")) if err != nil { t.Fatalf("failed to read clone.go: %v", err) } cloneSource := string(cloneData) requiredCloneSnippets := []string{ "RefreshCanonicalMetadata(&out)", } for _, snippet := range requiredCloneSnippets { if !strings.Contains(cloneSource, snippet) { t.Fatalf("internal/unifiedresources/clone.go must preserve canonical identity via %q", snippet) } } } // TestNoLegacyHostResourceTypeSymbol prevents reintroducing the removed // ResourceTypeHost symbol. v6 code must use ResourceTypeAgent and // CanonicalResourceType() for legacy normalization. func TestNoLegacyHostResourceTypeSymbol(t *testing.T) { internalDir := filepath.Join("..") err := filepath.Walk(internalDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } if filepath.Ext(path) != ".go" || strings.HasSuffix(path, "_test.go") { return nil } data, readErr := os.ReadFile(path) if readErr != nil { return readErr } content := string(data) if !strings.Contains(content, "ResourceTypeHost") { return nil } normalizedPath := filepath.ToSlash(path) t.Errorf("%s: legacy ResourceTypeHost symbol detected; use ResourceTypeAgent instead", normalizedPath) return nil }) if err != nil { t.Fatalf("failed to scan internal packages: %v", err) } } func TestResourceParentBySourceStateRemainsInternal(t *testing.T) { resourceType := reflect.TypeOf(Resource{}) parentIDField, ok := resourceType.FieldByName("ParentID") if !ok { t.Fatalf("expected Resource.ParentID field") } if got := parentIDField.Tag.Get("json"); got != "parentId,omitempty" { t.Fatalf("Resource.ParentID json tag = %q, want %q", got, "parentId,omitempty") } parentBySourceField, ok := resourceType.FieldByName("parentBySource") if !ok { t.Fatalf("expected Resource.parentBySource field") } if parentBySourceField.IsExported() { t.Fatalf("expected Resource.parentBySource to remain internal-only") } if got := parentBySourceField.Tag.Get("json"); got != "" { t.Fatalf("expected Resource.parentBySource to have no JSON contract, got %q", got) } } // TestNoLegacyMigrationHintsInRuntimeCode prevents reintroducing runtime // messages that point removed aliases at the wrong token guidance. func TestNoLegacyMigrationHintsInRuntimeCode(t *testing.T) { bannedPhrases := []string{ `no longer supported; use "agent"`, `no longer supported; use "agent:*"`, `app_container is no longer supported; use container`, } internalDir := filepath.Join("..") err := filepath.Walk(internalDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } if filepath.Ext(path) != ".go" || strings.HasSuffix(path, "_test.go") { return nil } data, readErr := os.ReadFile(path) if readErr != nil { return readErr } content := string(data) normalizedPath := filepath.ToSlash(path) for _, phrase := range bannedPhrases { if !strings.Contains(content, phrase) { continue } t.Errorf("%s: banned legacy migration hint detected: %q", normalizedPath, phrase) } return nil }) if err != nil { t.Fatalf("failed to scan internal packages: %v", err) } } // TestV6AgentRegistrationArtifactsStayCanonical prevents the release-facing // agent registration journey and eval instructions from drifting back to // legacy /api/state.hosts or legacy agent.type="host" assumptions. func TestV6AgentRegistrationArtifactsStayCanonical(t *testing.T) { repoRoot := filepath.Join("..", "..") integrationRoots := []string{ filepath.Join(repoRoot, "tests", "integration", "tests"), filepath.Join(repoRoot, "tests", "integration", "evals"), } globalBannedPatterns := []*regexp.Regexp{ regexp.MustCompile(`state\.hosts\b`), regexp.MustCompile(`hosts array`), regexp.MustCompile(`agent\.type\s*=\s*"host"`), regexp.MustCompile(`type:\s*'host'`), regexp.MustCompile(`"type"\s*:\s*"host"`), regexp.MustCompile(`resourceType"\s*:\s*"host"`), regexp.MustCompile(`resourceType:\s*'host'`), regexp.MustCompile(`/api/resources\?type=host`), } for _, root := range integrationRoots { err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } switch filepath.Ext(path) { case ".ts", ".tsx", ".md": default: return nil } data, readErr := os.ReadFile(path) if readErr != nil { return readErr } content := string(data) normalizedPath := filepath.ToSlash(path) for _, pattern := range globalBannedPatterns { matches := pattern.FindAllStringIndex(content, -1) for _, match := range matches { line := 1 + strings.Count(content[:match[0]], "\n") t.Errorf("%s:%d: banned legacy integration/eval pattern %q", normalizedPath, line, pattern.String()) } } return nil }) if err != nil { t.Fatalf("failed to scan %s: %v", root, err) } } artifacts := []struct { path string requiredSnippets []string bannedPatterns []*regexp.Regexp }{ { path: filepath.Join( repoRoot, "tests", "integration", "tests", "journeys", "04-agent-install-registration.spec.ts", ), requiredSnippets: []string{ "state.resources", "type: 'unified'", }, bannedPatterns: []*regexp.Regexp{ regexp.MustCompile(`state\.hosts\b`), regexp.MustCompile(`hosts array`), regexp.MustCompile(`type:\s*'host'`), regexp.MustCompile(`"type"\s*:\s*"host"`), }, }, { path: filepath.Join( repoRoot, "tests", "integration", "evals", "tasks", "agent-registration.md", ), requiredSnippets: []string{ "resources[]", `agent.type = "unified"`, }, bannedPatterns: []*regexp.Regexp{ regexp.MustCompile("`hosts` array"), regexp.MustCompile(`agent\.type\s*=\s*"host"`), }, }, } for _, artifact := range artifacts { data, err := os.ReadFile(artifact.path) if err != nil { t.Fatalf("failed to read %s: %v", artifact.path, err) } content := string(data) normalizedPath := filepath.ToSlash(artifact.path) for _, snippet := range artifact.requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required canonical v6 snippet %q", normalizedPath, snippet) } } for _, pattern := range artifact.bannedPatterns { matches := pattern.FindAllStringIndex(content, -1) for _, match := range matches { line := 1 + strings.Count(content[:match[0]], "\n") t.Errorf( "%s:%d: banned legacy agent registration artifact pattern %q", normalizedPath, line, pattern.String(), ) } } } } // TestV6AIEvalPromptsStayCanonical prevents internal AI eval scenarios from // teaching legacy pulse_query list types after the v6 canonicalization. func TestV6AIEvalPromptsStayCanonical(t *testing.T) { repoRoot := filepath.Join("..", "..") path := filepath.Join(repoRoot, "internal", "ai", "eval", "scenarios.go") data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } content := string(data) normalizedPath := filepath.ToSlash(path) requiredSnippets := []string{ `type=system-containers`, `type=app-containers`, } for _, snippet := range requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required canonical AI eval snippet %q", normalizedPath, snippet) } } bannedSnippets := []string{ `type=containers`, `type=docker`, } for _, snippet := range bannedSnippets { if !strings.Contains(content, snippet) { continue } t.Errorf("%s: banned legacy AI eval snippet %q", normalizedPath, snippet) } } // TestV6AlertConfigAliasesStayStripped keeps alert-config compatibility tests // pinned on dropping removed legacy resource-type aliases and host-era keys. func TestV6AlertConfigAliasesStayStripped(t *testing.T) { repoRoot := filepath.Join("..", "..") path := filepath.Join(repoRoot, "internal", "alerts", "config_aliases_test.go") data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } content := string(data) normalizedPath := filepath.ToSlash(path) requiredSnippets := []string{ `TestAlertConfigUnmarshal_LegacyHostAliasesIgnored`, `expected legacy timeThresholds.host to be removed`, `expected legacy timeThresholds.docker to be removed`, `expected legacy timeThresholds.k8s to be removed`, `expected legacy metricTimeThresholds.host to be removed`, `expected legacy metricTimeThresholds.dockerhost to be removed`, `expected legacy metricTimeThresholds.kubernetes-cluster to be removed`, `TestAlertConfigUnmarshal_CanonicalKeysTakePrecedence`, `did not expect legacy metricTimeThresholds.docker to remain`, `TestAlertConfigMarshal_UsesCanonicalAgentKeys`, `did not expect legacy hostDefaults in output`, `did not expect legacy disableAllHosts in output`, } for _, snippet := range requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required alert-config alias stripping snippet %q", normalizedPath, snippet) } } } // TestV6BroadLegacyAliasCoverage keeps the broader removed alias set pinned in // central API, AI, and alerts tests so coverage does not regress back to host-only. func TestV6BroadLegacyAliasCoverage(t *testing.T) { repoRoot := filepath.Join("..", "..") artifacts := []struct { path string requiredSnippets []string }{ { path: filepath.Join(repoRoot, "internal", "api", "ai_handlers_test.go"), requiredSnippets: []string{ `legacy guest rejected`, `legacy docker rejected`, `legacy container rejected`, `legacy k8s alias rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "alert_adapter_test.go"), requiredSnippets: []string{ `vm qemu rejected`, `system container lxc rejected`, `legacy system_container alias rejected`, `legacy docker_container alias rejected`, `legacy docker_service alias rejected`, `legacy kubernetes_cluster alias rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "patrol_run_test.go"), requiredSnippets: []string{ `expected legacy 'qemu' alias to be rejected`, `expected legacy 'container' alias to be rejected`, `expected legacy 'system_container' alias to be rejected`, `expected legacy 'docker_container' alias to be rejected`, `expected legacy 'kubernetes_cluster' alias to be rejected`, `expected legacy 'app_container' alias to be rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_metrics_alerts_test.go"), requiredSnippets: []string{ `expected error for legacy system_container resource_type`, `expected error for legacy container resource_type`, `expected error for legacy app_container resource_type`, `expected error for legacy docker resource_type`, }, }, { path: filepath.Join(repoRoot, "internal", "alerts", "utility_test.go"), requiredSnippets: []string{ `legacy host alias type key is dropped`, `legacy docker alias type key is dropped`, }, }, } for _, artifact := range artifacts { data, err := os.ReadFile(artifact.path) if err != nil { t.Fatalf("failed to read %s: %v", artifact.path, err) } content := string(data) normalizedPath := filepath.ToSlash(artifact.path) for _, snippet := range artifact.requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required broad legacy-alias coverage snippet %q", normalizedPath, snippet) } } } } // TestV6ReleaseFacingAPITestsCoverLegacyHostRejection keeps release-facing API // contract tests pinned on strict v6 behavior for removed host aliases. func TestV6ReleaseFacingAPITestsCoverLegacyHostRejection(t *testing.T) { repoRoot := filepath.Join("..", "..") artifacts := []struct { path string requiredSnippets []string }{ { path: filepath.Join(repoRoot, "internal", "api", "ai_handler_test.go"), requiredSnippets: []string{ `canonicalizeChatMentionType("host")`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "ai_handlers_test.go"), requiredSnippets: []string{ `"target_type":"host"`, `unsupported resource_type "host"`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "org_handlers_test.go"), requiredSnippets: []string{ `"resourceType":"host"`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "resources_test.go"), requiredSnippets: []string{ `/api/resources?type=host`, `unsupported type filter token(s): host`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "discovery_handlers_info_test.go"), requiredSnippets: []string{ `/api/discovery/info/host`, `unsupported resource type "host"`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "discovery_handlers_test.go"), requiredSnippets: []string{ `/api/discovery/type/host`, `/api/discovery/host/host-1/host-1`, `unsupported resource type "host"`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "docker_agents_routes_more_test.go"), requiredSnippets: []string{ `legacy hosts alias status = %d, want 400`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "reporting_handlers_test.go"), requiredSnippets: []string{ `/api/reporting?format=pdf&resourceType=host&resourceId=h-1`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "router_version_tenant_metrics_test.go"), requiredSnippets: []string{ `/api/metrics-store/history?resourceType=host&resourceId=agent-1&metric=cpu&range=1h`, `unsupported resourceType "host"`, }, }, } for _, artifact := range artifacts { data, err := os.ReadFile(artifact.path) if err != nil { t.Fatalf("failed to read %s: %v", artifact.path, err) } content := string(data) normalizedPath := filepath.ToSlash(artifact.path) for _, snippet := range artifact.requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required legacy-host rejection snippet %q", normalizedPath, snippet) } } } } // TestV6DirectHostAliasValidatorCoverage keeps direct validator-level tests in // place for the highest-risk host-alias rejection paths. func TestV6DirectHostAliasValidatorCoverage(t *testing.T) { repoRoot := filepath.Join("..", "..") artifacts := []struct { path string requiredSnippets []string }{ { path: filepath.Join(repoRoot, "internal", "api", "ai_handlers_test.go"), requiredSnippets: []string{ `TestNormalizeAndValidateAIExecuteTargetType_StrictCanonicalV6`, `legacy host rejected", in: "host"`, `TestNormalizeInvestigateAlertTargetType_StrictCanonicalV6`, `host target type rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "org_handlers_test.go"), requiredSnippets: []string{ `TestIsUnsupportedOrganizationShareResourceType`, `host unsupported`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "discovery_handlers_test.go"), requiredSnippets: []string{ `TestParseDiscoveryResourceType_RejectsLegacyHostAlias`, `legacy host rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "resource_type_legacy_test.go"), requiredSnippets: []string{ `TestIsUnsupportedLegacyAIResourceTypeToken`, `legacy host rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_patrol_test.go"), requiredSnippets: []string{ `TestHandlePatrolReportFinding_RejectsLegacyResourceTypeAliases`, `TestHandlePatrolReportFinding_AcceptsPhysicalDiskResourceType`, `"resource_type"] = "physical_disk"`, `[]string{"host", "container", "docker"`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_discovery_test.go"), requiredSnippets: []string{ `TestIsUnsupportedDiscoveryLegacyResourceTypeToken`, `"host", "lxc"`, `TestExecuteListDiscoveries_RejectsLegacyTypeAlias`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_query_test.go"), requiredSnippets: []string{ `TestExecuteGetTopology_RejectsLegacyDockerIncludeAlias`, `expected error for legacy include alias`, `invalid include`, `"type": "host"`, `invalid type: host`, `"resource_type": "host"`, `invalid resource_type: host`, `[]string{"lxc", "host"}`, `TestExecuteGetGuestConfig_RejectsLegacyResourceTypes`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "alert_adapter_test.go"), requiredSnippets: []string{ `with_metadata_host_legacy_ignored`, `agent host alias rejected`, `input: "host"`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "findings_resource_type_test.go"), requiredSnippets: []string{ `{in: "host", want: ""}`, `TestNormalizeFindingResourceTypes_RejectsLegacyAndInfers`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "patrol_triggers_test.go"), requiredSnippets: []string{ `AnomalyDetectedPatrolScope("res-host", "host", "cpu", 95, 50)`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "patrol_run_test.go"), requiredSnippets: []string{ `expected legacy 'host' alias to be rejected`, `expected non-canonical 'docker' alias to be rejected`, `expected non-canonical 'agent_raid' alias to be rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "patrol_triage_test.go"), requiredSnippets: []string{ `triageResourceType("host", "qemu/100")`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "adapters", "adapters_additional_test.go"), requiredSnippets: []string{ `expected unsupported host resource ID to be rejected`, `expected unsupported host query alias to be rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "knowledge", "store_extended_test.go"), requiredSnippets: []string{ `expected unsupported host guest ID to be rejected`, `expected unsupported host guest ID query to be rejected`, `expected unsupported host guest type to be rejected`, `expected unsupported host file to remain unchanged`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "approval", "store_test.go"), requiredSnippets: []string{ `expected unsupported host target type to be rejected`, `expected error for unsupported host target type input`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "metadata_provider_test.go"), requiredSnippets: []string{ `[]string{"host", "guest", "docker", "container", "lxc", "qemu", "docker_container", "docker_service"}`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "incident_coordinator_additional_test.go"), requiredSnippets: []string{ `TestIncidentCoordinator_OnAnomalyDetected_CanonicalizesLegacyHostAlias`, `expected anomaly recording resource type to be canonicalized to agent`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_metrics_alerts_test.go"), requiredSnippets: []string{ `expected error for legacy host resource_type`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_read_test.go"), requiredSnippets: []string{ `TestPulseToolExecutor_ExecuteReadRejectsLegacyAppContainerArg`, `app_container is no longer supported; use app-container`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "tools", "tools_file_test.go"), requiredSnippets: []string{ `Legacy AppContainer Rejected`, `app_container is no longer supported; use app-container`, }, }, { path: filepath.Join(repoRoot, "internal", "ai", "chat", "context_prefetch_additional_test.go"), requiredSnippets: []string{ `expected legacy host mention to be ignored`, }, }, { path: filepath.Join(repoRoot, "internal", "alerts", "utility_test.go"), requiredSnippets: []string{ `legacy host alias rejected`, `legacy container alias rejected`, `legacy docker alias rejected`, `legacy k8s alias rejected`, }, }, { path: filepath.Join(repoRoot, "internal", "metrics", "incident_recorder_test.go"), requiredSnippets: []string{ `TestStartRecordingCanonicalizesLegacyHostAlias`, `expected legacy host alias to canonicalize to agent`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "resources_test.go"), requiredSnippets: []string{ `/api/resources?type=host`, `unsupported type filter token(s): host`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "resources_frontend_types_test.go"), requiredSnippets: []string{ `unsupported host ignored by parser`, `TestUnsupportedResourceTypeFilterTokensRejectsLegacyAliases`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "router_helpers_additional_test.go"), requiredSnippets: []string{ `metadata legacy resource type ignored`, `Metadata: map[string]interface{}{"resourceType": "host"}`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "reporting_handlers_test.go"), requiredSnippets: []string{ `TestNormalizeReportResourceType_RejectsLegacyAliases`, `{"host", "container"}`, }, }, { path: filepath.Join(repoRoot, "internal", "api", "router_misc_additional_test.go"), requiredSnippets: []string{ `TestNormalizeMetricsHistoryResourceType_RejectsLegacyAliases`, `[]string{"host", "guest", "docker", "dockerhost", "dockercontainer", "system_container"}`, }, }, } for _, artifact := range artifacts { data, err := os.ReadFile(artifact.path) if err != nil { t.Fatalf("failed to read %s: %v", artifact.path, err) } content := string(data) normalizedPath := filepath.ToSlash(artifact.path) for _, snippet := range artifact.requiredSnippets { if !strings.Contains(content, snippet) { t.Errorf("%s: missing required direct host-alias validator snippet %q", normalizedPath, snippet) } } } } // SRC-04b: Ratchet-to-hard-ban conversion completed 2026-03-01. // // All state.* field access patterns and GetState() calls in consumer packages // reached ceiling 0 through SRC-03a → SRC-04g migration work. They are now // enforced as hard bans via migratedResourcePatterns above (per-file, per-line // error reporting). The legacy ratchet infrastructure (legacyStateRatchet type, // legacyStateRatchets slice, TestLegacyStateAccessRatchet) has been removed. // // Migration changelog preserved in git history (see commits SRC-03f → SRC-04g). func TestResourceAPIHotPathUsesSingleRegistryListSnapshot(t *testing.T) { repoRoot := filepath.Join("..", "..") path := filepath.Join(repoRoot, "internal", "api", "resources.go") data, err := os.ReadFile(path) if err != nil { t.Fatalf("failed to read %s: %v", path, err) } source := string(data) normalizedPath := filepath.ToSlash(path) if strings.Count(source, "allResources := registry.List()") != 2 { t.Fatalf("%s: expected HandleListResources and HandleStats to each seed exactly one registry list snapshot", normalizedPath) } if strings.Count(source, "computeResourceContractByType(allResources)") != 2 { t.Fatalf("%s: expected canonical by-type aggregations to reuse the seeded registry snapshot in both handlers", normalizedPath) } if strings.Contains(source, "computeResourceContractByType(registry.List())") { t.Fatalf("%s: duplicate registry.List() hot-path aggregation detected", normalizedPath) } } func TestCanonicalResourceOrderingContractsStayShared(t *testing.T) { repoRoot := filepath.Join("..", "..") resourcesPath := filepath.Join(repoRoot, "internal", "api", "resources.go") registryPath := filepath.Join(repoRoot, "internal", "unifiedresources", "registry.go") resourcesSource, err := os.ReadFile(resourcesPath) if err != nil { t.Fatalf("failed to read %s: %v", resourcesPath, err) } registrySource, err := os.ReadFile(registryPath) if err != nil { t.Fatalf("failed to read %s: %v", registryPath, err) } if !strings.Contains(string(resourcesSource), "unified.CompareResourcesByCanonicalName") { t.Fatalf("%s: /api/resources must route deterministic list ordering through unified.CompareResourcesByCanonicalName", filepath.ToSlash(resourcesPath)) } if !strings.Contains(string(registrySource), "sortResourcesByName(out)") { t.Fatalf("%s: ResourceRegistry.List() must normalize map iteration through sortResourcesByName(out)", filepath.ToSlash(registryPath)) } if !strings.Contains(string(registrySource), "sortNamedResourceViewsByName(rr.cachedStorage)") { t.Fatalf("%s: cached unified resource views must share the canonical deterministic name ordering helper", filepath.ToSlash(registryPath)) } } func TestBroadcastStateUsesSharedCanonicalResourceContract(t *testing.T) { repoRoot := filepath.Join("..", "..") typesPath := filepath.Join(repoRoot, "internal", "unifiedresources", "types.go") resourcesPath := filepath.Join(repoRoot, "internal", "api", "resources.go") monitorPath := filepath.Join(repoRoot, "internal", "monitoring", "monitor.go") typesSource, err := os.ReadFile(typesPath) if err != nil { t.Fatalf("failed to read %s: %v", typesPath, err) } resourcesSource, err := os.ReadFile(resourcesPath) if err != nil { t.Fatalf("failed to read %s: %v", resourcesPath, err) } monitorSource, err := os.ReadFile(monitorPath) if err != nil { t.Fatalf("failed to read %s: %v", monitorPath, err) } if !strings.Contains(string(typesSource), "func ContractResourceType(resource Resource) ResourceType {") { t.Fatalf("%s: unified resource contract type helper must remain canonical", filepath.ToSlash(typesPath)) } if !strings.Contains(string(resourcesSource), "return unified.ContractResourceType(r)") { t.Fatalf("%s: /api/resources must derive external resource types from unified.ContractResourceType", filepath.ToSlash(resourcesPath)) } requiredMonitorSnippets := []string{ "unifiedView := m.currentUnifiedStateView()", "return string(unifiedresources.ContractResourceType(resource))", "unifiedresources.ResourceDisplayName(resource)", "unifiedresources.ResourceClusterName(resource)", } for _, snippet := range requiredMonitorSnippets { if !strings.Contains(string(monitorSource), snippet) { t.Fatalf("%s: websocket/state broadcast must contain %q", filepath.ToSlash(monitorPath), snippet) } } }