cellos-sink-redact 0.5.1

Redacting wrapper EventSink for CellOS — strips configured fields from CloudEvents before forwarding to an inner sink.
Documentation

cellos-sink-redact

EventSink wrapper that redacts nominated JSON fields from CloudEvents before forwarding to the inner sink (SEC-09).

What it is

Implements cellos_core::ports::EventSink. Wraps any Arc<dyn EventSink> and, before calling inner.emit(), walks the CloudEventV1.data JSON tree and replaces the values of nominated field names with a fixed placeholder:

  • scalars / strings → "[redacted]"
  • arrays → ["[redacted]"]
  • maps → {}

Only data is walked. CloudEvent metadata (id, source, type, time) is left untouched. An absent or empty data is forwarded unchanged.

Selected in cellos-supervisor::composition::build_primary_event_sink and build_jsonl_sink. The supervisor wraps in this order:

DlqSink( Sign( Redact( inner ) ) )

The order is deliberate: redact-then-sign so the signed payload reflects the post-redaction text. A downstream consumer running its own redaction would otherwise diverge from what the producer signed.

What it does NOT do:

  • It does not redact CloudEvent metadata fields (id, source, type, time).
  • It does not redact by value (no regex matching of secret strings). The redaction set is purely field-name driven.
  • It does not redact secret values that should never appear in events in the first place; the supervisor emits only secret names (secretRefs). This sink hardens against operator- authored cell payloads that surface argv, paths, or teardown reason strings.

Public API surface

Symbol Purpose
RedactingEventSink The wrapper.
RedactingEventSink::new(inner, fields) Explicit field-name set.
RedactingEventSink::with_defaults(inner) DEFAULT_REDACT_FIELDS.
RedactingEventSink::from_env(inner) Parse CELLOS_REDACT_EVENT_FIELDS; identity if unset / empty.
DEFAULT_REDACT_FIELDS ["argv", "path", "reason"].

Source: src/lib.rs.

Configuration

Env var Description
CELLOS_REDACT_EVENT_FIELDS Comma-separated field names to redact, e.g. argv,path,reason. The literal value defaults expands to DEFAULT_REDACT_FIELDS. Unset / empty disables the wrapper.

Examples

export CELLOS_REDACT_EVENT_FIELDS=defaults
# equivalent to:
export CELLOS_REDACT_EVENT_FIELDS=argv,path,reason
cellos-supervisor --spec cell.yaml

Result: "data": { "argv": ["[redacted]"], "path": "[redacted]", … } in every event flowing to the inner sink.

Testing

cargo test -p cellos-sink-redact

Related crates

  • cellos-sink-jetstream / cellos-sink-jsonl — typical inner sinks.
  • cellos-sink-dlq — wraps around this redactor so DLQ files are redaction-clean too.
  • cellos-supervisor — applies RedactingEventSink::from_env between the inner transport and the signer.
  • cellos-core — defines EventSink and CloudEventV1.

ADRs

  • ADR-0011 — cellos-server shares this sink composition.
  • SEC-09 — redact-before-emit requirement.
  • FC-74 — 90-day audit retention floor; redaction is what makes retained events safe to keep.