package engine import "gitea.maximumdirect.net/eric/ConfigKit/internal/document" // postDecodeOverrideContext carries the typed post-CLI state and detached // resolution views after the history builder has taken ownership of evidence. type postDecodeOverrideContext struct { decoded decodedConfiguration metadata Metadata resolution resolutionInput 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) applications := structuralHistoryApplications(input) var structuralOverlays []overlayRecord if input.inheritance != nil && input.composition != nil { structuralOverlays = input.composition.overlays metadata.historyBuilder.setScratch(input.composition.root) metadata.historyBuilder.observeSourceEvidence(input.composition.root, input.composition.origins, applications, structuralOverlays) metadata.historyBuilder.setScratch(input.composition.root) metadata.historyBuilder.observeInheritanceEvidence(input.inheritance.operations) } else if input.composition != nil { structuralOverlays = input.composition.overlays metadata.historyBuilder.setScratch(input.composition.root) metadata.historyBuilder.observeSourceEvidence(input.composition.root, input.composition.origins, applications, structuralOverlays) } else if len(applications) != 0 { metadata.historyBuilder.observeSourceEvidence(input.document, nil, applications, nil) } metadata.historyBuilder.observePreCLICheckpoint(before.final, before.origins) 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}), }) } if len(cliRecords) != 0 { metadata.fields = make(map[string]FieldInfo) collectFieldInfo(after.final, Path{}, after, metadata.fields) } if len(cliRecords) != 0 || len(postDecodeApps) != 0 { metadata.historyBuilder.setScratch(before.final) metadata.historyBuilder.observeCLIEvidence(postDecodeApps, cliRecords) } metadata.historyBuilder.observePostCLICheckpoint(after.final, after.origins) metadata.historyBuilder.prefixReady = true 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) finalizeEffectiveMetadataPaths(&metadata, assigned.final) return postDecodeOverrideContext{ decoded: after, metadata: metadata, resolution: resolution, referenceInput: documentWithMetadataLocations(assigned.final, metadata, input.document), } } 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 var introduced []historyPathOrigin if existing, ok := documentAtPathWithLookup(before.final, override.path, lookup); ok { displaced = affectedOverrideOrigins(existing, override.value, before.origins, override.path, new(mappingIndex)) } application := historyApplication{ layer: LayerCLI, path: override.path.clone(), value: override.value, origin: overlayOrigin(LayerCLI, location), } walkHistoryApplication(application, func(_, effective Path, node *document.Node) { introduced = append(introduced, historyPathOrigin{ path: effective, origin: sourceApplicationOrigin(application, node), sensitive: node.Sensitive, }) }) records = append(records, overlayRecord{change: Change{ Path: override.path.clone(), Origin: overlayOrigin(LayerCLI, location), Previous: previousOrigins(previous), }, displaced: displaced, introduced: introduced}) } 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 structuralHistoryApplications(input assembledInput) []historyApplication { if input.composition != nil { return input.composition.applications } if input.document == nil { return nil } return []historyApplication{{layer: LayerMain, value: 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 lookup *documentLookup fallbackLocation := func(path Path) (document.Location, bool) { if lookup == nil { lookup = buildDocumentLookup(fallbackRoot) } return nearestConcreteDocumentLocationWithLookup(fallbackRoot, path, lookup) } var visit func(*document.Node, Path) visit = func(node *document.Node, path Path) { if info, exists := metadata.effectiveField(path); exists { if location, ok := metadataFieldLocation(metadata, path, info.Origin); ok { node.Location = location } else if location, ok := fallbackLocation(path); ok { node.Location = location } } else if location, ok := fallbackLocation(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.effectiveField(childPath); exists { if location, ok := metadataFieldLocation(metadata, childPath, info.Origin); ok { entry.KeyLocation = location entry.ValueLocation = location } else if location, ok := fallbackLocation(childPath); ok { entry.KeyLocation = location entry.ValueLocation = location } } else if location, ok := fallbackLocation(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 nearestConcreteDocumentLocationWithLookup(root *document.Node, path Path, lookup *documentLookup) (document.Location, bool) { if root == nil || !path.valid() { return document.Location{}, false } current := root nearest := current.Location for _, segment := range path.segments { switch current.Kind { case document.Mapping: if segment.kind != pathSegmentKey { return nearest, locationKnown(nearest) } position := -1 if lookup != nil { position = lookup.find(current, segment.key) } else { for index, entry := range current.Mapping { if entry.Key == segment.key { position = index break } } } if position < 0 || position >= len(current.Mapping) { return nearest, locationKnown(nearest) } current = current.Mapping[position].Value case document.Sequence: if segment.kind != pathSegmentIndex || segment.index < 0 || segment.index >= len(current.Sequence) { return nearest, locationKnown(nearest) } current = current.Sequence[segment.index] default: return nearest, locationKnown(nearest) } if current == nil { return nearest, locationKnown(nearest) } nearest = current.Location } return nearest, locationKnown(nearest) } func metadataFieldLocation(metadata Metadata, path Path, origin Origin) (document.Location, bool) { if location, ok := latestOriginDocumentLocation(origin); ok { return location, true } if model := metadata.historyEvidence(); model != nil { location, ok := model.latestHistoricalLocation(path) if ok { return document.Location{SourceID: location.SourceID, Line: location.Line, Column: location.Column}, 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 }