package llm import ( "fmt" "strings" "gitea.maximumdirect.net/eric/audita/v3/internal/core/config" ck "go.maximumdirect.net/configkit" "gopkg.in/yaml.v3" ) type derivationView struct { Operation ck.ChangeKind `yaml:"operation"` Reason string `yaml:"reason"` Dependencies []string `yaml:"dependencies,omitempty"` } type inheritanceStepView struct { From string `yaml:"from"` To string `yaml:"to"` Reference string `yaml:"reference"` } type explanationView struct { Path string `yaml:"path"` Source string `yaml:"source"` Layer ck.Layer `yaml:"layer"` Derivations []derivationView `yaml:"derivations,omitempty"` Inheritance []inheritanceStepView `yaml:"inheritance,omitempty"` } // ExplanationYAML reports only origins and recorded resolution operations. // It intentionally excludes effective and historical values, including secrets. func ExplanationYAML(result *ck.Result[config.Config]) ([]byte, error) { if result == nil { return nil, fmt.Errorf("configuration result is unavailable") } metadata := result.Metadata() sources := make(map[string]string) for _, source := range result.Sources() { sources[source.ID] = source.Label } records := make([]explanationView, 0) paths := metadata.HistoricalPaths() for i, path := range paths { if path.String() == "" { continue } if i+1 < len(paths) && strings.HasPrefix(paths[i+1].String(), path.String()+"/") { continue } info, ok := metadata.Lookup(path) if !ok { continue } record := explanationView{Path: path.String(), Layer: info.Origin.Layer, Source: string(info.Origin.Layer)} for _, step := range info.Origin.Inheritance { record.Inheritance = append(record.Inheritance, inheritanceStepView{ From: step.From.String(), To: step.To.String(), Reference: step.Reference.String(), }) } if len(info.Origin.Locations) > 0 { if label := sources[info.Origin.Locations[0].SourceID]; label != "" { record.Source = label } } for _, change := range metadata.History(path) { if change.Origin.Layer != ck.LayerResolution { continue } for _, reason := range change.Reasons { derivation := derivationView{Operation: change.Origin.Operation, Reason: reason} for _, dependency := range change.Dependencies { derivation.Dependencies = append(derivation.Dependencies, dependency.String()) } record.Derivations = append(record.Derivations, derivation) } } records = append(records, record) } return yaml.Marshal(records) }