refactor(telemetry): ship the redact waterfall without built-in rules

The seam keeps the telemetry/redact scrubbing interface but ships no rules
of its own: the innermost next() passes records through unchanged, and
deployments mount their rules as waterfall listeners. As an SDK we cannot
know which patterns are secrets in a given deployment; a shipped list
invites false confidence while catching only known shapes, and false
positives would corrupt exported bodies. Mechanism stays with the seam,
policy moves to the deployment; both READMEs and the Agent Note state the
raw-export default plainly.

The loader-composition e2e now mounts a deployment-style rule fixture and
pins the same wire behavior: secret absent, placeholder present, canonical
log untouched.
This commit is contained in:
kingwl
2026-07-23 11:58:47 +08:00
parent cf2e184112
commit 70febffe1a
18 changed files with 155 additions and 236 deletions

View File

@@ -22,16 +22,17 @@ declare module 'cordis' {
interface Events {
/**
* Redact one outbound record before it reaches the backend. The innermost
* `next()` applies the seam's conservative default rule set
* (credential-shape scrubbing); listeners stack stricter rules by
* transforming its return value, and returning without `next()` replaces
* the default — the exported record is then only as clean as the
* replacing rule. Dispatched synchronously on the capture hot path inside
* the coordinator's containment: a throwing listener withholds that one
* record (fail-closed) and never reaches the agent loop. Redaction
* applies to the exported copy only; the canonical session log is never
* rewritten.
* Redact one outbound record before it reaches the backend — the seam's
* scrubbing extension point. The seam ships NO rules of its own: the
* innermost `next()` passes the record through unchanged, and with no
* listener mounted records reach the backend as captured, so exported
* data is exactly as clean as the rules a deployment mounts. Listeners
* stack by transforming `next()`'s return value; returning without
* `next()` replaces everything beneath. Dispatched synchronously on the
* capture hot path inside the coordinator's containment: a throwing
* listener withholds that one record (fail-closed) and never reaches the
* agent loop. Redaction applies to the exported copy only; the canonical
* session log is never rewritten.
* @param record - the candidate record, already the coordinator's own deep
* copy; listeners return a (possibly new) record and must not mutate it.
* @mode waterfall
@@ -142,4 +143,3 @@ export abstract class Telemetry extends Service implements TelemetryBackend {
}
export { TelemetryCoordinator } from './coordinator.ts'
export { applyDefaultRedaction, REDACTION_PLACEHOLDER } from './redact.ts'