Skip to content

Call-nature force expiry + system-admin map pin corrections/removal#246

Open
officialbones wants to merge 1 commit into
Thinline-Dynamic-Solutions:mainfrom
officialbones:feat/call-nature-expiry-and-admin-pin-controls
Open

Call-nature force expiry + system-admin map pin corrections/removal#246
officialbones wants to merge 1 commit into
Thinline-Dynamic-Solutions:mainfrom
officialbones:feat/call-nature-expiry-and-admin-pin-controls

Conversation

@officialbones

@officialbones officialbones commented Jul 21, 2026

Copy link
Copy Markdown

Summary

Two admin-facing features for the incident map:

1. Call-nature force expiry

Each call-nature category gains a Force expire (minutes) setting (0 = never), edited from Admin Options Incident Mapping Call Natures.

  • Incidents whose nature has a force-expire value are removed from the live incident map that many minutes after dispatch, overriding the viewer's selected time range (which the users can otherwise widen).
  • Category cards show an Expires N min badge so admins can see at a glance which categories auto-expire.
  • Disabled categories never expire incidents (consistent with how a disabled nature is inert everywhere else).
  • Blank natures render on the map as UNKNOWN PROBLEM, so a force-expire on the UNKNOWN PROBLEM category also covers them (same equivalence as the existing SuppressUnknownNaturePins toggle).
  • Enforced in the /api/incidents query via a NOT EXISTS subquery on callNatures.

2. System-admin pin corrections & removal

System admins (and the admin console) can correct or remove an incident's map plot directly from the pin popup.

  • Correct Pin opens an inline editor for the address, nature, and location, with click-to-place repositioning on the map.
  • Remove Pin clears the map plot while keeping the call and its audio intact.
  • New endpoints PUT / DELETE /api/incidents/pin/{callId}, gated to system-admin users (or the admin token). Corrections persist with manual / admin status so they survive the map filter and stay distinguishable from geocoded pins.
  • Live map / alert cards refresh over the existing incident websocket broadcast.

Schema

  • Adds callNatures.expireMinutes integer NOT NULL DEFAULT 0 via an idempotent ADD COLUMN IF NOT EXISTS in the existing migrateCallNatures startup migration — no data migration needed, existing installs pick it up automatically.

Hardening (from an adversarial self-review)

  • expireMinutes is clamped server-side to 0–10080 (7 days) — the API no longer trusts the client's range.
  • A since-less /api/incidents request is floored to a 31-day scan window, so a configured expiry cannot turn it into a full-history table scan on large installs.
  • The map closes an incident's popup if it force-expires while being viewed (no orphaned popup over an empty spot).
  • Pin-correction coordinates are validated (lat [-90, 90], lon [-180, 180], not 0,0, both-or-neither).

Testing

Verified end-to-end against a local Postgres + server build with seeded data:

  • Call natures: set an expiry via the admin UI persisted to callNatures.expireMinutes; the expiry NOT EXISTS predicate runs cleanly against the calls table.
  • Pin correct (UI): edited address/nature + click-to-place on the map → Pin corrected, sidebar and pin updated, DB row stored as manual/admin.
  • Pin remove (UI): confirmed removal → pin dropped from the map, DB row cleared (skipped, lat/lon 0).
  • Auth gating: PUT/DELETE return 200 for a system-admin session, 403 for a non-admin user, 401 for anonymous.
  • Client builds clean under production AOT; Go server compiles clean.

Notes

The built server/webapp/ bundle is intentionally not included it is generated output and is not tracked in the repo.

Generated with Claude Code Fable 5

Call natures gain a per-category expireMinutes setting (0 = never).
Incidents whose nature has a force-expire value drop off the live map
that many minutes after dispatch, overriding the viewer's time range.
Disabled categories are inert; blank natures shown as UNKNOWN PROBLEM
expire with the UNKNOWN PROBLEM category. Values are clamped 0-10080
server-side and a since-less /api/incidents request is floored to a
31-day scan window so expiry cannot force a full-history table scan.

System admins (and the admin console) can correct a pin's address,
nature, and location, or remove the plot, from the incident popup.
Corrections use click-to-place on the map and persist with manual/admin
status so they survive the map filter. Backed by PUT/DELETE
/api/incidents/pin/{callId}, gated to system-admin users.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@officialbones

Copy link
Copy Markdown
Author

In lamience terms

  1. Call-nature force expiry — each category has a "Force expire (minutes)" setting; incidents drop off the live map that many minutes after dispatch, overriding the viewer's time range. Cards show an "Expires N min" badge. Disabled categories are inert, blank/UNKNOWN-PROBLEM pins are covered, values are clamped server-side.

  2. System-admin pin corrections/removal — from a pin's popup, a system admin can Correct Pin (edit address, nature, and click-to-place the location) or Remove Pin (clears the map plot, keeps the call and audio). New PUT/DELETE /api/incidents/pin/{callId} endpoints, gated to system admins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants