Civilian /v1/* tier, operator case CRUD, triage-driven Suggested cases panel#7
Open
hidden-salmon wants to merge 1 commit intoMichielMAnalytics:mainfrom
Open
Conversation
…s panel
End-to-end flow: SafeThread iOS app talks to the matching engine, NGO
operators create / edit cases, civilian messages flow into a curated
right-rail review queue rather than cluttering the case list.
Backend
- server/api/civilian.py (new) — POST /v1/register, /v1/message, /v1/sighting,
GET /v1/alerts/active, WS /v1/stream. Bearer-token auth = phone. Civilian
app messages land orphan (no auto-Alert); only operators turn them into
cases. Wires into the existing eventbus + triage worker via new_inbound.
- server/api/incidents.py — POST /api/incidents (operator creates a case),
PATCH /api/incidents/{id} (operator pushes update; same incident_upserted
pipe forwards an ALERT_ISSUED to iOS for in-place card replacement).
- server/api/dashboard.py — recentDistress includes orphan messages with
triage payload so the wire survives tab switches.
- server/api/ws.py — _compose_inbound_event includes triage; subscribes to
new inbound_triaged channel so the wire enriches in-place after triage.
- server/workers/triage.py — publishes inbound_triaged after success.
- server/llm/triage_client.py — broader prompt covering all four case
categories (missing_person / medical / resource_shortage / safety) so
"I NEED A MEDIC" classifies as sighting, not noise.
- server/db/identity.py — get_or_create_default_ngo helper used by both
/api/incidents and /v1/register so a fresh-volume DB never 503s.
Frontend
- web/src/components/CreateCaseModal.tsx (new) — case creation form with
optional pre-fill defaults so the same component handles "blank" and
"from-message" flows.
- web/src/components/EditCaseModal.tsx (new) — partial-update form for
description / urgency / status; saving pushes an update to civilians.
- web/src/pages/CasesView.tsx — "+ Create case" button on the left rail,
"Edit" affordance on the right-rail case profile.
- web/src/pages/MessagesView.tsx — triage classification pill + co-mention
rule + new "Needs review" right-rail panel grouping orphan messages by
shared name. "Now playing" + "What the agent can do" tucked under
collapsible disclosures.
- web/src/lib/api.ts — createIncident, updateIncident helpers.
- web/src/lib/types.ts — TriageInfo + RecentDistressItem.triage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
End-to-end flow tying the SafeThread iOS app to the matching engine + dashboard.
/v1/*) — newserver/api/civilian.pywithregister,message,sighting,alerts/active, andWS /v1/stream. Bearer-token auth = phone. Civilian app messages land orphan (no auto-Alert); only operators promote them to cases.POST /api/incidentsandPATCH /api/incidents/{id}reuse the existing `incident_upserted` channel; iOS receives `ALERT_ISSUED` envelopes viaWS /v1/streamand `upsertAlert` replaces cards in place.Tested end-to-end against a clean Postgres volume + iOS simulator pointed at `localhost:8080`.
Test plan
Notes
🤖 Generated with Claude Code