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

@@ -1124,8 +1124,8 @@ export const EVENT_API: readonly EventApiEntry[] = [
name: 'telemetry/redact',
mode: 'waterfall',
signature: '\'telemetry/redact\'(record: TelemetryRecord, next: () => TelemetryRecord): TelemetryRecord',
jsDoc: '/**\n * Redact one outbound record before it reaches the backend. The innermost\n * `next()` applies the seam\'s conservative default rule set\n * (credential-shape scrubbing); listeners stack stricter rules by\n * transforming its return value, and returning without `next()` replaces\n * the default — the exported record is then only as clean as the\n * replacing rule. Dispatched synchronously on the capture hot path inside\n * the coordinator\'s containment: a throwing listener withholds that one\n * record (fail-closed) and never reaches the agent loop. Redaction\n * applies to the exported copy only; the canonical session log is never\n * rewritten.\n * @param record - the candidate record, already the coordinator\'s own deep\n * copy; listeners return a (possibly new) record and must not mutate it.\n * @mode waterfall\n */',
summary: 'Redact one outbound record before it reaches the backend.',
jsDoc: '/**\n * Redact one outbound record before it reaches the backend — the seam\'s\n * scrubbing extension point. The seam ships NO rules of its own: the\n * innermost `next()` passes the record through unchanged, and with no\n * listener mounted records reach the backend as captured, so exported\n * data is exactly as clean as the rules a deployment mounts. Listeners\n * stack by transforming `next()`\'s return value; returning without\n * `next()` replaces everything beneath. Dispatched synchronously on the\n * capture hot path inside the coordinator\'s containment: a throwing\n * listener withholds that one record (fail-closed) and never reaches the\n * agent loop. Redaction applies to the exported copy only; the canonical\n * session log is never rewritten.\n * @param record - the candidate record, already the coordinator\'s own deep\n * copy; listeners return a (possibly new) record and must not mutate it.\n * @mode waterfall\n */',
summary: 'Redact one outbound record before it reaches the backend — the seam\'s scrubbing extension point.',
},
{
name: 'tools/change',