Class: Insika::Safety::OutputFilter
- Inherits:
-
Object
- Object
- Insika::Safety::OutputFilter
- Defined in:
- lib/insika/safety/output_filter.rb
Overview
Deterministic output redaction on the STREAM (RFC-0009 §3.2 / D3). The turn
streams content deltas, so we cannot "unsay" text already sent — the filter
sits between the provider chunks and the :content event and only ever emits
text it has PROVEN clean.
The hard part (RFC §6, "fronteira de chunk"): a CPF/secret can arrive split
across two chunks and neither half matches on its own. A naive delta-by-delta
regex leaks "by construction". So the filter keeps a SLIDING BUFFER: it retains
the tail that might still be growing into a match (Detectors::OPEN_TAIL, which
also covers the unbounded sk-… case a fixed window can't) and emits only the
prefix that no future chunk can reach back into — at the cost of a few chars of
tail latency. On flush (turn end) the remainder is redacted and released.
Stateful and single-turn: one instance per streamed turn.
Instance Attribute Summary collapse
-
#redaction_counts ⇒ Object
readonly
Returns the value of attribute redaction_counts.
Instance Method Summary collapse
-
#flush ⇒ Object
Turn end: redact and release whatever is still buffered (nothing can grow anymore).
-
#initialize ⇒ OutputFilter
constructor
A new instance of OutputFilter.
-
#output ⇒ Object
The FULL redacted text produced across the turn (deltas + flush) — what gets persisted / put in the terminal event, so storage and stream agree.
-
#push(delta) ⇒ Object
Feeds one raw provider delta.
Constructor Details
#initialize ⇒ OutputFilter
Returns a new instance of OutputFilter.
24 25 26 27 28 |
# File 'lib/insika/safety/output_filter.rb', line 24 def initialize @buf = +"" @emitted = +"" # full redacted text emitted so far (for the persisted content) @redaction_counts = Hash.new(0) end |
Instance Attribute Details
#redaction_counts ⇒ Object (readonly)
Returns the value of attribute redaction_counts.
22 23 24 |
# File 'lib/insika/safety/output_filter.rb', line 22 def redaction_counts @redaction_counts end |
Instance Method Details
#flush ⇒ Object
Turn end: redact and release whatever is still buffered (nothing can grow anymore). Returns the final redacted tail (may be empty).
39 |
# File 'lib/insika/safety/output_filter.rb', line 39 def flush = release(@buf.length) |
#output ⇒ Object
The FULL redacted text produced across the turn (deltas + flush) — what gets persisted / put in the terminal event, so storage and stream agree.
43 |
# File 'lib/insika/safety/output_filter.rb', line 43 def output = @emitted.dup |
#push(delta) ⇒ Object
Feeds one raw provider delta. Returns the redacted, proven-clean slice to emit downstream (may be empty when everything is still held back).
32 33 34 35 |
# File 'lib/insika/safety/output_filter.rb', line 32 def push(delta) @buf << delta.to_s release(safe_cut) end |