package uiaselector import "time" const ( StrictExitOK = 0 StrictExitReportGenerationFailure = 1 StrictExitUnmatched = 2 StrictExitAmbiguous = 3 StrictExitInvalidCatalog = 4 ) type Report struct { OK bool `json:"ok"` SourceDump string `json:"source_dump"` CatalogSize int `json:"catalog_size"` MatchedCount int `json:"matched_count"` UnmatchedCount int `json:"unmatched_count"` AmbiguousCount int `json:"ambiguous_count"` GeneratedAtUTC string `json:"generated_at_utc"` Selectors []SelectorReport `json:"selectors"` Warnings []string `json:"warnings"` Error *ReportError `json:"error,omitempty"` } type ReportError struct { Code string `json:"code"` Message string `json:"message"` } type SelectorReport struct { SelectorID string `json:"selector_id"` Description string `json:"description"` AllowedUse string `json:"allowed_use"` StabilityScore int `json:"stability_score"` Evidence Evidence `json:"evidence"` Matched bool `json:"matched"` MatchCount int `json:"match_count"` Matches []NodeMatch `json:"matches"` Warnings []string `json:"warnings"` } func RunCatalogReport(sourceDump string, root *Node, catalog []Selector, generatedAt time.Time) Report { report := Report{ OK: true, SourceDump: sourceDump, CatalogSize: len(catalog), GeneratedAtUTC: generatedAt.UTC().Format(time.RFC3339), Warnings: []string{}, } if root == nil { report.OK = false report.Error = &ReportError{Code: "NO_ROOT", Message: "UIA dump root is nil"} return report } for _, selector := range catalog { if selector.AllowedUse != AllowedUseReadOnlyLocate { report.OK = false report.Error = &ReportError{Code: "INVALID_CATALOG", Message: "selector is not read-only: " + selector.ID} return report } match := MatchSelector(root, catalog, selector.ID) selectorReport := SelectorReport{ SelectorID: selector.ID, Description: selector.Description, AllowedUse: selector.AllowedUse, StabilityScore: selector.StabilityScore, Evidence: selector.Evidence, Matched: match.Matched, MatchCount: match.MatchCount, Matches: match.Matches, Warnings: append([]string{}, match.Warnings...), } report.Selectors = append(report.Selectors, selectorReport) if match.Matched { report.MatchedCount++ } else { report.UnmatchedCount++ } if match.MatchCount > 1 { report.AmbiguousCount++ } } return report } func StrictExitCode(report Report) int { if !report.OK { if report.Error != nil && report.Error.Code == "INVALID_CATALOG" { return StrictExitInvalidCatalog } return StrictExitReportGenerationFailure } if report.UnmatchedCount > 0 { return StrictExitUnmatched } if report.AmbiguousCount > 0 { return StrictExitAmbiguous } return StrictExitOK }