Publish inspection through one frozen history model
This commit is contained in:
@@ -635,7 +635,10 @@ secret/diff integration tests.
|
||||
## Stage 14 — Publish One Frozen History Owner
|
||||
|
||||
Owners: `Inspection`, `prepareInspectionHistory`, `publishLoadResult`,
|
||||
`Inspection.Metadata`, cloning and lookup setup. Status: pending.
|
||||
`Inspection.Metadata`, cloning and lookup setup. Status: complete. Validation:
|
||||
`GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -run 'Detached|Independent|ConcurrentReadOnly|History|Explain' -count=1`,
|
||||
`GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test -race ./internal/engine -run 'Detached|Independent|ConcurrentReadOnly|History|Explain' -count=1`,
|
||||
`GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./...`, and `git diff --check`.
|
||||
|
||||
1. Finish the model before publication, with eager indexes and final observations.
|
||||
Attach the same frozen owner to inspection and metadata. Remove independent
|
||||
|
||||
@@ -34,11 +34,11 @@ func prepareDiffRegions(left, right *Inspection) ([]diffRegion, error) {
|
||||
deltas := compareConfigurationValues(left.final, right.final)
|
||||
regions := make([]diffRegion, 0, len(deltas))
|
||||
for _, delta := range deltas {
|
||||
leftNode, leftPresent := documentAtPathWithLookup(left.final, delta.path, left.immutableLookup)
|
||||
leftNode, leftPresent := documentAtPathWithLookup(left.final, delta.path, left.documentLookup())
|
||||
if !leftPresent {
|
||||
leftNode = nil
|
||||
}
|
||||
rightNode, rightPresent := documentAtPathWithLookup(right.final, delta.path, right.immutableLookup)
|
||||
rightNode, rightPresent := documentAtPathWithLookup(right.final, delta.path, right.documentLookup())
|
||||
if !rightPresent {
|
||||
rightNode = nil
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestDiffUsesFinalValuesAndDependencyDerivedSensitivity(t *testing.T) {
|
||||
!right.Inspection.secrets["/credential"] || !right.Inspection.secrets["/derived"] {
|
||||
t.Fatalf("typed or dependency-derived sensitivity was not retained: left=%#v right=%#v", left.Inspection.secrets, right.Inspection.secrets)
|
||||
}
|
||||
if node, present := documentAtPathWithLookup(left.Inspection.final, Keys("derived"), left.Inspection.immutableLookup); !present || node.Text != "before" {
|
||||
if node, present := documentAtPathWithLookup(left.Inspection.final, Keys("derived"), left.Inspection.documentLookup()); !present || node.Text != "before" {
|
||||
t.Fatalf("left frozen derived value = %#v, present=%v", node, present)
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ func TestDiffUsesReferenceNamesAndFrozenSecretState(t *testing.T) {
|
||||
if err != nil || len(differences) != 0 {
|
||||
t.Fatalf("credential rotation behind one reference = %#v, err = %v", differences, err)
|
||||
}
|
||||
if node, present := documentAtPathWithLookup(left.Inspection.final, Keys("optional"), left.Inspection.immutableLookup); !present || node.Text != "DIFF_ROTATING_SECRET" {
|
||||
if node, present := documentAtPathWithLookup(left.Inspection.final, Keys("optional"), left.Inspection.documentLookup()); !present || node.Text != "DIFF_ROTATING_SECRET" {
|
||||
t.Fatalf("frozen reference = %#v, present=%v", node, present)
|
||||
}
|
||||
if node, present := documentAtPathWithLookup(right.Inspection.final, Keys("optional"), right.Inspection.immutableLookup); !present || node.Text != "DIFF_ROTATING_SECRET" {
|
||||
if node, present := documentAtPathWithLookup(right.Inspection.final, Keys("optional"), right.Inspection.documentLookup()); !present || node.Text != "DIFF_ROTATING_SECRET" {
|
||||
t.Fatalf("right frozen reference = %#v, present=%v", node, present)
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ func TestDiffUsesReferenceNamesAndFrozenSecretState(t *testing.T) {
|
||||
if absent.Config.Optional != nil {
|
||||
t.Fatalf("missing optional reference decoded as %#v", absent.Config.Optional)
|
||||
}
|
||||
if node, present := documentAtPathWithLookup(absent.Inspection.final, Keys("optional"), absent.Inspection.immutableLookup); !present || node.Kind != document.Null {
|
||||
if node, present := documentAtPathWithLookup(absent.Inspection.final, Keys("optional"), absent.Inspection.documentLookup()); !present || node.Kind != document.Null {
|
||||
t.Fatalf("optional nil projection = %#v, present=%v", node, present)
|
||||
}
|
||||
differences, err = Diff(absent.Inspection, left.Inspection)
|
||||
@@ -210,7 +210,7 @@ func TestDiffProtectsHistoricalSensitiveRemovalAndReplacement(t *testing.T) {
|
||||
if !left.Inspection.secrets[secretPath.String()] {
|
||||
t.Fatal("removed historical selector was not retained")
|
||||
}
|
||||
if _, present := documentAtPathWithLookup(left.Inspection.final, secretPath, left.Inspection.immutableLookup); present {
|
||||
if _, present := documentAtPathWithLookup(left.Inspection.final, secretPath, left.Inspection.documentLookup()); present {
|
||||
t.Fatal("removed token remains in the effective left tree")
|
||||
}
|
||||
differences, err := Diff(left.Inspection, right.Inspection)
|
||||
|
||||
@@ -127,7 +127,10 @@ type expectedDiffRegion struct {
|
||||
}
|
||||
|
||||
func diffTestInspection(root *document.Node) *Inspection {
|
||||
return &Inspection{final: root, immutableLookup: buildDocumentLookup(root)}
|
||||
builder := newHistoryBuilder()
|
||||
builder.model.final = root
|
||||
model := builder.freeze()
|
||||
return &Inspection{final: root, history: model, metadata: Metadata{historyModel: model}}
|
||||
}
|
||||
|
||||
func assertDiffRegionNode(t *testing.T, side string, node *document.Node, wantPresent bool, wantKind document.Kind) {
|
||||
|
||||
@@ -40,7 +40,7 @@ func (r *Inspection) Explain(path Path) (Explanation, bool) {
|
||||
if r == nil || r.final == nil || !path.valid() {
|
||||
return Explanation{}, false
|
||||
}
|
||||
model := r.metadata.historyModel
|
||||
model := r.history
|
||||
if model == nil {
|
||||
return Explanation{}, false
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func (r *Inspection) Explain(path Path) (Explanation, bool) {
|
||||
if len(selections) == 0 && !model.hasObservedShape(path) {
|
||||
return Explanation{}, false
|
||||
}
|
||||
explanation := Explanation{Path: path.clone(), Effective: valueSnapshotWithLookup(r.final, path, r.secrets, r.immutableLookup)}
|
||||
explanation := Explanation{Path: path.clone(), Effective: valueSnapshotWithLookup(r.final, path, r.secrets, model.documentLookup)}
|
||||
if info, ok := r.metadata.Lookup(path); ok {
|
||||
explanation.Origin = cloneOrigin(info.Origin)
|
||||
}
|
||||
|
||||
@@ -308,16 +308,28 @@ func TestSecretsBootstrapLoadAndExplanationRemainSeparateAndSafe(t *testing.T) {
|
||||
func TestHistoryNodeBudgetCountsSharedTreesOnce(t *testing.T) {
|
||||
leaf := &document.Node{Kind: document.String, Text: "value"}
|
||||
root := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{{Key: "value", Value: leaf}}}
|
||||
inspection := &Inspection{
|
||||
baseline: root, input: root, final: root,
|
||||
applications: []historyApplication{{layer: LayerBase, value: root}},
|
||||
}
|
||||
builder := newHistoryBuilder()
|
||||
builder.model.baseline = root
|
||||
builder.model.final = root
|
||||
builder.model.sourcePayloads = []historySourcePayload{{
|
||||
kind: historySourceApplicationPayload, application: historyApplication{layer: LayerBase, value: root},
|
||||
}}
|
||||
model := builder.freeze()
|
||||
inspection := &Inspection{history: model, metadata: Metadata{historyModel: model}, final: root}
|
||||
counter := newRetainedNodeCounter(2)
|
||||
if !addInspectionHistory(counter, inspection) || counter.count != 2 {
|
||||
t.Fatal("structurally shared history was counted more than once")
|
||||
}
|
||||
other := document.Clone(root)
|
||||
inspection.input = other
|
||||
builder = newHistoryBuilder()
|
||||
builder.model.baseline = root
|
||||
builder.model.final = root
|
||||
builder.model.sourcePayloads = []historySourcePayload{{
|
||||
kind: historySourceApplicationPayload, application: historyApplication{layer: LayerBase, value: other},
|
||||
}}
|
||||
model = builder.freeze()
|
||||
inspection.history = model
|
||||
inspection.metadata.historyModel = model
|
||||
counter = newRetainedNodeCounter(3)
|
||||
if addInspectionHistory(counter, inspection) {
|
||||
t.Fatal("distinct retained nodes did not consume the budget")
|
||||
@@ -425,7 +437,7 @@ func TestIntegerVersionInspectionRetainsInputAndReconcilesTypedValue(t *testing.
|
||||
if first.Config.Version != "4" || second.Config.Version != "4" {
|
||||
t.Fatalf("configurations = %#v / %#v", first.Config, second.Config)
|
||||
}
|
||||
inputVersion, inputOK := documentAtPath(first.applications[0].value, Keys("version"))
|
||||
inputVersion, inputOK := documentAtPath(first.history.sourcePayloads[0].application.value, Keys("version"))
|
||||
finalVersion, finalOK := documentAtPath(first.final, Keys("version"))
|
||||
if !inputOK || inputVersion.Kind != document.Number || inputVersion.Text != "4" ||
|
||||
!finalOK || finalVersion.Kind != document.String || finalVersion.Text != "4" {
|
||||
|
||||
@@ -85,36 +85,14 @@ func documentCloneNodeCount(root *document.Node, limit int) (int, bool) {
|
||||
}
|
||||
|
||||
func addInspectionHistory(counter *retainedNodeCounter, inspection *Inspection) bool {
|
||||
if inspection == nil {
|
||||
if inspection == nil || inspection.history == nil {
|
||||
return false
|
||||
}
|
||||
for _, root := range []*document.Node{inspection.baseline, inspection.input, inspection.final, inspection.preCLI} {
|
||||
for _, root := range inspection.history.documentRoots() {
|
||||
if !counter.add(root) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, application := range inspection.applications {
|
||||
if !counter.add(application.value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, application := range inspection.postDecodeApps {
|
||||
if !counter.add(application.value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, snapshot := range inspection.resolution {
|
||||
if !counter.add(snapshot.before) || !counter.add(snapshot.after) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, operations := range [][]inheritanceOperation{inspection.inheritance, inspection.metadata.inheritance} {
|
||||
for _, operation := range operations {
|
||||
if !counter.add(operation.parent) || !counter.add(operation.effective) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -22,21 +22,33 @@ type historyBudgetLayeredConfig struct {
|
||||
|
||||
func retainedInspectionNodeCountForTest(inspection *Inspection) int {
|
||||
seen := make(map[*document.Node]struct{})
|
||||
stack := []*document.Node{inspection.baseline, inspection.input, inspection.final, inspection.preCLI}
|
||||
for _, application := range inspection.applications {
|
||||
stack = append(stack, application.value)
|
||||
model := inspection.history
|
||||
stack := []*document.Node{model.baseline, model.final}
|
||||
for _, payload := range model.sourcePayloads {
|
||||
if payload.kind == historySourceApplicationPayload {
|
||||
stack = append(stack, payload.application.value)
|
||||
}
|
||||
}
|
||||
for _, application := range inspection.postDecodeApps {
|
||||
stack = append(stack, application.value)
|
||||
for _, payload := range model.inheritancePayloads {
|
||||
for _, operation := range payload.operations {
|
||||
stack = append(stack, operation.parent, operation.effective)
|
||||
}
|
||||
}
|
||||
for _, snapshot := range inspection.resolution {
|
||||
stack = append(stack, snapshot.before, snapshot.after)
|
||||
for _, payload := range model.cliPayloads {
|
||||
if payload.kind == historySourceApplicationPayload {
|
||||
stack = append(stack, payload.application.value)
|
||||
}
|
||||
}
|
||||
for _, operation := range inspection.inheritance {
|
||||
stack = append(stack, operation.parent, operation.effective)
|
||||
if model.preCLICheckpoint != nil {
|
||||
stack = append(stack, model.preCLICheckpoint.root)
|
||||
}
|
||||
for _, operation := range inspection.metadata.inheritance {
|
||||
stack = append(stack, operation.parent, operation.effective)
|
||||
if model.postCLICheckpoint != nil {
|
||||
stack = append(stack, model.postCLICheckpoint.root)
|
||||
}
|
||||
if model.resolutionPayload != nil {
|
||||
for _, snapshot := range model.resolutionPayload.snapshots {
|
||||
stack = append(stack, snapshot.before, snapshot.after)
|
||||
}
|
||||
}
|
||||
|
||||
for len(stack) != 0 {
|
||||
@@ -144,8 +156,8 @@ func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) {
|
||||
if want == 0 {
|
||||
t.Fatal("independent retained-tree count was empty")
|
||||
}
|
||||
if len(baseline.Inspection.inheritance) == 0 || len(baseline.Inspection.metadata.inheritance) == 0 {
|
||||
t.Fatal("layered load did not retain both inheritance evidence copies")
|
||||
if baseline.Inspection.history == nil || baseline.Inspection.metadata.historyModel != baseline.Inspection.history || len(baseline.Inspection.history.inheritancePayloads) == 0 {
|
||||
t.Fatal("layered load did not publish its shared inheritance evidence owner")
|
||||
}
|
||||
exactCounts := &callbackCounts{}
|
||||
loaded, err := loadGroupedWithSecretLookupLimit(makeRequest(exactCounts), testSecretBinding(), lookup(exactCounts), want)
|
||||
@@ -169,23 +181,46 @@ func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparedInheritanceEvidenceOwnsDistinctTrees(t *testing.T) {
|
||||
root := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{{Key: "value", Value: &document.Node{Kind: document.String, Text: "shared"}}}}
|
||||
resolved := resolvedLoad[historyBudgetSimpleConfig]{
|
||||
inheritance: &inheritanceScope{operations: []inheritanceOperation{{parent: root, effective: root}}},
|
||||
func TestPreparedInheritanceEvidenceSharesOwnerAndDetachesPublicViews(t *testing.T) {
|
||||
input := parseCompositionDocument(t, "inheritance", "parent: {value: shared}\nchild: {extends: parent}\n")
|
||||
expanded, diagnostics := expandInheritanceWithOrigins(input, nil, defaultProjectionLimits())
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatal(diagnostics)
|
||||
}
|
||||
counter := newRetainedNodeCounter(8)
|
||||
baseline := &document.Node{Kind: document.Mapping}
|
||||
builder := newHistoryBuilder()
|
||||
builder.observeBaseline(baseline)
|
||||
builder.setScratch(input)
|
||||
builder.observeInheritanceEvidence(expanded.operations)
|
||||
metadata := Metadata{historyBuilder: builder}
|
||||
resolved := resolvedLoad[historyBudgetSimpleConfig]{
|
||||
metadata: metadata, historyBuilder: builder, final: expanded.root,
|
||||
decoded: decodedConfiguration{baseline: baseline}, structuralInput: input,
|
||||
inheritance: expanded,
|
||||
}
|
||||
counter := newRetainedNodeCounter(100)
|
||||
inspection, ok := prepareInspectionHistory(resolved, counter)
|
||||
if !ok {
|
||||
t.Fatal("preparation rejected the exact size of the distinct retained copies")
|
||||
t.Fatal("preparation rejected the shared evidence owner")
|
||||
}
|
||||
if len(inspection.inheritance) != 1 || len(inspection.metadata.inheritance) != 1 {
|
||||
t.Fatalf("inheritance copies = inspection %#v, metadata %#v", inspection.inheritance, inspection.metadata.inheritance)
|
||||
if inspection.history == nil || inspection.metadata.historyModel != inspection.history || len(inspection.history.inheritancePayloads) != 1 {
|
||||
t.Fatalf("history owners = inspection %p, metadata %p, inheritance payloads %d", inspection.history, inspection.metadata.historyModel, len(inspection.history.inheritancePayloads))
|
||||
}
|
||||
inspectionOperation := inspection.inheritance[0]
|
||||
metadataOperation := inspection.metadata.inheritance[0]
|
||||
if inspectionOperation.parent == metadataOperation.parent || inspectionOperation.effective == metadataOperation.effective || counter.count != 8 {
|
||||
t.Fatalf("separate inheritance copies were not counted independently: inspection=(%p, %p) metadata=(%p, %p) count=%d", inspectionOperation.parent, inspectionOperation.effective, metadataOperation.parent, metadataOperation.effective, counter.count)
|
||||
path := Keys("child", "value")
|
||||
first := inspection.Metadata().History(path)
|
||||
if len(first) == 0 {
|
||||
t.Fatal("metadata projection omitted inherited history")
|
||||
}
|
||||
first[0].Origin.Locations[0].SourceID = "mutated metadata result"
|
||||
first[0].Dependencies[0].segments[0].key = "mutated metadata dependency"
|
||||
if explanation, found := inspection.Explain(path); !found || len(explanation.History) == 0 || explanation.History[0].Origin.Locations[0].SourceID == "mutated metadata result" {
|
||||
t.Fatalf("metadata result mutation leaked into explanation: %#v, %v", explanation, found)
|
||||
}
|
||||
explanation, _ := inspection.Explain(path)
|
||||
explanation.History[0].Origin.Locations[0].SourceID = "mutated explanation result"
|
||||
second := inspection.Metadata().History(path)
|
||||
if second[0].Origin.Locations[0].SourceID == "mutated explanation result" || second[0].Dependencies[0].String() == "/mutated metadata dependency" {
|
||||
t.Fatalf("explanation mutation leaked into metadata: %#v", second)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ type historyModel struct {
|
||||
attributions []historyAttribution
|
||||
baseline *document.Node
|
||||
final *document.Node
|
||||
inventoryRoots []*document.Node
|
||||
sourcePayloads []historySourcePayload
|
||||
inheritancePayloads []historyInheritancePayload
|
||||
cliPayloads []historySourcePayload
|
||||
@@ -149,20 +148,12 @@ func (builder *historyBuilder) observeDocumentAt(root *document.Node, prefix Pat
|
||||
if root == nil {
|
||||
return
|
||||
}
|
||||
builder.registerDocumentRoot(root)
|
||||
payload := builder.nextPayload(phase)
|
||||
walkDocument(root, prefix, func(path Path, node *document.Node) {
|
||||
builder.addInventoryObservation(path, path, payload, phase, node.Sensitive)
|
||||
})
|
||||
}
|
||||
|
||||
func (builder *historyBuilder) registerDocumentRoot(root *document.Node) {
|
||||
builder.requireOpen()
|
||||
if root != nil {
|
||||
builder.model.inventoryRoots = append(builder.model.inventoryRoots, root)
|
||||
}
|
||||
}
|
||||
|
||||
func (builder *historyBuilder) addInventoryObservation(path, reportedPath Path, payload historyPayloadRef, phase historyPhase, sensitive bool) int {
|
||||
return builder.addObservation(historyObservation{
|
||||
path: path, phase: phase, payload: payload,
|
||||
@@ -204,32 +195,40 @@ func (model *historyModel) documentRoots() []*document.Node {
|
||||
if model == nil {
|
||||
return nil
|
||||
}
|
||||
roots := append([]*document.Node(nil), model.inventoryRoots...)
|
||||
roots = append(roots, model.baseline, model.final)
|
||||
var roots []*document.Node
|
||||
appendRoot := func(root *document.Node) {
|
||||
if root != nil {
|
||||
roots = append(roots, root)
|
||||
}
|
||||
}
|
||||
appendRoot(model.baseline)
|
||||
appendRoot(model.final)
|
||||
for _, payload := range model.sourcePayloads {
|
||||
if payload.kind == historySourceApplicationPayload {
|
||||
roots = append(roots, payload.application.value)
|
||||
appendRoot(payload.application.value)
|
||||
}
|
||||
}
|
||||
for _, payload := range model.inheritancePayloads {
|
||||
for _, operation := range payload.operations {
|
||||
roots = append(roots, operation.parent, operation.effective)
|
||||
appendRoot(operation.parent)
|
||||
appendRoot(operation.effective)
|
||||
}
|
||||
}
|
||||
for _, payload := range model.cliPayloads {
|
||||
if payload.kind == historySourceApplicationPayload {
|
||||
roots = append(roots, payload.application.value)
|
||||
appendRoot(payload.application.value)
|
||||
}
|
||||
}
|
||||
if model.preCLICheckpoint != nil {
|
||||
roots = append(roots, model.preCLICheckpoint.root)
|
||||
appendRoot(model.preCLICheckpoint.root)
|
||||
}
|
||||
if model.postCLICheckpoint != nil {
|
||||
roots = append(roots, model.postCLICheckpoint.root)
|
||||
appendRoot(model.postCLICheckpoint.root)
|
||||
}
|
||||
if model.resolutionPayload != nil {
|
||||
for _, snapshot := range model.resolutionPayload.snapshots {
|
||||
roots = append(roots, snapshot.before, snapshot.after)
|
||||
appendRoot(snapshot.before)
|
||||
appendRoot(snapshot.after)
|
||||
}
|
||||
}
|
||||
return roots
|
||||
|
||||
@@ -156,7 +156,7 @@ func TestHistorySelectionMatchesDeepSidesOfAncestorShapeChange(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryModelFinalizesLocationSensitivityAndDocumentReaders(t *testing.T) {
|
||||
func TestHistoryModelFinalizesLocationAndSensitivityWithoutRetainingInventoryTrees(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := parseDocumentForDecode(t, "shape: {'0': {value: old}}\n")
|
||||
@@ -189,11 +189,11 @@ func TestHistoryModelFinalizesLocationSensitivityAndDocumentReaders(t *testing.T
|
||||
})
|
||||
model := builder.freeze()
|
||||
|
||||
if got := model.documentRoots(); len(got) == 0 || got[0] != root {
|
||||
t.Fatalf("document roots = %#v, want registered root", got)
|
||||
if got := model.documentRoots(); len(got) != 0 {
|
||||
t.Fatalf("inventory-only document was retained: %#v", got)
|
||||
}
|
||||
if got, ok := model.documentAt(root, Keys("shape", "0")); !ok || got.Kind != document.Mapping {
|
||||
t.Fatalf("indexed document lookup = %#v, %v", got, ok)
|
||||
if got, ok := model.documentAt(root, Keys("shape", "0")); ok || got != nil {
|
||||
t.Fatalf("lookup retained an inventory-only document = %#v, %v", got, ok)
|
||||
}
|
||||
if got, ok := model.latestHistoricalLocation(keyPath); !ok || got.SourceID != "base.yml" || got.Line != 4 || got.Column != 2 {
|
||||
t.Fatalf("latest historical location = %#v, %v", got, ok)
|
||||
@@ -213,9 +213,6 @@ func TestHistoryModelFinalizesLocationSensitivityAndDocumentReaders(t *testing.T
|
||||
if !sawCandidate {
|
||||
t.Fatal("sensitivity candidate omitted the concrete historical path")
|
||||
}
|
||||
if got, found := model.documentAt(root, Keys("shape", "missing")); found || got != nil {
|
||||
t.Fatalf("lookup for missing value = %#v, %v", got, found)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryBuilderScratchUsesOneDetachedWorkingDocument(t *testing.T) {
|
||||
|
||||
@@ -278,14 +278,13 @@ func TestProjectedSequenceHistoryAgreesAcrossMetadataAndExplanation(t *testing.T
|
||||
t.Fatalf("projected metadata omitted shifted path %s: %#v", path, metadata.HistoricalPaths())
|
||||
}
|
||||
|
||||
inspection := &Inspection{
|
||||
metadata: metadata, baseline: &document.Node{Kind: document.Mapping},
|
||||
input: composed.root, preCLI: composed.root, final: composed.root, applications: composed.applications,
|
||||
}
|
||||
inspection.metadata.historyModel = sourceHistoryModelForInspection(inspection.baseline, composed.root, composed.origins, composed.applications, composed.overlays)
|
||||
baseline := &document.Node{Kind: document.Mapping}
|
||||
model := sourceHistoryModelForInspection(baseline, composed.root, composed.origins, composed.applications, composed.overlays)
|
||||
metadata.historyModel = model
|
||||
inspection := &Inspection{metadata: metadata, history: model, final: composed.root}
|
||||
inspection.secrets = classifySecretPaths(nil, func(candidate Path) bool {
|
||||
return reflect.DeepEqual(candidate, path)
|
||||
}, metadata, composed.root, composed.applications)
|
||||
}, metadata, composed.root, nil)
|
||||
explanation, ok := inspection.Explain(path)
|
||||
if !ok || !explanation.Effective.Redacted {
|
||||
t.Fatalf("shifted explanation = %#v, %v", explanation, ok)
|
||||
@@ -326,14 +325,13 @@ func TestReplacedProjectedSensitiveRecordRemainsRedacted(t *testing.T) {
|
||||
path := Keys("records").Index(1).Key("token")
|
||||
var metadata Metadata
|
||||
finalizeMetadataPaths(&metadata, final, applications)
|
||||
inspection := &Inspection{
|
||||
metadata: metadata, baseline: &document.Node{Kind: document.Mapping},
|
||||
input: final, preCLI: final, final: final, applications: applications,
|
||||
}
|
||||
inspection.metadata.historyModel = sourceHistoryModelForInspection(inspection.baseline, final, nil, applications, nil)
|
||||
baseline := &document.Node{Kind: document.Mapping}
|
||||
model := sourceHistoryModelForInspection(baseline, final, nil, applications, nil)
|
||||
metadata.historyModel = model
|
||||
inspection := &Inspection{metadata: metadata, history: model, final: final}
|
||||
inspection.secrets = classifySecretPaths(nil, func(candidate Path) bool {
|
||||
return reflect.DeepEqual(candidate, path)
|
||||
}, metadata, final, applications)
|
||||
}, metadata, final, nil)
|
||||
explanation, ok := inspection.Explain(path)
|
||||
if !ok || explanation.Effective.Present {
|
||||
t.Fatalf("replaced shifted record explanation = %#v, %v", explanation, ok)
|
||||
@@ -353,7 +351,6 @@ func sourceHistoryModelForInspection(baseline, final *document.Node, origins map
|
||||
builder.setScratch(baseline)
|
||||
builder.observeSourceEvidence(final, origins, applications, records)
|
||||
builder.model.final = final
|
||||
builder.registerDocumentRoot(final)
|
||||
return builder.freeze()
|
||||
}
|
||||
|
||||
@@ -409,12 +406,12 @@ func TestMappedUpsertProjectsSensitiveReplacementEvidence(t *testing.T) {
|
||||
|
||||
var metadata Metadata
|
||||
finalizeMetadataPaths(&metadata, finalRoot, applications)
|
||||
inspection := &Inspection{
|
||||
metadata: metadata, baseline: &document.Node{Kind: document.Mapping},
|
||||
input: finalRoot, preCLI: finalRoot, final: finalRoot, applications: applications,
|
||||
}
|
||||
baseline := &document.Node{Kind: document.Mapping}
|
||||
model := sourceHistoryModelForInspection(baseline, finalRoot, nil, applications, nil)
|
||||
metadata.historyModel = model
|
||||
inspection := &Inspection{metadata: metadata, history: model, final: finalRoot}
|
||||
secretRule := func(candidate Path) bool { return reflect.DeepEqual(candidate, secretPath) }
|
||||
inspection.secrets = classifySecretPaths(nil, secretRule, metadata, finalRoot, applications)
|
||||
inspection.secrets = classifySecretPaths(nil, secretRule, metadata, finalRoot, nil)
|
||||
explanation, ok := inspection.Explain(secretPath)
|
||||
if !ok || !explanation.Effective.Redacted {
|
||||
t.Fatalf("mapped replacement explanation = %#v, %v", explanation, ok)
|
||||
|
||||
@@ -35,7 +35,6 @@ func (builder *historyBuilder) observeBaseline(root *document.Node) {
|
||||
return
|
||||
}
|
||||
builder.model.baseline = root
|
||||
builder.registerDocumentRoot(root)
|
||||
payload := builder.nextPayload(historyPhaseBaseline)
|
||||
defaultAttribution := builder.addAttribution(Origin{Layer: LayerDefault}, nil, nil)
|
||||
walkDocument(root, Path{}, func(path Path, node *document.Node) {
|
||||
|
||||
@@ -41,7 +41,6 @@ func TestHistorySourceObservationsPreserveRawAndCompositeDefinitions(t *testing.
|
||||
builder.observeBaseline(baseline)
|
||||
builder.observeSourceEvidence(assembly.current.root, assembly.current.origins, assembly.current.applications, assembly.current.overlays)
|
||||
builder.model.final = assembly.current.root
|
||||
builder.registerDocumentRoot(assembly.current.root)
|
||||
model := builder.freeze()
|
||||
|
||||
defaultPath := Keys("defaults", "nullable")
|
||||
@@ -99,8 +98,7 @@ func TestHistorySourceObservationsPreserveRawAndCompositeDefinitions(t *testing.
|
||||
}
|
||||
}
|
||||
inspection := &Inspection{
|
||||
metadata: metadata, baseline: baseline, final: assembly.current.root,
|
||||
immutableLookup: buildDocumentLookup(assembly.current.root),
|
||||
metadata: metadata, history: model, final: assembly.current.root,
|
||||
}
|
||||
explanation, explained := inspection.Explain(Keys("section", "empty"))
|
||||
var contributionSources []string
|
||||
|
||||
@@ -128,12 +128,18 @@ func inheritanceInspectionFromComposition(t *testing.T, composed *composedDocume
|
||||
applyInheritanceMetadata(&metadata, composed.root, composed.origins, composed.overlays, expanded)
|
||||
metadata.historyBuilder.setScratch(composed.root)
|
||||
metadata.historyBuilder.observeInheritanceEvidence(expanded.operations)
|
||||
metadata.inheritance = cloneInheritanceOperations(expanded.operations)
|
||||
finalizeMetadataPathsWithResolution(&metadata, expanded.root, composed.applications, snapshots, baseline, composed.root, expanded.root)
|
||||
final := expanded.root
|
||||
if len(snapshots) != 0 {
|
||||
final = document.Clone(expanded.root)
|
||||
for _, group := range coalescedResolutionSnapshots(snapshots) {
|
||||
if group.coveringRecordID >= 0 && group.coveringRecordID < len(snapshots) {
|
||||
replaceHistoryPath(&final, group.change.Path, snapshots[group.coveringRecordID].after)
|
||||
}
|
||||
}
|
||||
}
|
||||
finalizeMetadataPathsWithResolution(&metadata, final, composed.applications, snapshots, baseline, composed.root, expanded.root)
|
||||
return &Inspection{
|
||||
metadata: metadata, baseline: baseline, input: expanded.root, preCLI: expanded.root,
|
||||
inputOrigins: expanded.origins, final: expanded.root,
|
||||
applications: composed.applications, inheritance: expanded.operations,
|
||||
metadata: metadata, history: metadata.historyModel, final: final,
|
||||
}, expanded
|
||||
}
|
||||
|
||||
@@ -323,8 +329,8 @@ func TestIndexedInheritanceHistoryMatchesOperationScan(t *testing.T) {
|
||||
parseCompositionDocument(t, "source-2", "child: {extends: parent, branch: replaced}\n"),
|
||||
parseCompositionDocument(t, "source-3", "sibling: {extends: parent}\n"))
|
||||
metadata := inspection.Metadata()
|
||||
if len(metadata.inheritance) < 4 {
|
||||
t.Fatalf("inheritance operations = %d, want multiple control and transfer scopes", len(metadata.inheritance))
|
||||
if inspection.history == nil || len(inspection.history.inheritancePayloads) == 0 || len(inspection.history.inheritancePayloads[0].operations) < 4 {
|
||||
t.Fatalf("inheritance operations = %#v, want multiple control and transfer scopes", inspection.history)
|
||||
}
|
||||
queries := []Path{
|
||||
Keys("child"),
|
||||
@@ -372,11 +378,6 @@ func TestInheritanceHistoryPrecedesApplicationResolution(t *testing.T) {
|
||||
after: replacement,
|
||||
}
|
||||
inspection, _ := inheritanceInspectionFromComposition(t, composed, snapshot)
|
||||
final := document.Clone(inspection.final)
|
||||
replaceHistoryPath(&final, path, replacement)
|
||||
inspection.final = final
|
||||
inspection.resolution = []resolutionSnapshot{snapshot}
|
||||
inspection.resolutionReplay = coalescedResolutionSnapshots(inspection.resolution)
|
||||
inspection.metadata.fields[path.String()] = FieldInfo{Explicit: true, Origin: snapshot.change.Origin}
|
||||
history := inspection.Metadata().History(path)
|
||||
if len(history) < 2 || history[len(history)-2].Origin.Operation != ChangeInheritance ||
|
||||
@@ -390,17 +391,24 @@ func TestInheritanceHistoryPrecedesApplicationResolution(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryNodeBudgetCountsSharedInheritanceEvidenceOnce(t *testing.T) {
|
||||
func TestHistoryNodeBudgetCountsSharedInheritanceRootsOnce(t *testing.T) {
|
||||
shared := &document.Node{Kind: document.String, Text: "shared"}
|
||||
extra := &document.Node{Kind: document.String, Text: "extra"}
|
||||
inspection := &Inspection{
|
||||
inheritance: []inheritanceOperation{{parent: shared, effective: shared}},
|
||||
metadata: Metadata{inheritance: []inheritanceOperation{{parent: shared, effective: extra}}},
|
||||
}
|
||||
operation := inheritanceOperation{parent: shared, effective: shared}
|
||||
builder := newHistoryBuilder()
|
||||
builder.observeInheritanceEvidence([]inheritanceOperation{operation})
|
||||
model := builder.freeze()
|
||||
inspection := &Inspection{history: model, metadata: Metadata{historyModel: model}}
|
||||
counter := newRetainedNodeCounter(2)
|
||||
if !addInspectionHistory(counter, inspection) || counter.count != 2 {
|
||||
t.Fatal("shared evidence node accounting is incorrect")
|
||||
}
|
||||
operation.effective = extra
|
||||
builder = newHistoryBuilder()
|
||||
builder.observeInheritanceEvidence([]inheritanceOperation{operation})
|
||||
model = builder.freeze()
|
||||
inspection.history = model
|
||||
inspection.metadata.historyModel = model
|
||||
counter = newRetainedNodeCounter(1)
|
||||
if addInspectionHistory(counter, inspection) {
|
||||
t.Fatal("distinct inheritance evidence did not consume the budget")
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestInheritanceSensitivityFollowsCopiesWithoutMaskingNeighbors(t *testing.T
|
||||
inspection, _ := inheritanceInspectionForTest(t, input)
|
||||
inspection.secrets = classifySecretPaths(nil, func(path Path) bool {
|
||||
return path.String() == classified.String()
|
||||
}, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
||||
}, inspection.metadata, inspection.final, nil)
|
||||
for _, path := range []Path{Keys("parent", "token"), Keys("child", "token"), Keys("next", "token"), Keys("other", "token")} {
|
||||
explanation, found := inspection.Explain(path)
|
||||
if !found || !explanation.Effective.Redacted || strings.Contains(explanation.Effective.YAML, canary) {
|
||||
@@ -44,7 +44,7 @@ func TestInheritanceSensitivityPreservesDisplacedHistoryAndControl(t *testing.T)
|
||||
inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {branch: {token: "+canary+"}}\nchild: {extends: parent, branch: public}\n"))
|
||||
inspection.secrets = classifySecretPaths(nil, func(path Path) bool {
|
||||
return path.String() == Keys("parent", "branch", "token").String() || path.String() == Keys("child", inheritanceKey).String()
|
||||
}, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
||||
}, inspection.metadata, inspection.final, nil)
|
||||
path := Keys("child", "branch", "token")
|
||||
explanation, found := inspection.Explain(path)
|
||||
if !found || explanation.Effective.Present {
|
||||
@@ -85,7 +85,7 @@ func TestInheritanceSensitivityIncludesSchemaTaggedSource(t *testing.T) {
|
||||
t.Fatal(issue)
|
||||
}
|
||||
inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {token: TAGGED-CANARY}\nchild: {extends: parent}\n"))
|
||||
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
||||
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, nil)
|
||||
child, found := inspection.Explain(Keys("child", "token"))
|
||||
if !found || !child.Effective.Redacted || strings.Contains(child.Effective.YAML, "TAGGED-CANARY") {
|
||||
t.Fatalf("tagged source copy = %#v, %v", child, found)
|
||||
@@ -104,7 +104,7 @@ func TestSourceVersionEvidenceSensitivityFollowsInheritanceAndDisplacedHistory(t
|
||||
}
|
||||
inspection.secrets = classifySecretPathsWithEvidence(nil, func(path Path) bool {
|
||||
return path.String() == secretPath.String()
|
||||
}, inspection.metadata, inspection.final, inspection.applications, []*sourceVersionEvidence{evidence}, inspection.input)
|
||||
}, inspection.metadata, inspection.final, nil, []*sourceVersionEvidence{evidence})
|
||||
|
||||
path := Keys("child", "branch", "token")
|
||||
explanation, found := inspection.Explain(path)
|
||||
@@ -162,7 +162,7 @@ func TestInheritedSecretReferencesResolveOnlyAfterExpansion(t *testing.T) {
|
||||
t.Fatalf("inherited reference resolution = %#v, %d", resolved.diagnostics, lookupCount)
|
||||
}
|
||||
inspection, _ := inheritanceInspectionFromComposition(t, composed)
|
||||
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
||||
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, nil)
|
||||
var rendered bytes.Buffer
|
||||
if err := inspection.WriteEffective(&rendered); err != nil || strings.Contains(rendered.String(), "RESOLVED-CREDENTIAL-CANARY") {
|
||||
t.Fatalf("reference rendering = %q, %v", rendered.String(), err)
|
||||
|
||||
@@ -87,25 +87,22 @@ type Loaded[T any] struct {
|
||||
// Inspection owns frozen load snapshots and detached query state.
|
||||
type Inspection struct {
|
||||
metadata Metadata
|
||||
history *historyModel
|
||||
sources []SourceInfo
|
||||
contexts map[string]ResourceContext
|
||||
diagnostics []Diagnostic
|
||||
baseline *document.Node
|
||||
input *document.Node
|
||||
inputOrigins map[string]Origin
|
||||
preCLI *document.Node
|
||||
preCLIOrigins map[string]Origin
|
||||
postDecodeApps []historyApplication
|
||||
final *document.Node
|
||||
immutableLookup *documentLookup
|
||||
resolution []resolutionSnapshot
|
||||
resolutionReplay []resolutionReplayGroup
|
||||
applications []historyApplication
|
||||
inheritance []inheritanceOperation
|
||||
secrets map[string]bool
|
||||
secretReferences map[string]string
|
||||
}
|
||||
|
||||
func (r *Inspection) documentLookup() *documentLookup {
|
||||
if r == nil || r.history == nil {
|
||||
return nil
|
||||
}
|
||||
return r.history.documentLookup
|
||||
}
|
||||
|
||||
// Metadata returns detached effective presence, origin, and history records.
|
||||
func (r *Inspection) Metadata() Metadata {
|
||||
if r == nil {
|
||||
@@ -321,14 +318,6 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
||||
accumulator.add(Diagnostic{Code: CodeExplainLimitExceeded, Severity: SeverityError, Message: "retained configuration history exceeds the node limit"})
|
||||
return nil, accumulator.loadError()
|
||||
}
|
||||
historyApplications := make([]historyApplication, 0, len(inspection.applications)+len(inspection.postDecodeApps))
|
||||
historyApplications = append(historyApplications, inspection.applications...)
|
||||
historyApplications = append(historyApplications, inspection.postDecodeApps...)
|
||||
if !addInspectionHistory(counter, inspection) {
|
||||
accumulator.add(Diagnostic{Code: CodeExplainLimitExceeded, Severity: SeverityError, Message: "retained configuration history exceeds the node limit"})
|
||||
return nil, accumulator.loadError()
|
||||
}
|
||||
|
||||
// Detach resolver-borrowed values before reference mutation or validation.
|
||||
configuration, ownershipIssue := detachLoadConfiguration(schema, resolved.configuration, cloneUnresolvedSecrets)
|
||||
if ownershipIssue != nil {
|
||||
@@ -355,5 +344,5 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
||||
resolved.configuration = configuration
|
||||
// Publication detaches equal-valued validator replacements, preserving the
|
||||
// validated secret state, then finalizes metadata and sensitivity.
|
||||
return publishLoadResult(schema, request.definition, resolved, inspection, historyApplications, secretResolution.references, &accumulator)
|
||||
return publishLoadResult(schema, request.definition, resolved, inspection, secretResolution.references, &accumulator)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ func resolveLoadInput[T any](schema *schemaDescriptor, definition Definition[T],
|
||||
}
|
||||
if builder != nil {
|
||||
builder.model.final = final
|
||||
builder.registerDocumentRoot(final)
|
||||
}
|
||||
if refreshReferenceInput {
|
||||
referenceInput = documentWithMetadataLocations(final, metadata, input.document)
|
||||
@@ -120,44 +119,24 @@ func prepareInspectionHistory[T any](resolved resolvedLoad[T], counter *retained
|
||||
metadata := resolved.metadata
|
||||
if resolved.historyBuilder != nil {
|
||||
metadata.historyBuilder = resolved.historyBuilder
|
||||
} else if resolved.inheritance != nil {
|
||||
builder := newHistoryBuilder()
|
||||
if resolved.decoded.baseline != nil {
|
||||
builder.observeBaseline(resolved.decoded.baseline)
|
||||
}
|
||||
builder.setScratch(resolved.final)
|
||||
builder.observeInheritanceEvidence(resolved.inheritance.operations)
|
||||
metadata.historyBuilder = builder
|
||||
}
|
||||
metadata.inheritance = nil
|
||||
finalizeMetadataPathsWithResolution(
|
||||
&metadata, resolved.final, resolved.applications, resolved.snapshots,
|
||||
resolved.decoded.baseline, resolved.structuralInput, resolved.preCLI, resolved.decoded.final,
|
||||
)
|
||||
model := metadata.historyModel
|
||||
inspection := &Inspection{
|
||||
metadata: metadata,
|
||||
baseline: resolved.decoded.baseline,
|
||||
input: resolved.decoded.final,
|
||||
inputOrigins: cloneOriginIndex(resolved.decoded.origins),
|
||||
preCLI: resolved.preCLI,
|
||||
preCLIOrigins: cloneOrigins(resolved.preCLIOrigins),
|
||||
final: resolved.final,
|
||||
resolution: resolved.snapshots,
|
||||
resolutionReplay: coalescedResolutionSnapshots(resolved.snapshots),
|
||||
}
|
||||
if !addInspectionHistory(counter, inspection) {
|
||||
return nil, false
|
||||
}
|
||||
var ok bool
|
||||
inspection.applications, ok = cloneHistoryApplicationsWithinLimit(resolved.applications, counter)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
inspection.postDecodeApps, ok = cloneHistoryApplicationsWithinLimit(resolved.postDecodeApps, counter)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if resolved.inheritance != nil {
|
||||
roots := inheritanceOperationDocumentRoots(resolved.inheritance.operations)
|
||||
if !counter.canAddClones(roots, 2) {
|
||||
return nil, false
|
||||
}
|
||||
inspection.metadata.inheritance = cloneInheritanceOperations(resolved.inheritance.operations)
|
||||
if !addInheritanceOperationDocuments(counter, inspection.metadata.inheritance) {
|
||||
return nil, false
|
||||
}
|
||||
inspection.inheritance = cloneInheritanceOperations(resolved.inheritance.operations)
|
||||
if !addInheritanceOperationDocuments(counter, inspection.inheritance) {
|
||||
return nil, false
|
||||
}
|
||||
metadata: metadata,
|
||||
history: model,
|
||||
final: resolved.final,
|
||||
}
|
||||
if !addInspectionHistory(counter, inspection) {
|
||||
return nil, false
|
||||
@@ -165,33 +144,7 @@ func prepareInspectionHistory[T any](resolved resolvedLoad[T], counter *retained
|
||||
return inspection, true
|
||||
}
|
||||
|
||||
func cloneHistoryApplicationsWithinLimit(values []historyApplication, counter *retainedNodeCounter) ([]historyApplication, bool) {
|
||||
for _, value := range values {
|
||||
if !counter.add(value.value) {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return cloneHistoryApplications(values), true
|
||||
}
|
||||
|
||||
func inheritanceOperationDocumentRoots(operations []inheritanceOperation) []*document.Node {
|
||||
roots := make([]*document.Node, 0, len(operations)*2)
|
||||
for _, operation := range operations {
|
||||
roots = append(roots, operation.parent, operation.effective)
|
||||
}
|
||||
return roots
|
||||
}
|
||||
|
||||
func addInheritanceOperationDocuments(counter *retainedNodeCounter, operations []inheritanceOperation) bool {
|
||||
for _, operation := range operations {
|
||||
if !counter.add(operation.parent) || !counter.add(operation.effective) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func publishLoadResult[T any](schema *schemaDescriptor, definition Definition[T], resolved resolvedLoad[T], inspection *Inspection, applications []historyApplication, references map[string]string, accumulator *diagnosticAccumulator) (*Loaded[T], error) {
|
||||
func publishLoadResult[T any](schema *schemaDescriptor, definition Definition[T], resolved resolvedLoad[T], inspection *Inspection, references map[string]string, accumulator *diagnosticAccumulator) (*Loaded[T], error) {
|
||||
// A read-only validator can replace a value with an equal borrowed object.
|
||||
// Detach without re-reading the environment or discarding validated state.
|
||||
configuration, issue := detachLoadConfiguration(schema, resolved.configuration, cloneValidatedSecrets)
|
||||
@@ -199,21 +152,13 @@ func publishLoadResult[T any](schema *schemaDescriptor, definition Definition[T]
|
||||
accumulator.add(*issue)
|
||||
return nil, accumulator.loadError()
|
||||
}
|
||||
decoded := resolved.decoded
|
||||
metadata, final, preCLI := inspection.metadata, inspection.final, inspection.preCLI
|
||||
finalizeMetadataPathsWithResolution(&metadata, final, applications, resolved.snapshots, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
||||
secrets := classifySecretPathsWithEvidence(schema, definition.Secret, metadata, final, applications, resolved.versionEvidence, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
||||
metadata, final := inspection.metadata, inspection.final
|
||||
secrets := classifySecretPathsWithEvidence(schema, definition.Secret, metadata, final, nil, resolved.versionEvidence)
|
||||
sources := sourceInfosWithVersionEvidence(accumulator.sources, resolved.versionEvidence, secrets, false)
|
||||
retainedTrees := make([]*document.Node, 0, len(applications)+4)
|
||||
retainedTrees = append(retainedTrees, decoded.final, final, preCLI)
|
||||
for _, application := range applications {
|
||||
retainedTrees = append(retainedTrees, application.value)
|
||||
}
|
||||
inspection.metadata = metadata
|
||||
inspection.sources = sources
|
||||
inspection.contexts = cloneResourceContexts(resolved.contexts)
|
||||
inspection.diagnostics = canonicalDiagnostics(accumulator.diagnostics)
|
||||
inspection.immutableLookup = buildDocumentLookup(retainedTrees...)
|
||||
inspection.secrets = secrets
|
||||
inspection.secretReferences = cloneSecretReferences(references)
|
||||
return &Loaded[T]{Config: configuration, Inspection: inspection}, nil
|
||||
|
||||
@@ -171,7 +171,6 @@ func finalizeMetadataPathsWithResolution(m *Metadata, final *document.Node, appl
|
||||
}
|
||||
if builder.model.final != final {
|
||||
builder.model.final = final
|
||||
builder.registerDocumentRoot(final)
|
||||
}
|
||||
m.historyModel = builder.freeze()
|
||||
m.historyBuilder = nil
|
||||
@@ -200,7 +199,6 @@ func finalizeMetadataPathsWithResolution(m *Metadata, final *document.Node, appl
|
||||
builder.observeDocument(final, historyPhasePostCLI)
|
||||
}
|
||||
for _, application := range applications {
|
||||
builder.registerDocumentRoot(application.value)
|
||||
phase := historyPhaseSources
|
||||
if application.layer == LayerCLI {
|
||||
phase = historyPhaseCLI
|
||||
@@ -219,8 +217,6 @@ func finalizeMetadataPathsWithResolution(m *Metadata, final *document.Node, appl
|
||||
if operation.transfer == nil {
|
||||
continue
|
||||
}
|
||||
builder.registerDocumentRoot(operation.parent)
|
||||
builder.registerDocumentRoot(operation.effective)
|
||||
for _, root := range []*document.Node{operation.parent, operation.effective} {
|
||||
walkDocument(root, operation.transfer.to, func(path Path, node *document.Node) {
|
||||
builder.addInventoryObservation(path, path, payload, historyPhaseInheritance, node.Sensitive)
|
||||
|
||||
@@ -117,13 +117,7 @@ func TestPostDecodeOverrideContextOrdersDecodeCLIAndResolutionEvidence(t *testin
|
||||
|
||||
finalizeMetadataPaths(&prepared.metadata, assigned.final, prepared.historyApplications(), decoded.baseline, prepared.structuralInput, prepared.preCLI, assigned.final)
|
||||
inspection := Inspection{
|
||||
metadata: prepared.metadata, baseline: decoded.baseline, input: assigned.final, inputOrigins: assigned.origins,
|
||||
preCLI: prepared.preCLI, preCLIOrigins: prepared.preCLIOrigins,
|
||||
postDecodeApps: prepared.postDecodeApps, final: assigned.final,
|
||||
applications: prepared.applications,
|
||||
immutableLookup: buildDocumentLookup(prepared.preCLI, assigned.final,
|
||||
prepared.applications[0].value, prepared.postDecodeApps[0].value, prepared.postDecodeApps[1].value,
|
||||
prepared.postDecodeApps[2].value, prepared.postDecodeApps[3].value),
|
||||
metadata: prepared.metadata, history: prepared.metadata.historyModel, final: assigned.final,
|
||||
}
|
||||
rateExplanation, ok := inspection.Explain(Keys("rate"))
|
||||
if !ok {
|
||||
|
||||
@@ -76,8 +76,9 @@ func TestLoadRunsRecordedResolutionWithMapWriteback(t *testing.T) {
|
||||
"/artifacts/first/output", "/artifacts/first/timeout",
|
||||
"/artifacts/second/output", "/artifacts/second/timeout", "/timeout",
|
||||
}
|
||||
gotOrder := make([]string, len(result.resolution))
|
||||
for index, snapshot := range result.resolution {
|
||||
snapshots := result.history.resolutionPayload.snapshots
|
||||
gotOrder := make([]string, len(snapshots))
|
||||
for index, snapshot := range snapshots {
|
||||
gotOrder[index] = snapshot.change.Path.String()
|
||||
}
|
||||
if !reflect.DeepEqual(gotOrder, wantOrder) {
|
||||
@@ -179,11 +180,12 @@ func TestResolutionContainerRecordCoversSubtreeRemovalAndSnapshotsAreDetached(t
|
||||
if _, ok := result.Metadata().Lookup(Keys("items", "remove")); ok {
|
||||
t.Fatal("removed entry remains effective metadata")
|
||||
}
|
||||
if len(result.resolution) != 1 || result.resolution[0].before == nil || result.resolution[0].after == nil {
|
||||
t.Fatalf("snapshots = %#v", result.resolution)
|
||||
snapshots := result.history.resolutionPayload.snapshots
|
||||
if len(snapshots) != 1 || snapshots[0].before == nil || snapshots[0].after == nil {
|
||||
t.Fatalf("snapshots = %#v", snapshots)
|
||||
}
|
||||
result.Config.Items["keep"] = item{Value: "changed"}
|
||||
if mappingValue(t, result.resolution[0].after, "keep").Mapping[0].Value.Text != "yes" {
|
||||
if mappingValue(t, snapshots[0].after, "keep").Mapping[0].Value.Text != "yes" {
|
||||
t.Fatal("caller mutation changed private resolution snapshot")
|
||||
}
|
||||
}
|
||||
@@ -383,8 +385,9 @@ func TestResolutionPresenceUsesEntryShapeAcrossDynamicChanges(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result.resolution) != 2 || result.resolution[1].change.Origin.Operation != ChangeDerivedDefault {
|
||||
t.Fatalf("resolution records = %#v", result.resolution)
|
||||
snapshots := result.history.resolutionPayload.snapshots
|
||||
if len(snapshots) != 2 || snapshots[1].change.Origin.Operation != ChangeDerivedDefault {
|
||||
t.Fatalf("resolution records = %#v", snapshots)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user