secret

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package secret is the agent's in-memory credential primitive: a string-like value that holds an API key, token, or password but refuses to render itself. Every way a value normally escapes a process by accident - fmt verbs, JSON encoding, structured logs, an event written to the spine - returns a fixed redaction marker instead of the secret. The value leaves only through one explicit, grep-able call, Expose, used at the single point where it crosses the network boundary (an Authorization header). A credential leak by stray %v or a logged struct is therefore not a bug to be careful about, it is unrepresentable.

Text pairs with Source, the vault port: where a named credential reference resolves to a value. The default EnvSource reads the process environment so the agent runs with zero setup; an OS keychain, an age-encrypted file vault, a KMS, or a remote broker are swap-in adapters of the same port, the credential analog of state.Provider.

Honest scope: Go strings and the garbage collector make true zeroization best-effort. Text stores its bytes in a slice it owns and Destroy overwrites them, but copies the runtime made before Destroy (or that escaped via Expose) are beyond reach. The redaction guarantees are exact; the wiping is mitigation.

Index

Constants

View Source
const Redacted = "[REDACTED]"

Redacted is what every rendering of a Text shows in place of the value. It is deliberately not empty so a redacted secret is visible as such in output rather than looking like a missing field.

Variables

View Source
var ErrNotFound = errors.New("secret: not found")

ErrNotFound is returned by a Source when a reference resolves to no secret. It is a distinct sentinel so a caller can tell "this credential is not configured" apart from a backend failure (a locked keychain, an unreachable vault).

Functions

This section is empty.

Types

type EnvSource

type EnvSource struct{}

EnvSource resolves a reference to the process environment variable of the same name. It is the standalone default: it needs no configuration and works on every host. It is the only place the agent reads a credential from the environment, so the environment-as-secret-store assumption lives behind the port rather than scattered through the code.

func (EnvSource) Lookup

func (EnvSource) Lookup(_ context.Context, ref string) (Text, error)

Lookup returns the value of the environment variable named ref, or ErrNotFound if it is unset or empty. An empty variable is treated as absent so a blank export does not silently produce an empty credential that fails later at the API.

type Source

type Source interface {
	Lookup(ctx context.Context, ref string) (Text, error)
}

Source resolves a named reference to a secret value. It is the vault port: the agent asks for a credential by name and a backend supplies it, so the rest of the code never reads a raw environment variable or file. The default EnvSource keeps the agent zero-setup; an OS keychain, an age-encrypted file vault, a KMS, or a remote broker implement the same interface and swap in without touching the call sites. A Source must be safe for concurrent use and must return ErrNotFound (not an empty Text) for an absent reference.

func Chain

func Chain(sources ...Source) Source

Chain resolves a reference through an ordered list of Sources, returning the first value found. It is how a binary composes credential backends without the call site knowing the order: try the OS keychain, then a sealed file, then the environment, and stop at the first hit. A Source that returns ErrNotFound is skipped; any other error stops the chain and is returned, so a locked keychain or a corrupt vault surfaces rather than being silently masked by a later fallback. With no source holding the reference the chain returns ErrNotFound.

type Text

type Text struct {
	// contains filtered or unexported fields
}

Text holds a secret value and renders only as Redacted. The zero value is a valid empty secret. Text is a value type; copying it shares the underlying bytes, so Destroy on any copy clears them for all. It is safe to read concurrently; Destroy must not race a concurrent Expose.

func New

func New(value string) Text

New wraps a plaintext value in a Text. The input string's bytes are copied into storage the Text owns, so the caller may discard or overwrite its own copy.

func (*Text) Destroy

func (t *Text) Destroy()

Destroy overwrites the secret's bytes with zeros and empties the receiver. Because copies of a Text share the same backing array, the wipe clears the value for every copy; the receiver is additionally reset so it reports Empty. It is best-effort (see the package doc): it cannot reach copies the runtime made during a GC move, or a string an earlier Expose returned.

func (Text) Empty

func (t Text) Empty() bool

Empty reports whether the secret holds no value.

func (Text) Equal

func (t Text) Equal(other Text) bool

Equal compares two secrets in constant time, so a comparison does not leak the value through timing. Two empty secrets are equal.

func (Text) Expose

func (t Text) Expose() string

Expose returns the underlying plaintext. This is the one audited point where a secret becomes an ordinary string: call sites are intentionally easy to grep, and it should be used only where the value must cross a boundary the agent does not control (a request header). Do not log, format, or store the result.

func (Text) Format

func (t Text) Format(f fmt.State, _ rune)

Format implements fmt.Formatter, which fmt consults before Stringer, GoStringer, or struct-field reflection for every verb. It writes Redacted unconditionally, so even a numeric verb (%d, %x) that would otherwise recurse into the byte slice and print its contents cannot reveal the value.

func (Text) GoString

func (t Text) GoString() string

GoString implements fmt.GoStringer so the %#v verb (used by test helpers and struct dumps) also redacts.

func (Text) MarshalJSON

func (t Text) MarshalJSON() ([]byte, error)

MarshalJSON ensures a Text encodes as the redaction marker string, never the value, so a secret embedded in a struct cannot leak into JSON written to a log, an API response, or the event spine. Together with Format (which guards every fmt verb) this covers both the JSON and the text rendering paths a structured logger uses, so a Text logged through any handler shows only the marker.

func (Text) MarshalText

func (t Text) MarshalText() ([]byte, error)

MarshalText makes Text redact under any encoding that honors encoding.TextMarshaler, and lets a struct field of type Text serialize safely without a custom marshaler on the parent.

func (Text) String

func (t Text) String() string

String implements fmt.Stringer and returns Redacted, for callers that invoke Stringer directly rather than through fmt (where Format already guards).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL