package configkit // Layer identifies the precedence layer responsible for a configuration value. type Layer string const ( LayerDefault Layer = "default" LayerBase Layer = "base" LayerProfile Layer = "profile" LayerCLI Layer = "cli" LayerResolution Layer = "resolution" ) // ChangeKind identifies an application resolution operation. The zero value is // used for input and default origins. type ChangeKind string const ( 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" CodeProfileInvalid Code = "profile.invalid" CodeProfileMissing Code = "profile.missing" CodeProfileOutsideRoot Code = "profile.outside_root" CodeProfileRepeated Code = "profile.repeated" CodeProfileDirective Code = "profile.directive" CodeProfileVersion Code = "profile.version" CodeProfileLimitExceeded Code = "profile.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" ) // 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. Path is a canonical // local path when one exists. ImportedFrom identifies the declaration that // included this source. type SourceInfo struct { ID string Label string Path string Layer Layer ImportedFrom *Location } // 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 } // Origin describes where an effective definition came from. Multiple locations // represent a composite origin. type Origin struct { Layer Layer Locations []Location Operation ChangeKind } // FieldInfo describes an effective configuration path. type FieldInfo struct { Explicit bool Null bool Origin Origin } // Change describes a definition or application-resolution operation. 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.ImportedFrom = cloneLocation(source.ImportedFrom) return source } 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) 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 }