Expand description
Provable security events for the value surface.
lean-ctx’s default-on protections (secret redaction, the shell allowlist, the path jail, prompt-injection screening) used to act silently: nothing a user could later point to. This module turns each firing into
- a hash-chained, signed
crate::core::audit_trailentry — the proof, and - a session counter (
SecurityCounts) — what the status line shows.
Counting is once per tool result. Deep code (redaction, allowlist) calls
note, which only lands in the collector that
collect opens around one MCP tool handler; the dispatch layer then
records the tally for that single result. note outside a collector (CLI,
hooks, config loading) is deliberately dropped, so a secret redacted twice
on its way through nested passes, or a re-rendered cache entry outside a
tool call, never inflates the count. Undercounting is acceptable; claiming
more than happened is not. Prompt-injection flags go further: one per
flagged object per process (record_injections), however often the same
object is delivered again.
The audit trail’s event_type enum is not extended: an older binary
verifying a trail that contains an unknown variant would report it as
tampered. The kind is committed in the (hashed) action field instead.
Structs§
- Call
Tally - What one tool call noted: the per-kind counts and the boundary refusals,
which are recorded with their
RefusalClass. - Injection
Flag - One object the prompt-injection heuristic flagged: which pattern families matched and the object’s SHA-256 — never its content.
- Security
Counts - Per-kind event counts. Persisted inside
SessionStats, so every field isserde(default)and old session files load unchanged.
Enums§
- Refusal
Class - Why the I/O boundary refused a path a call asked for. The trail records this class only: like every other entry, never the path, a digest of it or any content.
- Security
Kind - What a protection did. The wording each kind renders with is part of the honesty contract: injections are flagged, never “neutralized”.
Functions§
- anchor_
receipt - Anchors a Context Gateway receipt in the signed, hash-chained audit trail:
the digest in the hashed
actionbinds the stored receipt to the chain. Not a counted kind (parse_actionignores it), so nothing is counted twice. - collect
- Runs
f(one synchronous tool handler) with a fresh collector and returns what it noted. Nested calls keep the outer collector’s tally intact. - collect_
call collect, including the call’s boundary refusals (record_call).- drain_
pending - Takes the counts recorded since the last drain (the MCP server folds them into the current session’s stats).
- note
- Notes
nfirings ofkindinto the collector of the tool call running on this thread. A no-op outsidecollect— see the module docs for why. - note_
refusals - Notes
nboundary refusals ofclassinto the running call’s collector, likenote(a no-op outside one). A call that refuses several paths of one class gets one trail entry carrying the count. - parse_
action - Splits a recorded
action(<kind>:<n>[|<detail>…][|session=<id>]) into its parts; details (an injection flag’s pattern kinds) are skipped. - record
- Records one tool result’s security tally: one audit-trail entry per kind (the proof) plus the pending session counters (the display).
- record_
call - Records one tool call’s
CallTally: the counted kinds (record) and one entry per refusal class. - record_
injections - Records flagged objects: one audit-trail entry per object this process has not recorded yet (with the pattern kinds and a digest prefix, never content) plus the pending session counter. Returns how many were recorded.
- record_
one - Convenience for a single event recorded outside a handler (dispatch layer).
- record_
refusals - Records
nboundary refusals ofclassfor one tool call: one trail entry with the reason class (never the path) plus the session counter.