Prepare inspection history before publication
This commit is contained in:
@@ -375,6 +375,13 @@ Focused check: `go test ./internal/engine -run 'Sequence|Collection|Inheritance|
|
|||||||
Finding: preparation portion of **D01**.
|
Finding: preparation portion of **D01**.
|
||||||
Owners: `internal/engine/load.go`, `load_result.go`, `history.go`, `inheritance_load.go`.
|
Owners: `internal/engine/load.go`, `load_result.go`, `history.go`, `inheritance_load.go`.
|
||||||
|
|
||||||
|
Status: **complete** (preparation portion of D01). Prior completed commits:
|
||||||
|
`2736ddf`, `deb9aa5`, `ae3408a`, `ea27f17`, `08a8c25`, `877c497`,
|
||||||
|
`8aba43d`, `7bf2f0c`, `0f9ecf1`, `119b42c`, `247a12b`. Validation passed:
|
||||||
|
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -run 'Load|History|Explain|Inheritance|Validation|Secret' -count=1`,
|
||||||
|
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -count=1`,
|
||||||
|
and `git diff --check`.
|
||||||
|
|
||||||
1. Extract preparation of the existing `Inspection` document/history fields from
|
1. Extract preparation of the existing `Inspection` document/history fields from
|
||||||
publication. Produce the actual owned pre-CLI copy, inherited-operation copies,
|
publication. Produce the actual owned pre-CLI copy, inherited-operation copies,
|
||||||
application lists, raw resolution snapshots, and coalesced replay that the result
|
application lists, raw resolution snapshots, and coalesced replay that the result
|
||||||
@@ -396,6 +403,12 @@ Acceptance: existing lifecycle and explanation behavior stays intact. Document
|
|||||||
the concrete retained document fields for Stage 13. This preparatory stage alone
|
the concrete retained document fields for Stage 13. This preparatory stage alone
|
||||||
does not close D01; avoid temporary public state or compatibility APIs if the
|
does not close D01; avoid temporary public state or compatibility APIs if the
|
||||||
handoff is not yet buildable.
|
handoff is not yet buildable.
|
||||||
|
|
||||||
|
Prepared retained roots for Stage 13 admission are `Inspection.baseline`,
|
||||||
|
`input`, `final`, `preCLI`, source/CLI application values, raw and coalesced
|
||||||
|
resolution before/after values, and inspection inheritance parent/effective
|
||||||
|
values. `Metadata.inheritance` holds its separate cloned parent/effective values;
|
||||||
|
the immutable document lookup is built only during publication.
|
||||||
Focused check when buildable: `go test ./internal/engine -run 'Load|History|Explain|Inheritance|Validation|Secret'`.
|
Focused check when buildable: `go test ./internal/engine -run 'Load|History|Explain|Inheritance|Validation|Secret'`.
|
||||||
|
|
||||||
## Stage 13 — Enforce The Quota On The Prepared Published Graph
|
## Stage 13 — Enforce The Quota On The Prepared Published Graph
|
||||||
|
|||||||
@@ -341,8 +341,11 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
|||||||
if hasErrors(diagnostics) {
|
if hasErrors(diagnostics) {
|
||||||
return nil, accumulator.loadError()
|
return nil, accumulator.loadError()
|
||||||
}
|
}
|
||||||
historyApplications := append(cloneHistoryApplications(resolved.applications), cloneHistoryApplications(resolved.postDecodeApps)...)
|
inspection := prepareInspectionHistory(resolved)
|
||||||
if !historyNodesWithinLimit(decoded.baseline, decoded.final, resolved.final, historyApplications, resolved.snapshots, input.inheritance) {
|
historyApplications := make([]historyApplication, 0, len(inspection.applications)+len(inspection.postDecodeApps))
|
||||||
|
historyApplications = append(historyApplications, inspection.applications...)
|
||||||
|
historyApplications = append(historyApplications, inspection.postDecodeApps...)
|
||||||
|
if !historyNodesWithinLimit(inspection.baseline, inspection.input, inspection.final, historyApplications, inspection.resolution, input.inheritance) {
|
||||||
accumulator.add(Diagnostic{Code: CodeExplainLimitExceeded, Severity: SeverityError, Message: "retained configuration history exceeds the node limit"})
|
accumulator.add(Diagnostic{Code: CodeExplainLimitExceeded, Severity: SeverityError, Message: "retained configuration history exceeds the node limit"})
|
||||||
return nil, accumulator.loadError()
|
return nil, accumulator.loadError()
|
||||||
}
|
}
|
||||||
@@ -373,5 +376,5 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
|||||||
resolved.configuration = configuration
|
resolved.configuration = configuration
|
||||||
// Publication detaches equal-valued validator replacements, preserving the
|
// Publication detaches equal-valued validator replacements, preserving the
|
||||||
// validated secret state, then finalizes metadata and sensitivity.
|
// validated secret state, then finalizes metadata and sensitivity.
|
||||||
return publishLoadResult(schema, request.definition, resolved, secretResolution.references, &accumulator)
|
return publishLoadResult(schema, request.definition, resolved, inspection, historyApplications, secretResolution.references, &accumulator)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func resolveLoadInput[T any](schema *schemaDescriptor, definition Definition[T],
|
|||||||
}
|
}
|
||||||
applications := []historyApplication(nil)
|
applications := []historyApplication(nil)
|
||||||
if input.composition != nil {
|
if input.composition != nil {
|
||||||
applications = cloneHistoryApplications(input.composition.applications)
|
applications = input.composition.applications
|
||||||
} else if input.document != nil {
|
} else if input.document != nil {
|
||||||
applications = []historyApplication{{layer: LayerBase, value: input.document}}
|
applications = []historyApplication{{layer: LayerBase, value: input.document}}
|
||||||
}
|
}
|
||||||
@@ -83,8 +83,8 @@ func resolveLoadInput[T any](schema *schemaDescriptor, definition Definition[T],
|
|||||||
return resolvedLoad[T]{
|
return resolvedLoad[T]{
|
||||||
configuration: configuration, decoded: decoded, metadata: metadata, final: final,
|
configuration: configuration, decoded: decoded, metadata: metadata, final: final,
|
||||||
snapshots: resolutionSnapshots, applications: applications,
|
snapshots: resolutionSnapshots, applications: applications,
|
||||||
postDecodeApps: cloneHistoryApplications(prepared.postDecodeApps), structuralInput: document.Clone(prepared.structuralInput),
|
postDecodeApps: prepared.postDecodeApps, structuralInput: document.Clone(prepared.structuralInput),
|
||||||
preCLI: document.Clone(prepared.preCLI), preCLIOrigins: cloneOrigins(prepared.preCLIOrigins), referenceInput: referenceInput,
|
preCLI: prepared.preCLI, preCLIOrigins: prepared.preCLIOrigins, referenceInput: referenceInput,
|
||||||
versionEvidence: versionEvidence, inheritance: input.inheritance, contexts: input.contexts,
|
versionEvidence: versionEvidence, inheritance: input.inheritance, contexts: input.contexts,
|
||||||
}, diagnostics
|
}, diagnostics
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,24 @@ func detachLoadConfiguration[T any](schema *schemaDescriptor, configuration T, m
|
|||||||
return detached.Interface().(T), nil
|
return detached.Interface().(T), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func publishLoadResult[T any](schema *schemaDescriptor, definition Definition[T], resolved resolvedLoad[T], references map[string]string, accumulator *diagnosticAccumulator) (*Loaded[T], error) {
|
func prepareInspectionHistory[T any](resolved resolvedLoad[T]) *Inspection {
|
||||||
|
return &Inspection{
|
||||||
|
metadata: resolved.metadata,
|
||||||
|
baseline: resolved.decoded.baseline,
|
||||||
|
input: resolved.decoded.final,
|
||||||
|
inputOrigins: cloneOriginIndex(resolved.decoded.origins),
|
||||||
|
preCLI: resolved.preCLI,
|
||||||
|
preCLIOrigins: cloneOrigins(resolved.preCLIOrigins),
|
||||||
|
postDecodeApps: cloneHistoryApplications(resolved.postDecodeApps),
|
||||||
|
final: resolved.final,
|
||||||
|
resolution: resolved.snapshots,
|
||||||
|
resolutionReplay: coalescedResolutionSnapshots(resolved.snapshots),
|
||||||
|
applications: cloneHistoryApplications(resolved.applications),
|
||||||
|
inheritance: inheritanceOperations(resolved.inheritance),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
// A read-only validator can replace a value with an equal borrowed object.
|
// A read-only validator can replace a value with an equal borrowed object.
|
||||||
// Detach without re-reading the environment or discarding validated state.
|
// Detach without re-reading the environment or discarding validated state.
|
||||||
configuration, issue := detachLoadConfiguration(schema, resolved.configuration, cloneValidatedSecrets)
|
configuration, issue := detachLoadConfiguration(schema, resolved.configuration, cloneValidatedSecrets)
|
||||||
@@ -107,38 +124,23 @@ func publishLoadResult[T any](schema *schemaDescriptor, definition Definition[T]
|
|||||||
accumulator.add(*issue)
|
accumulator.add(*issue)
|
||||||
return nil, accumulator.loadError()
|
return nil, accumulator.loadError()
|
||||||
}
|
}
|
||||||
decoded, metadata := resolved.decoded, resolved.metadata
|
decoded := resolved.decoded
|
||||||
final, applications, resolutionSnapshots := resolved.final, resolved.applications, resolved.snapshots
|
metadata, final, preCLI := inspection.metadata, inspection.final, inspection.preCLI
|
||||||
preCLI := document.Clone(resolved.preCLI)
|
finalizeMetadataPaths(&metadata, final, applications, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
||||||
allApplications := append(cloneHistoryApplications(applications), cloneHistoryApplications(resolved.postDecodeApps)...)
|
secrets := classifySecretPathsWithEvidence(schema, definition.Secret, metadata, final, applications, resolved.versionEvidence, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
||||||
finalizeMetadataPaths(&metadata, final, allApplications, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
|
||||||
secrets := classifySecretPathsWithEvidence(schema, definition.Secret, metadata, final, allApplications, resolved.versionEvidence, decoded.baseline, resolved.structuralInput, resolved.preCLI, decoded.final)
|
|
||||||
sources := sourceInfosWithVersionEvidence(accumulator.sources, resolved.versionEvidence, secrets, false)
|
sources := sourceInfosWithVersionEvidence(accumulator.sources, resolved.versionEvidence, secrets, false)
|
||||||
retainedTrees := make([]*document.Node, 0, len(allApplications)+4)
|
retainedTrees := make([]*document.Node, 0, len(applications)+4)
|
||||||
retainedTrees = append(retainedTrees, decoded.final, final, preCLI)
|
retainedTrees = append(retainedTrees, decoded.final, final, preCLI)
|
||||||
for _, application := range allApplications {
|
for _, application := range applications {
|
||||||
retainedTrees = append(retainedTrees, application.value)
|
retainedTrees = append(retainedTrees, application.value)
|
||||||
}
|
}
|
||||||
inspection := &Inspection{
|
inspection.metadata = metadata
|
||||||
metadata: metadata,
|
inspection.sources = sources
|
||||||
sources: sources,
|
inspection.contexts = cloneResourceContexts(resolved.contexts)
|
||||||
contexts: cloneResourceContexts(resolved.contexts),
|
inspection.diagnostics = canonicalDiagnostics(accumulator.diagnostics)
|
||||||
diagnostics: canonicalDiagnostics(accumulator.diagnostics),
|
inspection.immutableLookup = buildDocumentLookup(retainedTrees...)
|
||||||
baseline: decoded.baseline,
|
inspection.secrets = secrets
|
||||||
input: decoded.final,
|
inspection.secretReferences = cloneSecretReferences(references)
|
||||||
inputOrigins: cloneOriginIndex(decoded.origins),
|
|
||||||
preCLI: preCLI,
|
|
||||||
preCLIOrigins: cloneOrigins(resolved.preCLIOrigins),
|
|
||||||
postDecodeApps: cloneHistoryApplications(resolved.postDecodeApps),
|
|
||||||
final: final,
|
|
||||||
immutableLookup: buildDocumentLookup(retainedTrees...),
|
|
||||||
resolution: resolutionSnapshots,
|
|
||||||
resolutionReplay: coalescedResolutionSnapshots(resolutionSnapshots),
|
|
||||||
applications: applications,
|
|
||||||
inheritance: inheritanceOperations(resolved.inheritance),
|
|
||||||
secrets: secrets,
|
|
||||||
secretReferences: cloneSecretReferences(references),
|
|
||||||
}
|
|
||||||
return &Loaded[T]{Config: configuration, Inspection: inspection}, nil
|
return &Loaded[T]{Config: configuration, Inspection: inspection}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user