enhancement: opaque Spec value type with comprehensive redaction (ai) #6
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
heiko/secret#6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
enhancement: opaque
Specvalue type with comprehensive redaction (ai)Summary
go.schlittermann.de/heiko/secretcurrently exposes a proceduralAPI:
secret.Get(string) (string, error). Spec strings live asplain
stringvalues until resolution. This makes redaction theconsumer's responsibility on every output path:
fmt.Println,slog,MarshalJSON,MarshalText, structured-error wrapping,reflection-based debug dumpers — every one of these can leak the
spec (which is "safe-ish" for
env:VARbut actively dangerous forplain:andpass:schemes that carry the cleartext literal).Proposed addition
An opaque
Spectype with redaction-aware methods on every commonoutput interface:
The current
secret.Get(string)can stay as a thin wrapper forbackward compatibility (
Get(s) = s2, _ := ParseSpec(s); Resolve(s2)).Why this belongs upstream
Every consumer of
heiko/secretthat ships a service (especiallyone with structured logging, JSON config introspection, or a
"dump effective config" verb) needs the same redaction guarantees.
The dmarc project re-implemented
Specininternal/secret/spec.go(~310 LOC plus 600 LOC of tests) forexactly this reason. Anyone else writing a long-running daemon
that uses
heiko/secretwill hit the same need and eithercopy the dmarc shape or invent their own.
Putting it upstream:
(one author got
Format(%#v)right, the next forgets);parses lazily inside
Get, so a malformed spec fails atresolve-time, not config-load time);
pkg.go.deva single canonical shape for the docs.What dmarc does today
internal/secret/spec.goprovides exactly thisSpectype plusparse-time scheme validation, quote-balance checks, and
fallback-chain length limits. It calls upstream
secret.Get(spec.getRaw())for the actual resolution. Thewrapper is ~310 lines of dmarc-specific code that would
disappear if upstream shipped the type.
Out of scope for this issue
Resolution caching / dedup / audit-channel hooks are separate
concerns; filing those individually so each can be evaluated on
its own merits.
Compatibility
A
Spectype addition is purely additive —secret.Get(string)keeps working. Consumers that want the redaction-safe value type
opt in.
References
https://git.schlittermann.de/heiko/dmarc/src/branch/dev/internal/secret/spec.go
of zero-value
Specvia redacted-string comparison) is beingfixed in dmarc directly; the wrapper itself was correct.