Skip to main content

ADR-0099: Active adverse-media re-screen in continuous monitoring

Date: 2026-07-06 Status: Accepted Deciders: Adrian (Soft4U), Claude Opus 4.8

Decision context:

  • Latency: one adverse-media agent call per due, monitored case per cadence window — real external API spend, so gated behind a default-off flag + the existing risk cadence (EDD 90d / CDD 180d / SDD 365d). Not on any request path (the scheduled ContinuousMonitoringWorkflow). Not-due and flag-off are both zero-cost no-ops.
  • Dependency surface: no new packages. Reuses run_adverse_media_agent (ADR-0077), is_rescreen_due (ADR-0066), the ScreeningResultRecord evidence trail (ADR-0063), and the trigger router (ADR-0083). One new MonitoringCheckType member, one _CHECK_TYPE_TRIGGER mapping, one check method, one config flag.
  • Debuggability: each re-screen writes an append-only ScreeningResultRecord (screened_by="monitoring-adverse-rescreen") + (on a hit) a monitoring_alerts row via the existing route — a queryable evidence trail with timestamps, not a transient result. An indeterminate agent run persists a WARNING, never a silent clean.
  • Reversibility: additive — a new enum member, a new check method, a config flag defaulting off. Reverting removes the check from the suite; the flag-off default means it is inert until deliberately enabled. ~4-file change.
  • Blast radius: additive on run_check dispatch + one router mapping. No change to the person/UBO re-screen (ADR-0066), the material-change diff, or the alert lifecycle. The default-off flag means production behaviour is unchanged until the Calibration-Review gate flips it.
  • Alternative considered: emit the result as a material_change event with an adverse_media signal (reuses the existing router mapping, no new check type) — rejected because it conflates a fresh subject re-query with the persisted-data diff (a taxonomy-conflation the Calibration checklist forbids) and hides the distinct cadence/evidence stream.

Context

Post-approval monitoring re-screens persons (directors/UBOs) against sanctions/PEP watchlists on a risk cadence (check_ubo_screening, ADR-0066), and detect_material_changes surfaces an adverse-media signal — but only from persisted investigation data (_derive_signals(fiscal_rep_data)), never a fresh query. There is no periodic fresh adverse-media re-query of the subject entity once a relationship is onboarded. A subject first named in an enforcement action or serious-crime story after onboarding is therefore invisible until the next full periodic review — a gap AMLR Art. 26 ongoing-monitoring targets, and the residual of issue #14 (ADR-0066/0083/0089 shipped the rest). ADR-0093's Tier-B adverse recall runs at investigation time, not on the monitoring cadence.

Decision

Add a distinct, cadence-gated, cost-flagged adverse-media re-screen to continuous monitoring.

  1. MonitoringCheckType.adverse_media (a new, distinct check — not folded into material_change) with a _CHECK_TYPE_TRIGGER["adverse_media"] = adverse_media_critical mapping in triggers_for_event.
  2. check_adverse_media_rescreen: cadence-gated (is_rescreen_due), behind adverse_media_monitoring_enabled (default False — dark-launched, Calibration-Review-gated to flip). When due + enabled, calls run_adverse_media_agent for the subject, compares against the last recorded adverse-media evidence, and emits a MonitoringEvent: a new critical finding → critical (routes to adverse_media_critical); an agent error / indeterminate → WARNING, indeterminate=True, never a benign clean (ADR-0067 fail-closed). Persists an append-only ScreeningResultRecord (screened_by="monitoring-adverse-rescreen"). No caching across the cadence — always fresh.
  3. Dispatched in run_check; added to the default check suite (inert while the flag is off).
  4. No migration — reuses monitoring_events / screening_results / monitoring_alerts and the config flag.

Consequences

Positive

  • A subject that becomes adverse-media-relevant after onboarding is detected on the monitoring cadence, not only at the next full review — closing the #14 residual and the AMLR Art. 26 ongoing-monitoring adverse-media gap.
  • Distinct check type + evidence stream keeps the taxonomy honest (fresh subject re-query ≠ persisted-data diff ≠ person watchlist re-screen) and gives an auditable per-re-screen trail.
  • Reuses the whole alert/route/review lifecycle — a hit routes and (EDD) opens a review case with zero new machinery.

Negative

  • Real external API spend per due monitored case when enabled — the reason for the default-off flag + cadence gate; a large EDD population makes this the dominant monitoring cost when flipped on.
  • Adverse-media agent recall/precision is imperfect (ADR-0077/0093): a re-screen can miss a real new story (recall) or raise a low-value hit (precision); the fail-closed WARNING covers the error path but not a confident-but-wrong agent result.
  • Prior-state comparison depends on a consistent adverse-media evidence representation across investigation and monitoring; a drift there could mis-flag an old finding as "new".

Neutral

  • Inert in production until the Calibration-Review gate flips adverse_media_monitoring_enabled.
  • Person/UBO watchlist re-screen (ADR-0066) and the material-change diff are unchanged.

Alternatives Considered

Alternative 1: emit as a material_change adverse-media signal (no new check type)

  • Reuse the existing material_changeadverse_media_critical router mapping.
  • Why rejected: conflates a fresh subject re-query with the persisted-data diff — a taxonomy-conflation the Calibration checklist forbids — and buries the distinct cadence and evidence stream, making "was the subject actively re-screened?" unanswerable from the data.

Alternative 2: do nothing (rely on the next full periodic review)

  • Let the Art. 26 periodic review (ADR-0083) catch new adverse media.
  • Why rejected: the periodic review can be a year out for EDD; "without undue delay" on a new serious-crime/enforcement signal is exactly what event-driven monitoring exists for, and the detection spine already exists — only the fresh re-query was missing.