package configkit import ( "errors" "io" "gitea.maximumdirect.net/eric/ConfigKit/internal/engine" ) // SecretFileStatus describes the outcome for one file considered by // LoadSecretsDir. type SecretFileStatus string const ( SecretFileLoaded SecretFileStatus = "loaded" SecretFileSkippedExisting SecretFileStatus = "skipped_existing" SecretFileNotApplied SecretFileStatus = "not_applied" SecretFileFailed SecretFileStatus = "failed" ) // SecretFileResult is the safe, value-free bootstrap result for one directory // entry. ExistingEmpty is meaningful when Status is SecretFileSkippedExisting. type SecretFileResult struct { Name string Path string Status SecretFileStatus ExistingEmpty bool } // SecretsReport is a detached snapshot of an explicit secrets-directory // bootstrap. It does not retain file contents or environment values. type SecretsReport struct{ value *engine.SecretsReport } // Entries returns a copy of the report's filename-ordered entries. func (r *SecretsReport) Entries() []SecretFileResult { if r == nil || r.value == nil { return nil } values := r.value.Entries() if values == nil { return nil } result := make([]SecretFileResult, len(values)) for index := range values { result[index] = fromEngineSecretFileResult(values[index]) } return result } // WriteTo renders one safe, deterministic line per entry. Names and paths are // quoted so control characters cannot affect terminal output. func (r *SecretsReport) WriteTo(output io.Writer) (int64, error) { if r == nil || r.value == nil { return (*engine.SecretsReport)(nil).WriteTo(output) } return r.value.WriteTo(output) } // SecretsError reports safe structured diagnostics for a failed explicit // secrets-directory bootstrap. It intentionally does not unwrap filesystem or // environment errors. type SecretsError struct{ value *engine.SecretsError } // Error implements error without rendering filenames, paths, or file contents. func (e *SecretsError) Error() string { if e == nil || e.value == nil { return "configkit: secrets bootstrap failed" } return e.value.Error() } // Diagnostics returns a deep copy of the bootstrap diagnostics. func (e *SecretsError) Diagnostics() []Diagnostic { if e == nil || e.value == nil { return nil } values := e.value.Diagnostics() if values == nil { return nil } result := make([]Diagnostic, len(values)) for index := range values { result[index] = fromEngineDiagnostic(values[index]) } return result } // LoadSecretsDir explicitly loads immediate regular files from directory into // previously unset process environment variables. Applications should call it // once during startup, before concurrent work; Load never calls it. func LoadSecretsDir(directory string) (*SecretsReport, error) { report, err := engine.LoadSecretsDir(directory) result := &SecretsReport{value: report} if err == nil { return result, nil } var secretsError *engine.SecretsError if errors.As(err, &secretsError) { return result, &SecretsError{value: secretsError} } return result, &SecretsError{} }