Skip to content

Doc status: Latest (rolling). See Versions.

This page tracks planned features, UX improvements, and known issues that are documented but not yet implemented. Items are grouped by priority and labelled with their category.


Known Issues

Re-login still prompts for invite code when membership exists

bug ux high

Current behaviour: When a user with an existing UID, active license, and group membership signs back in (e.g. after clearing app data or reinstalling), the app still presents the "Enter invite code" screen — even though the server already knows their group association.

Expected behaviour: The app should detect the existing membership via GET /v1/me/membership and restore the user directly into their group without requiring an invite code.

Context: The recovery endpoint already exists and works (added in v1.0.0). The mobile post-login flow calls it, but currently falls through to the invite-code screen if local state is empty — it should instead use the API response to skip the invite step entirely.

Affected versions: v1.0.0, v1.0.1

Alert notifications are silent and do not persist

bug critical high

Current behaviour: When an alert is triggered, recipients receive a standard push notification with default message-tone priority. On silent/DND mode the notification makes no sound. The notification text is generic ("Neighbourhood — alert triggered nearby") with no address detail. Once the notification is dismissed or the app is opened, the alert disappears entirely — there is no in-app record of it.

Expected behaviour:

  1. Critical / alarm-level sound — Alert notifications must behave like a "Find My Phone" alarm: full-volume, bypass silent/DND, persist audibly until the user unlocks the phone and acknowledges. On iOS this requires the Critical Alerts entitlement. On Android this requires an alarm-priority notification channel with IMPORTANCE_MAX / fullScreenIntent.
  2. Address detail in payload — The decrypted address text should be displayed in the notification body (encrypted in transit, decrypted on-device before display).
  3. In-app persistence — The alert message and timestamp must persist in the app's alert list in plaintext until a manager clears/resolves the incident from the admin dashboard. Users should be able to re-read the alert at any time.

Affected versions: v1.0.0, v1.0.1


Planned Features

"Join a different group" button

feature ux medium

Add an in-app option (accessible from Settings or the group info screen) that allows a user to leave their current group and join a different one by entering a new invite code.

Acceptance criteria:

  • Button visible in Settings / group info area
  • Tapping it confirms the action ("You will leave [group name]. Continue?")
  • On confirm, clears local group state and prompts for a new invite code
  • Server-side: updates the user's groupId to the new group, cleans up old crypto keys

Multi-group membership

feature future

Allow users to be members of more than one neighbourhood group simultaneously.

Scope:

  • User can hold memberships in multiple groups
  • Group switcher UI in the app (e.g. tab or dropdown)
  • Alerts are scoped to the currently-active group (or optionally all groups)
  • Each group has independent admin controls (pause/ban per group)
  • Crypto keys are per-group (each group has its own KEM key pair)

Considerations:

  • Data model change: user doc groupId: stringgroupIds: string[] (or a subcollection)
  • Push notification routing: fan-out must target the correct group's members
  • License model: does each group need its own license, or does one license cover multi-group?
  • UX: keep it simple — avoid overwhelming users who only need one group

Dependencies: "Join a different group" should ship first as a stepping stone.

Incident lifecycle (acknowledge / close) — partially implemented ✅

feature future

Delivered (admin side):

  • Admin can resolve an incident from the admin dashboard with optional resolution note
  • Resolution sends FCM push notification to the group confirming resolution
  • Incidents tab in admin dashboard shows all incidents across managed groups with status filter
  • Incident detail modal with full note timeline, add-note form, and resolve action
  • Incident notes support visibility levels: public (all managers), manager only, super admin only
  • API: POST /v1/admin/groups/:gid/incidents/:iid/resolve, GET/POST .../notes

Still planned:

  • Member "I'm aware" acknowledgement (mobile app)
  • In-app incident history screen (mobile app)
  • Strict permissions: only the original reporter or an admin can close

Admin audit log UI ✅

feature highImplemented in v0.7.0

