The WhatsApp ingest Worker reads messages from approved resident groups and routes useful items without retaining raw chat. It handles text, image flyers, and voice notes.

Current routes

Classified itemDestinationPublish boundary
EventNotion EventsCreated unticked; an editor must publish it
Event changeMatching Notion eventPublished events receive a note; unticked events may be corrected
Official House Update candidateNotion House UpdatesNeeds Review until an editor approves it
Resident observationNotion Resident NotesAI-sanitized before write; an editor can revoke it
Resident casework or questionPrivate Casework databaseRouted to a current role owner; never published
Noise or spamNowhereDropped

WhatsApp no longer writes casework into House Updates. Email and WhatsApp casework use the same private writer, routing rules, consolidation checks, and owner feed from RC Console.

Flow

flowchart LR
  WA["Approved WhatsApp groups"] --> EVO["Evolution API"]
  EVO --> WEB["POST /webhook"]
  WEB --> MEDIA{"Message type"}
  MEDIA -->|"text or caption"| REDACT["Redact PII + filter noise"]
  MEDIA -->|"image flyer"| OCR["Vision OCR<br/>bytes not stored"]
  MEDIA -->|"voice note"| AUDIO["Whisper transcript<br/>bytes not stored"]
  OCR --> REDACT
  AUDIO --> REDACT
  REDACT --> KV["KV buffer<br/>redacted text only"]
  KV --> RUN["Debounced or 6-hour batch"]
  RUN --> ROUTE{"Classify and route"}
  ROUTE --> EVENTS["Events review"]
  ROUTE --> UPDATES["House Updates review"]
  ROUTE --> NOTES["Sanitized Resident Notes"]
  ROUTE --> CASES["Private Casework"]

POST /webhook does the immediate media handling, redaction, and deterministic filtering. A debounce alarm or the six-hour POST /run job classifies the buffered candidates. Empty runs are cheap no-ops.

Privacy boundary

  • Raw chat, names, phone numbers, profile photos, and message history are not stored.
  • Phone numbers, email addresses, and mentions are removed before text reaches KV.
  • Image and audio bytes exist only for the inference call; they are not written to KV, R2, logs, or the disposition ledger.
  • The KV buffer holds redacted candidates for up to 14 days.
  • The ledger records content-free processing state so an operator can tell whether a message was filtered, routed, or lost.
  • Debug output can expose redacted message text and is token-gated.

The Worker uses precision-first classification. An uncertain item goes to review or is dropped; it does not publish itself as an official statement.

Review and removal

Events remain hidden until Include in External Feed is enabled in Notion. Official updates remain hidden while their status is Needs Review, Draft, or Rejected.

Resident observations use a different boundary: the Worker rewrites them into public-safe notes before storing them. An editor removes one from the public feed by setting its status to Revoked.

Casework is private. Related reports, email threads, and answered questions can consolidate into an existing open case. The Casework owner comes from current RC Console position assignments. Alert email can be paused from RC Console without stopping intake.

Connector and health

Evolution API runs as a read-only WhatsApp connector paired to a replaceable account. It posts only allowed groups to the Worker.

The token-gated Evolution health probe checks:

  • connector reachability;
  • open WhatsApp session state;
  • whether any webhook has ever arrived;
  • whether a webhook arrived within the last 24 hours.

The cron service polls that probe every 30 minutes. This matters because a webhook missed during a connector outage cannot be replayed automatically.

Operations

  • Code deploys from changes under workers/whatsapp-ingest/ or workers/_shared/.
  • WA_BUFFER stores redacted candidates and content-free ledger entries.
  • Workers AI handles classification, image OCR, audio transcription, sanitation, and case matching.
  • Notion remains the review surface for Events, House Updates, Resident Notes, and private Casework.
  • /run?dryRun=1 classifies without writing.
  • /run?debug=1 adds redacted candidate text and model output for an authorized operator.
  • /ledger reports content-free dispositions.
  • /casework-digest sends the daily private owner digest.

After two merges land close together, confirm the path-filtered deploy ran for the later commit. GitHub can coalesce rapid push events.

Sources

  • ihnyc-rc-landing/workers/whatsapp-ingest/README.md
  • ihnyc-rc-landing/workers/whatsapp-ingest/CASEWORK_SETUP.md
  • ihnyc-rc-landing/workers/whatsapp-ingest/index.ts
  • ihnyc-rc-landing/workers/_shared/casework.ts