Appearance
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 — Fixed in v0.3.2
Fixed: The app now calls GET /v1/me/membership on every startup and restores the user directly into their group if server-side membership exists. The invite-code screen is only shown to genuinely new users.
Alert notifications are silent and do not persist
bug critical high — Largely fixed in v0.3.2
Fixed:
- Critical / alarm-level sound — Android: native
withAlarmChannelconfig plugin creates notification channel withAudioAttributes.USAGE_ALARM+setBypassDnd(true)+ custom 29-second siren. iOS: Critical Alerts entitlement configured withapns-priority: 10,critical: 1,volume: 1.0. Alerts bypass DND and silent mode. - Address detail in payload — Alert text is encrypted per-recipient on-device, transmitted as opaque envelopes, and decrypted on the recipient's device. GPS coordinates are rendered as tappable links that open in the native maps app.
- In-app persistence — Active incident card displays the decrypted alert with status until resolved by a manager.
- Sender exclusion — The sender's own device does not receive the alarm notification, protecting users who may be under duress.
Remaining: Full in-app alert history (scrollable list of past incidents) is not yet implemented.
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
groupIdto 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: string→groupIds: 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 high — Implemented 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/auditwith role-based scoping
iOS Critical Alerts entitlement
feature critical high — Implemented in v0.3.2
Done: APNs payload includes { "sound": { "critical": 1, "volume": 1.0 }, "interruption-level": "critical" }. The com.apple.developer.usernotifications.critical-alerts entitlement is configured in app.json. FCM payload builder in the API enables critical alerts when ENABLE_IOS_CRITICAL_ALERTS=true.
Pending: Apple entitlement approval (external process — submitted).
Android alarm-priority notifications
feature critical high — Implemented in v0.3.2
Done: Native withAlarmChannel Expo config plugin creates the "alerts" notification channel in MainApplication.onCreate with AudioAttributes.USAGE_ALARM + setBypassDnd(true) + custom 29-second siren (alarm.wav). ACCESS_NOTIFICATION_POLICY and USE_FULL_SCREEN_INTENT permissions are declared. FCM payloads target the alerts channel with HIGH priority.
Alert persistence and incident lifecycle
feature high — Partially implemented in v0.3.2
Done:
- Active incident card displays on the home screen with decrypted alert text, GPS link, and timestamp
- Manager can resolve incidents from admin dashboard with resolution notes
- Resolution sends FCM push to group confirming resolution
- FCM metadata includes
incidentId,groupId,kind,hasEnvelope
Still planned:
- Scrollable alert history list (past resolved incidents)
- Write alerts to local storage for offline persistence
- "I'm aware" acknowledgement from members
Recently completed
Member transfer between groups
feature admin — Implemented in v0.3.2
Managers can transfer members between groups from the admin dashboard. Checkbox multi-select with a transfer dropdown.
Zone map picker (geohash-5)
feature admin — Implemented in v0.3.2
Interactive Australia map with Leaflet + OpenStreetMap for selecting a group's zone ID. Uses geohash-5 (~5km grid cells) for coarse location. Suburb search via Nominatim (filtered to AU).
Admin version/device columns
feature admin — Implemented in v0.3.2
Members table shows Platform, App Version, and Last Seen columns from device telemetry.
Manual key rotation (user-side)
feature mobile — Implemented in v0.3.2
Users can rotate their encryption keys from the settings menu. Confirmation dialog, generates new KEM keypair, registers with server.
GPS coordinates as map links
feature mobile — Implemented in v0.3.2
GPS coordinates in decrypted alerts are rendered as tappable blue links. One tap opens Google Maps (Android) or Apple Maps (iOS).
Sender excluded from own alert
feature safety — Implemented in v0.3.2
The sender's device does not receive the alarm notification, protecting users who may be under duress.
User-friendly error messages
feature ux — Implemented in v0.3.2
All operational errors show "Please contact your group manager. Support error ref: <code> [route]" — directing users to their manager with an actionable ref code.
Group membership sync on startup
feature mobile — Implemented in v0.3.2
App always calls /v1/me/membership on startup and updates local cache if the server-side group has changed (e.g. after admin transfer).
Crypto polyfill for Hermes
feature mobile — Implemented in v0.3.2
globalThis.crypto.getRandomValues polyfilled at app startup using expo-crypto, enabling pure-JS mlkem + @noble/ciphers to run on Hermes engine.
Completed (v1.0.1+)
Incident management & audit log (admin)
feature high — Implemented 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 critical — Fixed 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
feature — Fixed 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).

