Redaction registry + walker for safely surfacing structured data (compiled plans, event payloads, env maps, log lines) to an AI assistant or any debug surface.
A rule is a map:
{:select <selector> ; path-vector OR predicate fn (key,val)→bool :replace <fn> ; (fn [val] -> replacement) :id <keyword> ; assigned by register-rule! :doc <string?>}
Rules are stored in a global atom registry. redact walks input via
clojure.walk/postwalk, applying matching rules and auto-replacing
any Tainted it encounters with its print-method form.
[:env "SSHPASS"] matches the value at that path
inside any nested map.(fn [k v] ...) invoked for every map entry; truthy
return → replace the value.Registered at namespace load time:
:env/sshpass → [:env "SSHPASS"] → "<redacted>" :env/ssh-auth-sock → [:env "SSH_AUTH_SOCK"] → "<redacted>" :env/ssh-askpass → [:env "SSH_ASKPASS"] → "<redacted>" :env/ssh-private-key → [:env "SSH_PRIVATE_KEY"] → "<redacted>"
Any Tainted encountered during the walk is replaced with its
pr-str form (the redacted print-method output) — no rule needed.
redact never invokes untaint and never reads :value directly.
It is safe to compose into a logger appender.
Redaction registry + walker for safely surfacing structured data
(compiled plans, event payloads, env maps, log lines) to an AI
assistant or any debug surface.
## Model
A *rule* is a map:
{:select <selector> ; path-vector OR predicate fn (key,val)→bool
:replace <fn> ; (fn [val] -> replacement)
:id <keyword> ; assigned by register-rule!
:doc <string?>}
Rules are stored in a global atom registry. `redact` walks input via
`clojure.walk/postwalk`, applying matching rules and auto-replacing
any `Tainted` it encounters with its print-method form.
## Selector forms
- Vector path — `[:env "SSHPASS"]` matches the value at that path
inside any nested map.
- Predicate fn — `(fn [k v] ...)` invoked for every map entry; truthy
return → replace the value.
## Default rules
Registered at namespace load time:
:env/sshpass → [:env "SSHPASS"] → "<redacted>"
:env/ssh-auth-sock → [:env "SSH_AUTH_SOCK"] → "<redacted>"
:env/ssh-askpass → [:env "SSH_ASKPASS"] → "<redacted>"
:env/ssh-private-key → [:env "SSH_PRIVATE_KEY"] → "<redacted>"
## Tainted handling
Any `Tainted` encountered during the walk is replaced with its
`pr-str` form (the redacted print-method output) — no rule needed.
## Privacy contract
`redact` never invokes `untaint` and never reads `:value` directly.
It is safe to compose into a logger appender.(install-default-rules!)Re-register the default env/* rules. Call after reset-rules! in tests
that want the default surface back.
Re-register the default env/* rules. Call after `reset-rules!` in tests that want the default surface back.
(redact data)Walk data and return a redacted structure.
Tainted is replaced with its print-method form (a string
like <redacted src=... h=#xxxx>).:select matches has its :replace
applied to the matched value.Pure: never mutates input, never invokes untaint.
Walk `data` and return a redacted structure. - Every `Tainted` is replaced with its print-method form (a string like `<redacted src=... h=#xxxx>`). - Every registered rule whose `:select` matches has its `:replace` applied to the matched value. Pure: never mutates input, never invokes untaint.
(register-rule! id rule)Register a redaction rule under id. Overwrites any existing rule
with the same id. Returns the rule.
rule shape: {:select <vector-or-fn> :replace <fn> :doc <string?>}
Register a redaction rule under `id`. Overwrites any existing rule
with the same id. Returns the rule.
rule shape: {:select <vector-or-fn> :replace <fn> :doc <string?>}(registered-rules)Snapshot of currently registered rules: {id → rule}.
Snapshot of currently registered rules: {id → rule}.
(reset-rules!)Clear ALL registered rules (including defaults). Mainly useful for tests; production callers should prefer targeted unregister-rule!. Returns the previous rule map.
Clear ALL registered rules (including defaults). Mainly useful for tests; production callers should prefer targeted unregister-rule!. Returns the previous rule map.
(unregister-rule! id)Remove the rule with the given id. Returns the removed rule or nil.
Remove the rule with the given id. Returns the removed rule or nil.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |