Class: Insika::Safety::OutputFilter

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initializeOutputFilter

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_countsObject (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

#flushObject

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)

#outputObject

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