hermes-agent/tests/monitoring/test_export_redaction.py
Victor Kyriazakos 505d12f662 refactor(monitoring): scope telemetry substrate to gateway health/diagnostics export
Salvages the event-spine foundation from feat/telemetry-observability
(emitter, typed events, OTLP streaming, redaction — authorship preserved in
the preceding commits) and scopes it to the plane enterprise operators need
today: gateway Service Health Monitoring plus redacted Operational
Diagnostics, exported over OTLP.

Dropped from the salvaged branch, deliberately:
- run/model/tool trajectory capture (plugins/telemetry hooks, tel_spans)
- the local JSONL + state.db tel_* store (monitoring is egress, not storage)
- usage rollups/metrics, /insights integration, bulk export
- hermes telemetry CLI (replaced by hermes monitoring status)

Those planes — shared client usage metrics and enterprise trace telemetry —
are being designed on the NeMo Relay integration with distinct consent,
policy, and export boundaries; this keeps the monitoring plane content-free
and independently enableable.

Renames agent/telemetry -> agent/monitoring, config telemetry.* ->
monitoring.*, and pins the otlp extra at OpenTelemetry 1.39.1 (matching
uv.lock; 1.30.0 conflicts with mistralai>=2.4 on opentelemetry-api).
2026-07-24 18:54:45 +00:00

56 lines
1.9 KiB
Python

"""Export redaction pipeline tests — the security-critical layer.
Invariants:
* Secrets ALWAYS stripped, every export path, no flag disables it.
* Fails CLOSED: if the redactor can't run, the raw string is never emitted.
* PII (emails, phones, UUID-shaped ids) stripped in 'pii' mode — the mode
the gateway diagnostics path always uses.
"""
from __future__ import annotations
import agent.monitoring.redaction as R
def test_secret_always_stripped_in_none_mode():
fake_key = "sk-ant-api03-" + "A" * 24 # constructed to dodge literal-scrubbers
text = f"calling with key {fake_key} and moving on"
out = R.redact_for_export(text, content_mode=R.CONTENT_NONE)
assert out is not None
assert fake_key not in out
def test_secret_always_stripped_in_pii_mode():
fake_token = "ghp_" + "0123456789abcdef" * 2 + "0123"
text = f"token {fake_token} leaked"
out = R.redact_for_export(text, content_mode=R.CONTENT_PII)
assert out is not None
assert fake_token not in out
def test_none_passthrough():
assert R.redact_for_export(None, content_mode=R.CONTENT_NONE) is None
def test_pii_mode_strips_email_phone_uuid():
text = ("reach alice@example.com or +1 415 555 0100, "
"install 123e4567-e89b-12d3-a456-426614174000")
out = R.redact_for_export(text, content_mode=R.CONTENT_PII)
assert out is not None
assert "alice@example.com" not in out
assert "426614174000" not in out
assert "[email]" in out
assert "[id]" in out
def test_none_mode_keeps_ordinary_words():
out = R.redact_for_export("just ordinary words", content_mode=R.CONTENT_NONE)
assert out == "just ordinary words"
def test_pii_mode_preserves_non_pii_structure():
text = "platform.slack entered fatal after auth_failed"
out = R.redact_for_export(text, content_mode=R.CONTENT_PII)
assert out is not None
assert "platform.slack" in out
assert "auth_failed" in out