Inbound (request)

  1. Prompt arrives at the Node core.
  2. PHI Rail decides: is the destination on the BAA allowlist?
    • Yes → pass through unchanged (BAA mode).
    • No → call PHI Gateway → scrub identifiers, get back a payload of typed aliases (PERSON_xxxx, EMAIL_xxxx, …) + a hydration map.
  3. The scrubbed payload + a SCRUB_MODE_GUARDRAIL system message ("never invent identifiers") goes to the LLM.

Outbound (response)

  1. LLM returns response containing aliases.
  2. PHI Rail calls phi_rehydrate with the response + the original hydration map.
  3. Real identifiers are spliced back in.
  4. Response flows to the caller.

Layered detection

The PHI Gateway runs a chain: known contacts (vault membership) → regex patterns → Presidio NER → insurance-specific dictionary. The first hit wins. Each stage has a confidence score that gates whether to alias.

Audit

Every scrub event is logged (timestamp, source, identifier counts — never the actual values). Queryable via phi_audit_query.