package engine import "gitea.maximumdirect.net/eric/ConfigKit/internal/document" // postDecodeOverrideContext keeps the structural, typed pre-CLI, and effective // post-CLI views distinct while preparing the existing inspection machinery. type postDecodeOverrideContext struct { structuralInput *document.Node preCLI *document.Node preCLIOrigins map[string]Origin decoded decodedConfiguration metadata Metadata resolution resolutionInput sources []SourceInfo applications []historyApplication postDecodeApps []historyApplication referenceInput *document.Node } func preparePostDecodeOverrideContext(input assembledInput, before decodedConfiguration, assigned decodedOverrideResult) postDecodeOverrideContext { after := before after.value = assigned.value after.presence = cloneInputPresence(assigned.presence) after.origins = cloneOrigins(assigned.origins) after.final = document.Clone(assigned.final) metadata := metadataFromDecoded(before) cliRecords := overrideMetadataRecords(before, assigned.overrides) var structuralOverlays []overlayRecord if input.inheritance != nil && input.composition != nil { structuralOverlays = input.composition.overlays applyInheritanceMetadata(&metadata, input.composition.root, input.composition.origins, structuralOverlays, input.inheritance) } else if input.composition != nil { structuralOverlays = input.composition.overlays applyOverlayMetadata(&metadata, structuralOverlays) } if len(cliRecords) != 0 { metadata.fields = make(map[string]FieldInfo) collectFieldInfo(after.final, Path{}, after, metadata.fields) appendPostDecodeCLIHistory(&metadata, cliRecords) } sources := cloneSourceInfos(input.sources) knownSources := make(map[string]bool, len(sources)+len(assigned.overrides)) for _, source := range sources { knownSources[source.ID] = true } for _, override := range assigned.overrides { if !knownSources[override.source.ID] { sources = append(sources, cloneSourceInfo(override.source)) knownSources[override.source.ID] = true } } if input.versionState != nil { sources = sourceInfosWithVersionEvidence(sources, input.versionState.evidence, nil, true) } resolution := newResolutionInput(metadata, assigned.final, sources, input.contexts) applications := structuralHistoryApplications(input) var postDecodeApps []historyApplication for _, override := range assigned.overrides { postDecodeApps = append(postDecodeApps, historyApplication{ layer: LayerCLI, path: override.path.clone(), value: document.Clone(override.value), origin: overlayOrigin(LayerCLI, document.Location{SourceID: override.source.ID}), }) } allApplications := append(cloneHistoryApplications(applications), cloneHistoryApplications(postDecodeApps)...) finalizeMetadataPaths(&metadata, assigned.final, allApplications, input.document, before.final) return postDecodeOverrideContext{ structuralInput: document.Clone(input.document), preCLI: document.Clone(before.final), preCLIOrigins: cloneOrigins(before.origins), decoded: after, metadata: metadata, resolution: resolution, sources: sources, applications: applications, postDecodeApps: postDecodeApps, referenceInput: documentWithMetadataLocations(assigned.final, metadata, input.document), } } // Source history is already assembled, with inheritance projected at query time. // Reuse overlay event construction for CLI changes without reapplying displaced // source definitions after those later assignments. func appendPostDecodeCLIHistory(metadata *Metadata, records []overlayRecord) { cli := Metadata{fields: metadata.fields} applyOverlayMetadata(&cli, records) for pointer, history := range cli.history { for _, change := range history { if change.Origin.Layer == LayerCLI { appendInputChangeEvent(metadata.history, nil, pointer, change) } } } } func overrideMetadataRecords(before decodedConfiguration, overrides []preparedOverride) []overlayRecord { if len(overrides) == 0 { return nil } lookup := buildDocumentLookup(before.final) records := make([]overlayRecord, 0, len(overrides)) for _, override := range overrides { location := document.Location{SourceID: override.source.ID} previous := cloneOrigin(before.origins[override.path.String()]) var displaced []displacedDefinition if existing, ok := documentAtPathWithLookup(before.final, override.path, lookup); ok { displaced = affectedOverrideOrigins(existing, override.value, before.origins, override.path, new(mappingIndex)) } records = append(records, overlayRecord{change: Change{ Path: override.path.clone(), Origin: overlayOrigin(LayerCLI, location), Previous: previousOrigins(previous), }, displaced: displaced}) } return records } func affectedOverrideOrigins(existing, incoming *document.Node, origins map[string]Origin, path Path, index *mappingIndex) []displacedDefinition { var displaced []displacedDefinition collectAffectedOverrideOrigins(&displaced, existing, incoming, origins, path, index) return sortDisplacedDefinitions(displaced) } func collectAffectedOverrideOrigins(displaced *[]displacedDefinition, existing, incoming *document.Node, origins map[string]Origin, path Path, index *mappingIndex) { if existing.Kind != document.Mapping || incoming.Kind != document.Mapping { collectDisplacedOrigins(displaced, existing, origins, path, Origin{}) return } *displaced = append(*displaced, displacedDefinition{path: path.clone(), origin: cloneOrigin(origins[path.String()])}) for _, entry := range incoming.Mapping { position := index.find(existing, entry.Key) if position < 0 { continue } childPath := path.Key(entry.Key) childExisting := existing.Mapping[position].Value if childExisting.Kind == document.Mapping && entry.Value.Kind == document.Mapping { collectAffectedOverrideOrigins(displaced, childExisting, entry.Value, origins, childPath, index) } else { collectDisplacedOrigins(displaced, childExisting, origins, childPath, Origin{}) } } } func (context postDecodeOverrideContext) historyApplications() []historyApplication { applications := cloneHistoryApplications(context.applications) return append(applications, cloneHistoryApplications(context.postDecodeApps)...) } func structuralHistoryApplications(input assembledInput) []historyApplication { if input.composition != nil { return cloneHistoryApplications(input.composition.applications) } if input.document == nil { return nil } return []historyApplication{{layer: LayerBase, value: document.Clone(input.document)}} } // documentWithMetadataLocations attaches effective origin coordinates to a // canonical typed projection for secret and validation diagnostics. func documentWithMetadataLocations(root *document.Node, metadata Metadata, fallback ...*document.Node) *document.Node { located := document.Clone(root) if located == nil { return nil } var fallbackRoot *document.Node if len(fallback) != 0 { fallbackRoot = fallback[0] } var visit func(*document.Node, Path) visit = func(node *document.Node, path Path) { pointer := path.String() if info, exists := metadata.fields[pointer]; exists { if location, ok := metadataFieldLocation(metadata, pointer, info.Origin); ok { node.Location = location } else if location, ok := nearestDocumentLocation(fallbackRoot, path); ok { node.Location = location } } else if location, ok := nearestDocumentLocation(fallbackRoot, path); ok { node.Location = location } switch node.Kind { case document.Mapping: for index := range node.Mapping { entry := &node.Mapping[index] childPath := path.Key(entry.Key) if info, exists := metadata.fields[childPath.String()]; exists { if location, ok := metadataFieldLocation(metadata, childPath.String(), info.Origin); ok { entry.KeyLocation = location entry.ValueLocation = location } else if location, ok := nearestDocumentLocation(fallbackRoot, childPath); ok { entry.KeyLocation = location entry.ValueLocation = location } } else if location, ok := nearestDocumentLocation(fallbackRoot, childPath); ok { entry.KeyLocation = location entry.ValueLocation = location } visit(entry.Value, childPath) } case document.Sequence: for index, child := range node.Sequence { visit(child, path.Index(index)) } } } visit(located, Path{}) return located } func metadataFieldLocation(metadata Metadata, pointer string, origin Origin) (document.Location, bool) { if location, ok := latestOriginDocumentLocation(origin); ok { return location, true } for index := len(metadata.history[pointer]) - 1; index >= 0; index-- { change := metadata.history[pointer][index] if location, ok := latestOriginDocumentLocation(change.Origin); ok { return location, true } for prior := len(change.Previous) - 1; prior >= 0; prior-- { if location, ok := latestOriginDocumentLocation(change.Previous[prior]); ok { return location, true } } } return document.Location{}, false } func latestOriginDocumentLocation(origin Origin) (document.Location, bool) { if len(origin.Locations) == 0 { return document.Location{}, false } location := origin.Locations[len(origin.Locations)-1] return document.Location{SourceID: location.SourceID, Line: location.Line, Column: location.Column}, true }