package configkit // Layer identifies the precedence layer responsible for a configuration value. type Layer string const ( LayerDefault Layer = "default" LayerBase Layer = "base" LayerUnderlay Layer = "underlay" LayerOverlay Layer = "overlay" LayerCLI Layer = "cli" LayerResolution Layer = "resolution" ) // SourceKind identifies how a configuration source was acquired, independent // of its precedence layer. type SourceKind string const ( SourceKindFile SourceKind = "file" SourceKindFilesystem SourceKind = "filesystem" SourceKindBytes SourceKind = "bytes" SourceKindReader SourceKind = "reader" SourceKindMapping SourceKind = "mapping" SourceKindCLI SourceKind = "cli" ) // ChangeKind identifies a recorded operation. The zero value is // used for input and default origins. type ChangeKind string const ( // ChangeDecoding records the built-in transition to canonical typed values. // It is inspection metadata, not an operation accepted by Resolution.Record. ChangeDecoding ChangeKind = "decoding" // ChangeInheritance records structural input expansion. It is inspection // metadata, not an operation accepted by Resolution.Record. ChangeInheritance ChangeKind = "inheritance" ChangeDerivedDefault ChangeKind = "derived_default" ChangeNormalization ChangeKind = "normalization" ) // Severity classifies a diagnostic. type Severity string const ( SeverityError Severity = "error" SeverityWarning Severity = "warning" ) // Code is a stable, machine-readable diagnostic classification. type Code string const ( CodeSourceInvalid Code = "source.invalid" CodeSourceMissing Code = "source.missing" CodeSourcePermission Code = "source.permission" CodeSourceRead Code = "source.read" CodeSourceNotRegular Code = "source.not_regular" CodeSourceLimitExceeded Code = "source.limit_exceeded" CodeSourceReaderUsed Code = "source.reader_used" CodeYAMLInvalid Code = "yaml.invalid" CodeYAMLEmpty Code = "yaml.empty" CodeYAMLMultipleDocuments Code = "yaml.multiple_documents" CodeYAMLRootType Code = "yaml.root_type" CodeYAMLDuplicateKey Code = "yaml.duplicate_key" CodeYAMLTag Code = "yaml.tag" CodeYAMLAnchor Code = "yaml.anchor" CodeYAMLAlias Code = "yaml.alias" CodeYAMLMergeKey Code = "yaml.merge_key" CodeYAMLScalar Code = "yaml.scalar" CodeYAMLDepthLimit Code = "yaml.depth_limit" CodeYAMLNodeLimit Code = "yaml.node_limit" CodeSchemaRoot Code = "schema.root" CodeSchemaUnsupportedType Code = "schema.unsupported_type" CodeSchemaAmbiguousField Code = "schema.ambiguous_field" CodeSchemaTag Code = "schema.tag" CodeSchemaTextCodec Code = "schema.text_codec" CodeSchemaInline Code = "schema.inline" CodeSchemaCycle Code = "schema.cycle" CodeSchemaProjectionLimit Code = "schema.projection_limit" CodeSchemaCodec Code = "schema.codec" CodeSchemaNonFinite Code = "schema.non_finite" CodeSchemaDynamicType Code = "schema.dynamic_type" CodeDecodeType Code = "decode.type" CodeDecodeNull Code = "decode.null" CodeDecodeRange Code = "decode.range" CodeDecodeDuration Code = "decode.duration" CodeDecodeText Code = "decode.text" CodeDecodeUnknownField Code = "decode.unknown_field" CodeDecodeArrayLength Code = "decode.array_length" CodeOptionsInvalid Code = "options.invalid" CodeOptionsUnavailable Code = "options.unavailable" CodeImportDisabled Code = "import.disabled" CodeImportInvalid Code = "import.invalid" CodeImportMissing Code = "import.missing" CodeImportPermission Code = "import.permission" CodeImportRead Code = "import.read" CodeImportOutsideRoot Code = "import.outside_root" CodeImportCycle Code = "import.cycle" CodeImportRepeated Code = "import.repeated" CodeImportLimitExceeded Code = "import.limit_exceeded" CodeImportVersion Code = "import.version" CodeUnderlayVersion Code = "underlay.version" CodeOverlayInvalid Code = "overlay.invalid" CodeOverlayMissing Code = "overlay.missing" CodeOverlayOutsideRoot Code = "overlay.outside_root" CodeOverlayRepeated Code = "overlay.repeated" CodeOverlayDirective Code = "overlay.directive" CodeOverlayVersion Code = "overlay.version" CodeOverlayLimitExceeded Code = "overlay.limit_exceeded" CodeComposeInvalid Code = "compose.invalid" CodeComposeConflict Code = "compose.conflict" CodeVersionType Code = "version.type" CodeVersionError Code = "version.error" CodeVersionWarning Code = "version.warning" CodeVersionHookFailed Code = "version.hook_failed" CodeResolveError Code = "resolve.error" CodeResolveWarning Code = "resolve.warning" CodeResolveHookFailed Code = "resolve.hook_failed" CodeResolveInvalidPath Code = "resolve.invalid_path" CodeResolveInvalidKind Code = "resolve.invalid_kind" CodeResolveInvalidRecord Code = "resolve.invalid_record" CodeResolveInvalidTarget Code = "resolve.invalid_target" CodeResolveInvalidValue Code = "resolve.invalid_value" CodeResolveUnrecordedChange Code = "resolve.unrecorded_change" CodeValidateError Code = "validate.error" CodeValidateWarning Code = "validate.warning" CodeValidateInvalidPath Code = "validate.invalid_path" CodeValidateMutation Code = "validate.mutation" CodeSecretsInvalidPath Code = "secrets.invalid_path" CodeSecretsMissing Code = "secrets.missing" CodeSecretsPermission Code = "secrets.permission" CodeSecretsRead Code = "secrets.read" CodeSecretsNotRegular Code = "secrets.not_regular" CodeSecretsInvalidName Code = "secrets.invalid_name" CodeSecretsLimitExceeded Code = "secrets.limit_exceeded" CodeSecretsInvalidValue Code = "secrets.invalid_value" CodeSecretsApplyFailed Code = "secrets.apply_failed" CodeSecretRequired Code = "secret.required" CodeSecretInvalidName Code = "secret.invalid_name" CodeSecretUnset Code = "secret.unset" CodeSecretEmpty Code = "secret.empty" CodeOverrideInvalidPath Code = "override.invalid_path" CodeOverrideInvalidLabel Code = "override.invalid_label" CodeOverrideInvalidValue Code = "override.invalid_value" CodeOverrideDuplicate Code = "override.duplicate" CodeOverrideOverlap Code = "override.overlap" CodeOverrideDirective Code = "override.directive" CodeOverrideVersion Code = "override.version" CodeOverrideLimitExceeded Code = "override.limit_exceeded" CodeExplainLimitExceeded Code = "explain.limit_exceeded" CodeInheritanceInvalid Code = "inheritance.invalid" CodeInheritanceMissing Code = "inheritance.missing" CodeInheritanceCycle Code = "inheritance.cycle" CodeInheritanceVersion Code = "inheritance.version" ) // Location identifies a position in a configuration source. Zero line and column // values mean that coordinates are unavailable or synthetic. type Location struct { SourceID string Line int Column int } // SourceInfo describes a source discovered during a load. Kind identifies its // acquisition, independent of Layer. Path is canonical for a host file and // namespace-relative for a filesystem file; synthetic sources have no Path. // Destination is the effective mapping path where this source contributes. // UnderlayIndex is the one-based original underlay position, or zero for other // sources. ImportedFrom identifies the declaration that included this source. type SourceInfo struct { ID string Label string Path string // Destination is the effective mapping path. Imports inherit their declaring // document's path unless they append a YAML destination; overlay and CLI // sources use the root path. Destination Path Layer Layer Kind SourceKind UnderlayIndex int ImportedFrom *Location // VersionCheck is the sanitized source-local version declaration observed // during an enabled source-version load. It is nil otherwise. VersionCheck *SourceVersionCheck } // SourceVersionCheck describes a source-local version declaration observed // during an enabled load. Text is empty when classification or conservative // early-access redaction withholds it; Present and Null retain their meaning. type SourceVersionCheck struct { Path Path Version Version Location *Location Redacted bool } // Diagnostic is a safe structured problem report. Message and source labels must // never contain configuration values or other secrets. type Diagnostic struct { Code Code Severity Severity Path Path Message string Primary *Location Related []Location } // InheritanceStep identifies a concrete payload transfer. From and To name // semantic value paths; Reference names the controlling destination `extends` // path. Locations belong to that directive, not the transferred value. type InheritanceStep struct { From Path To Path Reference Path Locations []Location } // Origin describes where an effective definition came from. Multiple locations // represent a composite origin; resolution origins are synthetic and identify their // operation instead of a file location. Inheritance records the concrete // derivation path while Layer and Locations continue to identify value sources. type Origin struct { Layer Layer Locations []Location Operation ChangeKind Inheritance []InheritanceStep } // FieldInfo describes an effective configuration path. type FieldInfo struct { Explicit bool Null bool Origin Origin } // Change describes a definition or application-resolution operation. Path can name // an ancestor operation affecting the queried descendant. Historical values are // intentionally not exposed by this record. type Change struct { Path Path Origin Origin Previous []Origin Reasons []string Dependencies []Path } func cloneLocation(location *Location) *Location { if location == nil { return nil } cloned := *location return &cloned } func cloneLocations(locations []Location) []Location { if locations == nil { return nil } return append([]Location(nil), locations...) } func cloneSourceInfo(source SourceInfo) SourceInfo { source.Destination = source.Destination.clone() source.ImportedFrom = cloneLocation(source.ImportedFrom) source.VersionCheck = cloneSourceVersionCheck(source.VersionCheck) return source } func cloneSourceVersionCheck(value *SourceVersionCheck) *SourceVersionCheck { if value == nil { return nil } cloned := *value cloned.Path = value.Path.clone() cloned.Location = cloneLocation(value.Location) return &cloned } func cloneSourceInfos(sources []SourceInfo) []SourceInfo { if sources == nil { return nil } cloned := make([]SourceInfo, len(sources)) for i, source := range sources { cloned[i] = cloneSourceInfo(source) } return cloned } func cloneOrigin(origin Origin) Origin { origin.Locations = cloneLocations(origin.Locations) if origin.Inheritance != nil { steps := make([]InheritanceStep, len(origin.Inheritance)) for index, step := range origin.Inheritance { steps[index] = InheritanceStep{ From: step.From.clone(), To: step.To.clone(), Reference: step.Reference.clone(), Locations: cloneLocations(step.Locations), } } origin.Inheritance = steps } return origin } func cloneFieldInfo(info FieldInfo) FieldInfo { info.Origin = cloneOrigin(info.Origin) return info } func cloneChange(change Change) Change { change.Path = change.Path.clone() change.Origin = cloneOrigin(change.Origin) if change.Previous != nil { previous := make([]Origin, len(change.Previous)) for i, origin := range change.Previous { previous[i] = cloneOrigin(origin) } change.Previous = previous } change.Reasons = append([]string(nil), change.Reasons...) if change.Dependencies != nil { dependencies := make([]Path, len(change.Dependencies)) for i, path := range change.Dependencies { dependencies[i] = path.clone() } change.Dependencies = dependencies } return change } func cloneDiagnostic(diagnostic Diagnostic) Diagnostic { diagnostic.Path = diagnostic.Path.clone() diagnostic.Primary = cloneLocation(diagnostic.Primary) diagnostic.Related = cloneLocations(diagnostic.Related) return diagnostic } func cloneDiagnostics(diagnostics []Diagnostic) []Diagnostic { if diagnostics == nil { return nil } cloned := make([]Diagnostic, len(diagnostics)) for i, diagnostic := range diagnostics { cloned[i] = cloneDiagnostic(diagnostic) } return cloned }