Documentation
¶
Overview ¶
Package redact removes credentials from everything PayCLI emits: stdout, stderr, log lines, audit records, cache files and the manifest (§5.3).
Two rules drive the whole package:
- Payload returns credentials inside ordinary documents. GET /api/{auth}/me hands back apiKey, hash and salt in plaintext, and a bulk write against the auth collection echoes every touched user, so any response body may contain a secret at any depth.
- error.raw and --output raw must stay byte-faithful *after* redaction (§11.1). JSON is therefore spliced, not re-encoded: when nothing matched, the caller gets the original bytes back with zero normalisation, and when something did match only the matched value ranges are replaced. Key order, indentation, number formatting and duplicate keys all survive.
Index ¶
- Constants
- func AuthorizationValue(value string) string
- func Fingerprint(secret string) string
- func Header(name string) bool
- func HeaderValue(name, value string) string
- func Headers(h http.Header, alsoSecret ...string) http.Header
- func IsJWT(s string) bool
- func Key(name string) bool
- func MaskSecret(secret string) string
- func Text(s string) string
- func URL(raw string) string
- func Value(v any) (any, []string)
- type Result
- type Scrubber
Constants ¶
const FingerprintDomain = "paycli-key-v1\x00"
FingerprintDomain is §4.4's domain separator. It exists so a PayCLI fingerprint can never be confused with a bare sha256 of the same key computed elsewhere.
const FingerprintLen = 16
FingerprintLen is §4.4's "16 hex everywhere" rule.
const Mask = "<redacted>"
Mask replaces every redacted value.
Variables ¶
This section is empty.
Functions ¶
func AuthorizationValue ¶
AuthorizationValue turns any Authorization header value into "<redacted:fp=a1b2c3d4e5f60718>" — the exact literal §5.3 requires the transport to log. The fingerprint covers the credential only (the last whitespace-separated field), so "users API-Key K" and "JWT K" fingerprint identically for the same K.
func Fingerprint ¶
Fingerprint is §4.4's stable, non-reversible tag for a secret: the first 16 hex characters of sha256("paycli-key-v1\x00" + secret). It is safe to print, log, store in the manifest (identity.key_fingerprint) and compare across runs.
This is THE formula. internal/secret.Fingerprint and cache.KeyFingerprint both delegate here, because §4.4 requires every producer — credentials.json, the manifest, `pay auth status`, `pay cache ls`, the §8.1 scope input and the transport's `Authorization: <redacted:fp=…>` log line — to emit the identical 16 characters for the same credential.
func HeaderValue ¶
HeaderValue returns the value that may be printed for a header. Authorization is special-cased into the fingerprint form mandated by §5.3's hard transport rule, so logs can prove *which* credential was used without revealing it.
func Headers ¶
Headers returns a copy of h safe to log or embed in a dry-run envelope. alsoSecret names additional headers to mask; the transport passes the profile's configured [profiles.X.headers] keys, all of which are secret.
func Key ¶
Key reports whether a JSON object key (or a query-parameter name) names a value that must never be emitted.
func MaskSecret ¶
MaskSecret renders a secret as "<redacted:fp=...>". An empty secret yields the plain mask so the output never implies a credential existed.
func Text ¶
Text scrubs credentials out of free-form text: log lines, server messages, error strings and command echoes.
func URL ¶
URL strips credentials from a URL before it crosses any boundary. §5.3 makes it mandatory on meta.base_url, error.http.url, §12.2's request.url, Event.BaseURL, Event.Path, the manifest's meta.base_url and source.base_url, and references/PROJECT.md.
Three things are removed:
- userinfo ("https://user:pass@host" -> "https://host"), removed outright rather than masked, because a masked userinfo re-encodes to "%3Credacted%3E@host" and stops being a usable URL;
- any query parameter whose name matches the value or header matchers;
- any path segment shaped like a JWT (reset-password links).
Percent-encoding, parameter order and the rest of the URL are preserved byte-for-byte: the raw query is rewritten in place, not re-encoded.
Types ¶
type Result ¶
Result is the outcome of redacting a JSON document.
Data is the original slice when Changed is false — literally the same bytes, so `--output raw` and error.raw stay byte-faithful on the overwhelmingly common path where there was nothing to hide. Paths lists the redacted locations in "docs[0].apiKey" form for the raw_redacted warning (§11.1).
type Scrubber ¶
type Scrubber struct {
// Literals are exact strings to replace wherever they appear. Empty and
// very short entries are ignored, because replacing a 1-character literal
// would shred unrelated output.
Literals []string
}
Scrubber adds known literal secret values (the resolved API key, a minted JWT) to the structural rules. The zero Scrubber applies the structural rules only and is what the package-level functions use.