redact

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: MIT Imports: 11 Imported by: 0

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:

  1. 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.
  2. 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

View Source
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.

View Source
const FingerprintLen = 16

FingerprintLen is §4.4's "16 hex everywhere" rule.

View Source
const Mask = "<redacted>"

Mask replaces every redacted value.

Variables

This section is empty.

Functions

func AuthorizationValue

func AuthorizationValue(value string) string

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

func Fingerprint(secret string) string

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 Header(name string) bool

Header reports whether a header's value must never be emitted.

func HeaderValue

func HeaderValue(name, value string) string

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

func Headers(h http.Header, alsoSecret ...string) http.Header

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 IsJWT

func IsJWT(s string) bool

IsJWT reports whether s is shaped like a JSON Web Token.

func Key

func Key(name string) bool

Key reports whether a JSON object key (or a query-parameter name) names a value that must never be emitted.

func MaskSecret

func MaskSecret(secret string) string

MaskSecret renders a secret as "<redacted:fp=...>". An empty secret yields the plain mask so the output never implies a credential existed.

func Text

func Text(s string) string

Text scrubs credentials out of free-form text: log lines, server messages, error strings and command echoes.

func URL

func URL(raw string) string

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.

func Value

func Value(v any) (any, []string)

Value redacts an already-decoded JSON-ish value in place-by-copy. It is the entry point for cache and audit writers that hold a map rather than bytes. The returned paths use the same notation as Result.Paths.

Types

type Result

type Result struct {
	Data    []byte
	Changed bool
	Paths   []string
}

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).

func JSON

func JSON(b []byte) Result

JSON redacts secret values inside a JSON document, preserving every byte it did not have to change. A body that is not valid JSON (an HTML error page, a truncated response) falls back to text scrubbing rather than being dropped.

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.

func (Scrubber) JSON

func (s Scrubber) JSON(b []byte) Result

JSON implements the splice-based redaction described in the package doc.

func (Scrubber) Text

func (s Scrubber) Text(in string) string

Text scrubs credentials out of free-form text.

func (Scrubber) Value

func (s Scrubber) Value(v any) (any, []string)

Value redacts a decoded value (map[string]any, []any, scalars).

Jump to

Keyboard shortcuts

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