fix(monitoring): address review — persist install_id, drop dead config, single redaction path

- Cut the leftover telemetry.* DEFAULT_CONFIG block (nothing reads it) and
  the legacy telemetry-key fallback in policy.py.
- install_id: persist the minted UUID back to config.yaml on first use so
  service.instance.id survives gateway restarts (fail-open when the write
  is not possible); regression test covers the restart path.
- Remove the no-op gateway_health_export.redaction config keys. Redaction
  is always-on by design and deliberately not configurable; status output
  now says so.
- Collapse redaction to one unconditional secrets+PII scrub: drop the
  none/pii content modes (they served the dropped trajectories plane) and
  fold gateway_health.py's duplicate bearer/token/email/phone regex layer
  into agent/monitoring/redaction.py.
This commit is contained in:
Victor Kyriazakos
2026-07-14 20:55:15 +00:00
committed by Victor Kyriazakos
parent 505d12f662
commit 87a15733c0
8 changed files with 137 additions and 163 deletions
+34 -21
View File
@@ -1,56 +1,69 @@
"""Export redaction pipeline tests — the security-critical layer.
"""Export redaction tests — the security-critical layer.
Invariants:
* Secrets ALWAYS stripped, every export path, no flag disables it.
* One unconditional scrub: secrets AND PII, no modes, no knobs.
* 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.
* Structure (subsystem names, error codes) survives; free-text PII does not.
"""
from __future__ import annotations
from unittest import mock
import agent.monitoring.redaction as R
def test_secret_always_stripped_in_none_mode():
def test_secret_key_always_stripped():
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)
out = R.redact_for_export(f"calling with key {fake_key} and moving on")
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)
def test_token_shapes_stripped():
ghp = "ghp_" + "0123456789abcdef" * 2 + "0123"
slack = "xoxb-" + "123456789012-abcdefABCDEF"
out = R.redact_for_export(f"token {ghp} and {slack} leaked")
assert out is not None
assert fake_token not in out
assert ghp not in out
assert slack not in out
assert "[redacted]" in out
def test_bearer_header_stripped():
out = R.redact_for_export("Authorization: Bearer abc.def-ghi_jkl")
assert out is not None
assert "abc.def-ghi_jkl" not in out
def test_none_passthrough():
assert R.redact_for_export(None, content_mode=R.CONTENT_NONE) is None
assert R.redact_for_export(None) is None
def test_pii_mode_strips_email_phone_uuid():
def test_pii_always_stripped():
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)
out = R.redact_for_export(text)
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
assert "[phone]" 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_ordinary_words_survive():
assert R.redact_for_export("just ordinary words") == "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)
def test_structure_preserved():
out = R.redact_for_export("platform.slack entered fatal after auth_failed")
assert out is not None
assert "platform.slack" in out
assert "auth_failed" in out
def test_fails_closed_when_redactor_unavailable():
with mock.patch("agent.redact.redact_sensitive_text", side_effect=RuntimeError):
out = R.redact_for_export("secret sauce sk-live-key")
assert out == "[redaction-unavailable]"
+24 -2
View File
@@ -14,8 +14,8 @@ def test_default_config_keeps_gateway_health_export_disabled():
assert cfg["warning_error_events_enabled"] is True
assert cfg["export_interval_seconds"] == 60
assert cfg["logs_export_interval_seconds"] == 5
assert cfg["redaction"]["enabled"] is True
assert cfg["redaction"]["include_raw_stack"] is False
# Redaction is always-on and deliberately NOT configurable.
assert "redaction" not in cfg
def test_gateway_health_snapshot_maps_runtime_status_to_low_cardinality_metrics():
@@ -340,3 +340,25 @@ def test_gateway_diagnostic_log_handler_never_raises_on_malformed_record():
)
handler.emit(record)
def test_install_id_persists_across_calls(tmp_path, monkeypatch):
"""A minted install id must survive restarts (service.instance.id continuity)."""
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "config.yaml").write_text("{}\n")
import hermes_cli.config as cfg_mod
from agent.monitoring.policy import ensure_install_id
first = ensure_install_id(cfg_mod.load_config())
assert first and first != "unknown"
# Persisted: a fresh load (simulating a new gateway process) returns the same id.
second = ensure_install_id(cfg_mod.load_config())
assert second == first
assert first in (tmp_path / "config.yaml").read_text()
def test_install_id_existing_value_wins(monkeypatch):
from agent.monitoring.policy import ensure_install_id
assert ensure_install_id({"monitoring": {"install_id": "keep-me"}}) == "keep-me"