Full audit log surfaced in the admin dashboard with role-based scoping.

Delivered:

  • Super admin view: All events across all groups — create_group, set_member_status, broadcast, trigger_incident, set_user_role, grant_license, revoke_license, add_incident_note, resolve_incident
  • Manager view: Only events for their own group(s)
  • Filterable by action, email, group (text search)
  • Action-colour-coded table with 100-row pagination
  • API: GET /v1/admin/audit with role-based scoping

iOS Critical Alerts entitlement

feature critical high

Why: Standard iOS push notifications respect silent mode and Do Not Disturb. For a neighbourhood emergency alert system this is unacceptable — alerts must sound at full volume regardless of device settings.

Apple Critical Alerts:

  • Requires a special entitlement granted by Apple (not available by default)
  • Application via Apple entitlement request form
  • Must demonstrate the app serves a genuine safety/health/security purpose
  • Once approved, the provisioning profile is updated and the app can send notifications with { "sound": { "critical": 1, "volume": 1.0 } } in the APNs payload
  • Critical Alerts bypass Do Not Disturb, silent mode, and Focus modes
  • A dedicated UI toggle in iOS Settings allows users to disable Critical Alerts per-app (Apple requirement)

Action items:

  1. Submit the entitlement request to Apple with justification (neighbourhood emergency safety system)
  2. Update the FCM payload builder in the API to include the critical alert sound payload when the entitlement is approved
  3. Update the iOS notification channel / category configuration in the Expo config
  4. Test on a physical device in DND mode

Android alarm-priority notifications

feature critical high

Why: Android respects DND for standard notification channels. Emergency alerts need to bypass this.

Android approach:

  • Create a notification channel with IMPORTANCE_HIGH or IMPORTANCE_MAX (alarm level)
  • Set the channel to bypass DND: setBypassDnd(true) (requires ACCESS_NOTIFICATION_POLICY permission)
  • Use fullScreenIntent to wake the device and show an interstitial alert activity
  • Use a custom alarm sound (looping) that plays until the user interacts
  • On Android 14+, check canUseFullScreenIntent() and request permission if needed
  • Configure via expo-notifications channel settings or a custom config plugin

Action items:

  1. Create a dedicated "Emergency Alert" notification channel in the Expo config with alarm-level importance
  2. Add ACCESS_NOTIFICATION_POLICY to AndroidManifest.xml via config plugin
  3. Implement a full-screen intent activity that shows the alert and plays alarm sound
  4. Test on physical device in DND mode

Alert persistence and incident lifecycle

feature high

Alerts must persist in-app until explicitly cleared by a manager.

Scope:

  • When an alert is received, write it to local storage (AsyncStorage / SQLite) with: message, timestamp, sender, group, status (active / resolved)
  • Display an "Active Alerts" list in the app — visible on the home/main screen
  • Alert remains in the list with active status until a manager resolves it from the admin dashboard
  • When resolved, a push notification is sent to the group: "Alert resolved by [manager]"
  • App updates the local alert status to resolved (greyed out, moved to history)
  • Admin dashboard: "Resolve Alert" button per active incident

Dependencies: Admin audit log (to record who resolved and when)


Completed (v1.0.1+)

Incident management & audit log (admin)

feature highImplemented in v0.7.0

Full incident management with ticketing, notes with visibility levels, resolution workflow, and comprehensive audit logging. See entries above for details.

Notification listener crash on Android

bug criticalFixed in v1.0.1

Notifications.removeNotificationSubscription() was removed in expo-notifications 0.32.x. The useEffect cleanup called this undefined function, causing a crash loop after Google Sign-In. Fixed by switching to subscription.remove().

Reinstall recovery

featureFixed in v1.0.0

Server now persists groupId on the user document. New GET /v1/me/membership endpoint allows the app to recover group state after a reinstall without requiring the user to re-enter an invite code (server-side recovery works; see known issue above for the remaining client-side gap).

Neighbourhood Emergency Alert System