"""Tests for observability incident bridge (#612) on #613 substrate.""" from __future__ import annotations import json import os import tempfile import unittest from control_plane_db import ControlPlaneDB, InvalidWorkKindError, WORK_KINDS from incident_bridge import ( OUTCOME_BLOCKED, OUTCOME_CREATED, OUTCOME_LINKED, OUTCOME_PREVIEW, OUTCOME_UPDATED, ProjectMapping, assert_not_raw_incident_work_item, build_gitea_issue_body, load_project_mappings, normalize_incident, project_mapping_from_dict, reconcile_incident, redact_text, sanitize_tags, ) def _mapping(**kwargs) -> ProjectMapping: base = dict( name="gitea-tools-mcp", provider="sentry", monitor_base_url="https://sentry.prgs.cc", monitor_org="prgs", monitor_project="gitea-tools-mcp", gitea_org="Scaled-Tech-Consulting", gitea_repo="Gitea-Tools", default_labels=("type:bug", "observability", "sentry", "status:ready"), ) base.update(kwargs) return ProjectMapping(**base) def _obs(**kwargs) -> dict: base = dict( provider="sentry", provider_base_url="https://sentry.prgs.cc", provider_org="prgs", provider_project="gitea-tools-mcp", provider_issue_id="ISSUE-100", provider_short_id="GITEA-TOOLS-1A", provider_permalink="https://sentry.prgs.cc/organizations/prgs/issues/100/", fingerprint="fp-abc", title="TypeError: boom", summary="TypeError: boom in handle_request", first_seen="2026-07-01T00:00:00Z", last_seen="2026-07-10T00:00:00Z", event_count=3, environment="production", severity="error", culprit="handle_request", tags={"runtime": "python", "release": "1.2.3"}, ) base.update(kwargs) return base class IncidentBridgeTest(unittest.TestCase): def setUp(self) -> None: self._tmp = tempfile.TemporaryDirectory() self.db = ControlPlaneDB(os.path.join(self._tmp.name, "cp.sqlite3")) self.mapping = _mapping() self.created: list[dict] = [] def tearDown(self) -> None: self._tmp.cleanup() def _create_issue(self, title, body, labels, g_org, g_repo): n = 9000 + len(self.created) rec = { "number": n, "success": True, "performed": True, "title": title, "body": body, "labels": labels, "org": g_org, "repo": g_repo, } self.created.append(rec) return rec def test_redact_secrets(self) -> None: dirty = "token=supersecret123 Authorization: Bearer abcdefghijklmnop" clean = redact_text(dirty) self.assertNotIn("supersecret", clean) self.assertNotIn("abcdefghijklmnop", clean) self.assertIn("[REDACTED]", clean) tags = sanitize_tags( {"token": "x", "runtime": "py", "password": "nope", "release": "1.0"} ) self.assertEqual(tags, {"runtime": "py", "release": "1.0"}) def test_body_contains_no_secrets(self) -> None: inc = normalize_incident( _obs( summary="fail password=hunter2 token: abc", tags={"cookie": "sid=1", "runtime": "py"}, ), self.mapping, ) body = build_gitea_issue_body(inc) self.assertNotIn("hunter2", body) self.assertNotIn("sid=1", body) self.assertIn("provider_issue_id", body) self.assertIn("not** assignable", body.lower()) def test_preview_no_mutation(self) -> None: res = reconcile_incident( self.db, observation=_obs(), mapping=self.mapping, apply=False, create_issue_fn=self._create_issue, ) self.assertTrue(res["success"]) self.assertEqual(res["outcome"], OUTCOME_PREVIEW) self.assertFalse(res["gitea_mutated"]) self.assertFalse(res["db_mutated"]) self.assertFalse(res["raw_incident_assignable"]) self.assertEqual(len(self.created), 0) self.assertIsNone( self.db.get_incident_link_by_provider( provider="sentry", provider_issue_id="ISSUE-100", provider_base_url="https://sentry.prgs.cc", provider_org="prgs", provider_project="gitea-tools-mcp", ) ) def test_apply_creates_issue_and_link(self) -> None: res = reconcile_incident( self.db, observation=_obs(), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) self.assertTrue(res["success"]) self.assertEqual(res["outcome"], OUTCOME_CREATED) self.assertTrue(res["gitea_mutated"]) self.assertTrue(res["db_mutated"]) self.assertEqual(len(self.created), 1) self.assertEqual(res["gitea_issue"]["number"], self.created[0]["number"]) link = self.db.get_incident_link_by_provider( provider="sentry", provider_issue_id="ISSUE-100", provider_base_url="https://sentry.prgs.cc", provider_org="prgs", provider_project="gitea-tools-mcp", ) self.assertIsNotNone(link) self.assertEqual(int(link["gitea_issue_number"]), self.created[0]["number"]) self.assertEqual(res["allocator_visible_as"]["kind"], "issue") def test_duplicate_observation_reuses_issue(self) -> None: first = reconcile_incident( self.db, observation=_obs(), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) second = reconcile_incident( self.db, observation=_obs(event_count=9, last_seen="2026-07-11T00:00:00Z"), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) self.assertEqual(first["outcome"], OUTCOME_CREATED) self.assertEqual(second["outcome"], OUTCOME_UPDATED) self.assertEqual(len(self.created), 1) self.assertEqual( second["gitea_issue"]["number"], first["gitea_issue"]["number"] ) link = self.db.get_incident_link_by_provider( provider="sentry", provider_issue_id="ISSUE-100", provider_base_url="https://sentry.prgs.cc", provider_org="prgs", provider_project="gitea-tools-mcp", ) self.assertEqual(int(link["event_count"]), 9) def test_explicit_link_existing_issue(self) -> None: res = reconcile_incident( self.db, observation=_obs(provider_issue_id="ISSUE-200"), mapping=self.mapping, apply=True, force_gitea_issue_number=555, create_issue_fn=self._create_issue, ) self.assertEqual(res["outcome"], OUTCOME_LINKED) self.assertEqual(len(self.created), 0) self.assertEqual(res["gitea_issue"]["number"], 555) link = self.db.get_incident_link_for_gitea_issue( gitea_org="Scaled-Tech-Consulting", gitea_repo="Gitea-Tools", gitea_issue_number=555, ) self.assertIsNotNone(link) def test_fingerprint_conflict_fails_closed(self) -> None: reconcile_incident( self.db, observation=_obs(fingerprint="fp-a"), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) res = reconcile_incident( self.db, observation=_obs(fingerprint="fp-b"), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) self.assertEqual(res["outcome"], OUTCOME_BLOCKED) self.assertIn("fingerprint conflict", res["reasons"][0].lower()) self.assertEqual(len(self.created), 1) def test_ambiguous_mapping_fails_closed(self) -> None: maps = [ _mapping(name="a", monitor_project="gitea-tools-mcp"), _mapping(name="b", monitor_project="gitea-tools-mcp"), ] res = reconcile_incident( self.db, observation=_obs(), mappings=maps, apply=False, ) self.assertEqual(res["outcome"], OUTCOME_BLOCKED) self.assertIn("ambiguous", res["reasons"][0].lower()) def test_missing_provider_issue_id_fails_closed(self) -> None: res = reconcile_incident( self.db, observation=_obs(provider_issue_id=""), mapping=self.mapping, apply=False, ) self.assertEqual(res["outcome"], OUTCOME_BLOCKED) def test_raw_incident_not_work_kind(self) -> None: self.assertNotIn("sentry_incident", WORK_KINDS) with self.assertRaises(InvalidWorkKindError): self.db.upsert_work_item( remote="prgs", org="o", repo="r", kind="sentry_incident", number=1, ) with self.assertRaises(Exception): assert_not_raw_incident_work_item("glitchtip_incident") def test_db_unavailable(self) -> None: res = reconcile_incident( None, observation=_obs(), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) self.assertFalse(res["success"]) self.assertEqual(res["outcome"], OUTCOME_BLOCKED) def test_structured_skip_reason_environment(self) -> None: m = _mapping(environment_filters=("staging",)) res = reconcile_incident( self.db, observation=_obs(environment="production"), mapping=m, apply=True, create_issue_fn=self._create_issue, ) self.assertTrue(res["success"]) self.assertEqual(res["action"], "skip_environment_filter") self.assertEqual(len(self.created), 0) def test_load_mappings_json(self) -> None: payload = json.dumps( { "projects": [ { "name": "gt", "provider": "glitchtip", "monitor_base_url": "https://glitchtip.example", "monitor_org": "org", "monitor_project": "proj", "gitea_org": "Scaled-Tech-Consulting", "gitea_repo": "Gitea-Tools", } ] } ) maps = load_project_mappings(mappings_json=payload) self.assertEqual(len(maps), 1) self.assertEqual(maps[0].provider, "glitchtip") def test_glitchtip_provider_accepted(self) -> None: m = _mapping(provider="glitchtip", monitor_base_url="https://glitchtip.example") res = reconcile_incident( self.db, observation=_obs( provider="glitchtip", provider_base_url="https://glitchtip.example", ), mapping=m, apply=True, create_issue_fn=self._create_issue, ) self.assertEqual(res["outcome"], OUTCOME_CREATED) self.assertEqual(res["incident"]["provider"], "glitchtip") def test_allocator_only_sees_issue_kind(self) -> None: res = reconcile_incident( self.db, observation=_obs(), mapping=self.mapping, apply=True, create_issue_fn=self._create_issue, ) vis = res["allocator_visible_as"] self.assertEqual(vis["kind"], "issue") self.assertIn(vis["kind"], WORK_KINDS) self.assertFalse(res["raw_incident_assignable"]) if __name__ == "__main__": unittest.main()