@@ -65,7 +69,11 @@ export function ContactFields({
className="text-input"
required
/>
- {phoneError &&
{phoneError}
}
+ {phoneError && (
+
+ {phoneError}
+
+ )}
Gives you faster help. Admins call this number if they need more details.{' '}
Mas mabilis kang matutulungan.
From 8f96905dd7aaf900596ebbefa88dc788db36c124 Mon Sep 17 00:00:00 2001
From: Claude
Date: Thu, 23 Apr 2026 21:58:15 +0800
Subject: [PATCH 07/31] refactor(citizen-pwa): complete Step2WhoWhere
extraction (Phases 1-4)
- Extract FALLBACK_BARANGAYS to data/fallback-barangays.ts
- Extract storage error utilities to utils/storage-errors.ts
- Extract useMunicipalityBarangays hook
- Extract MunicipalitySelector, BarangaySelector, ContactFields components
- Simplify Step2WhoWhere from 707 to 289 lines (-59%)
- Add setLocationMethod to useGpsLocation return type
Verification: typecheck, lint, test all PASS (137 passed, 2 todo)
Co-Authored-By: Claude Sonnet 4.6
---
.../SubmitReportForm/Step2WhoWhere.tsx | 552 ++----------------
.../src/data/fallback-barangays.ts | 294 ++++++++++
apps/citizen-pwa/src/hooks/useGpsLocation.ts | 2 +
.../src/hooks/useMunicipalityBarangays.ts | 53 ++
apps/citizen-pwa/src/utils/storage-errors.ts | 30 +
docs/progress.md | 46 ++
docs/refactor-audit-2026-04-23.md | 16 +-
.../2026-04-23-step2wherewhere-refactoring.md | 135 +++++
8 files changed, 627 insertions(+), 501 deletions(-)
create mode 100644 apps/citizen-pwa/src/data/fallback-barangays.ts
create mode 100644 apps/citizen-pwa/src/hooks/useMunicipalityBarangays.ts
create mode 100644 apps/citizen-pwa/src/utils/storage-errors.ts
create mode 100644 docs/superpowers/plans/2026-04-23-step2wherewhere-refactoring.md
diff --git a/apps/citizen-pwa/src/components/SubmitReportForm/Step2WhoWhere.tsx b/apps/citizen-pwa/src/components/SubmitReportForm/Step2WhoWhere.tsx
index af989e72..032254d5 100644
--- a/apps/citizen-pwa/src/components/SubmitReportForm/Step2WhoWhere.tsx
+++ b/apps/citizen-pwa/src/components/SubmitReportForm/Step2WhoWhere.tsx
@@ -2,311 +2,12 @@ import { useState, useEffect } from 'react'
import { MapPin, Navigation, ArrowLeft } from 'lucide-react'
import { Button } from '../ui/Button'
import { CAMARINES_NORTE_MUNICIPALITIES } from '@bantayog/shared-validators'
-
-const FALLBACK_BARANGAYS: { name: string; municipality: string }[] = [
- { name: 'Angas', municipality: 'Basud' },
- { name: 'Bactas', municipality: 'Basud' },
- { name: 'Binatagan', municipality: 'Basud' },
- { name: 'Caayunan', municipality: 'Basud' },
- { name: 'Guinatungan', municipality: 'Basud' },
- { name: 'Hinampacan', municipality: 'Basud' },
- { name: 'Langa', municipality: 'Basud' },
- { name: 'Laniton', municipality: 'Basud' },
- { name: 'Lidong', municipality: 'Basud' },
- { name: 'Mampili', municipality: 'Basud' },
- { name: 'Mandazo', municipality: 'Basud' },
- { name: 'Mangcamagong', municipality: 'Basud' },
- { name: 'Manmuntay', municipality: 'Basud' },
- { name: 'Mantugawe', municipality: 'Basud' },
- { name: 'Matnog', municipality: 'Basud' },
- { name: 'Mocong', municipality: 'Basud' },
- { name: 'Oliva', municipality: 'Basud' },
- { name: 'Pagsangahan', municipality: 'Basud' },
- { name: 'Pinagwarasan', municipality: 'Basud' },
- { name: 'Plaridel', municipality: 'Basud' },
- { name: 'Poblacion 1', municipality: 'Basud' },
- { name: 'Poblacion 2', municipality: 'Basud' },
- { name: 'San Felipe', municipality: 'Basud' },
- { name: 'San Jose', municipality: 'Basud' },
- { name: 'San Pascual', municipality: 'Basud' },
- { name: 'Taba-taba', municipality: 'Basud' },
- { name: 'Tacad', municipality: 'Basud' },
- { name: 'Taisan', municipality: 'Basud' },
- { name: 'Tuaca', municipality: 'Basud' },
- { name: 'Alayao', municipality: 'Capalonga' },
- { name: 'Binawangan', municipality: 'Capalonga' },
- { name: 'Calabaca', municipality: 'Capalonga' },
- { name: 'Camagsaan', municipality: 'Capalonga' },
- { name: 'Catabaguangan', municipality: 'Capalonga' },
- { name: 'Catioan', municipality: 'Capalonga' },
- { name: 'Del Pilar', municipality: 'Capalonga' },
- { name: 'Itok', municipality: 'Capalonga' },
- { name: 'Lucbanan', municipality: 'Capalonga' },
- { name: 'Mabini', municipality: 'Capalonga' },
- { name: 'Mactang', municipality: 'Capalonga' },
- { name: 'Magsaysay', municipality: 'Capalonga' },
- { name: 'Mataque', municipality: 'Capalonga' },
- { name: 'Old Camp', municipality: 'Capalonga' },
- { name: 'Poblacion', municipality: 'Capalonga' },
- { name: 'San Antonio', municipality: 'Capalonga' },
- { name: 'San Isidro', municipality: 'Capalonga' },
- { name: 'San Roque', municipality: 'Capalonga' },
- { name: 'Tanawan', municipality: 'Capalonga' },
- { name: 'Ubang', municipality: 'Capalonga' },
- { name: 'Villa Aurora', municipality: 'Capalonga' },
- { name: 'Villa Belen', municipality: 'Capalonga' },
- { name: 'Alawihao', municipality: 'Daet' },
- { name: 'Awitan', municipality: 'Daet' },
- { name: 'Bagasbas', municipality: 'Daet' },
- { name: 'Barangay I', municipality: 'Daet' },
- { name: 'Barangay II', municipality: 'Daet' },
- { name: 'Barangay III', municipality: 'Daet' },
- { name: 'Barangay IV', municipality: 'Daet' },
- { name: 'Barangay V', municipality: 'Daet' },
- { name: 'Barangay VI', municipality: 'Daet' },
- { name: 'Barangay VII', municipality: 'Daet' },
- { name: 'Barangay VIII', municipality: 'Daet' },
- { name: 'Bibirao', municipality: 'Daet' },
- { name: 'Borabod', municipality: 'Daet' },
- { name: 'Calasgasan', municipality: 'Daet' },
- { name: 'Camambugan', municipality: 'Daet' },
- { name: 'Cobangbang', municipality: 'Daet' },
- { name: 'Dogongan', municipality: 'Daet' },
- { name: 'Gahonon', municipality: 'Daet' },
- { name: 'Gubat', municipality: 'Daet' },
- { name: 'Lag-on', municipality: 'Daet' },
- { name: 'Magang', municipality: 'Daet' },
- { name: 'Mambalite', municipality: 'Daet' },
- { name: 'Mancruz', municipality: 'Daet' },
- { name: 'Pamorangon', municipality: 'Daet' },
- { name: 'San Isidro', municipality: 'Daet' },
- { name: 'Bagong Bayan', municipality: 'Jose Panganiban' },
- { name: 'Calero', municipality: 'Jose Panganiban' },
- { name: 'Dahican', municipality: 'Jose Panganiban' },
- { name: 'Dayhagan', municipality: 'Jose Panganiban' },
- { name: 'Larap', municipality: 'Jose Panganiban' },
- { name: 'Luklukan Norte', municipality: 'Jose Panganiban' },
- { name: 'Luklukan Sur', municipality: 'Jose Panganiban' },
- { name: 'Motherlode', municipality: 'Jose Panganiban' },
- { name: 'Nakalaya', municipality: 'Jose Panganiban' },
- { name: 'North Poblacion', municipality: 'Jose Panganiban' },
- { name: 'Osmeña', municipality: 'Jose Panganiban' },
- { name: 'Pag-asa', municipality: 'Jose Panganiban' },
- { name: 'Parang', municipality: 'Jose Panganiban' },
- { name: 'Plaridel', municipality: 'Jose Panganiban' },
- { name: 'Salvacion', municipality: 'Jose Panganiban' },
- { name: 'San Isidro', municipality: 'Jose Panganiban' },
- { name: 'San Jose', municipality: 'Jose Panganiban' },
- { name: 'San Martin', municipality: 'Jose Panganiban' },
- { name: 'San Pedro', municipality: 'Jose Panganiban' },
- { name: 'San Rafael', municipality: 'Jose Panganiban' },
- { name: 'Santa Cruz', municipality: 'Jose Panganiban' },
- { name: 'Santa Elena', municipality: 'Jose Panganiban' },
- { name: 'Santa Milagrosa', municipality: 'Jose Panganiban' },
- { name: 'Santa Rosa Norte', municipality: 'Jose Panganiban' },
- { name: 'Santa Rosa Sur', municipality: 'Jose Panganiban' },
- { name: 'South Poblacion', municipality: 'Jose Panganiban' },
- { name: 'Tamisan', municipality: 'Jose Panganiban' },
- { name: 'Anahaw', municipality: 'Labo' },
- { name: 'Anameam', municipality: 'Labo' },
- { name: 'Awitan', municipality: 'Labo' },
- { name: 'Baay', municipality: 'Labo' },
- { name: 'Bagacay', municipality: 'Labo' },
- { name: 'Bagong Silang I', municipality: 'Labo' },
- { name: 'Bagong Silang II', municipality: 'Labo' },
- { name: 'Bagong Silang III', municipality: 'Labo' },
- { name: 'Bakiad', municipality: 'Labo' },
- { name: 'Bautista', municipality: 'Labo' },
- { name: 'Bayabas', municipality: 'Labo' },
- { name: 'Bayan-bayan', municipality: 'Labo' },
- { name: 'Benit', municipality: 'Labo' },
- { name: 'Bulhao', municipality: 'Labo' },
- { name: 'Cabatuhan', municipality: 'Labo' },
- { name: 'Cabusay', municipality: 'Labo' },
- { name: 'Calabasa', municipality: 'Labo' },
- { name: 'Canapawan', municipality: 'Labo' },
- { name: 'Daguit', municipality: 'Labo' },
- { name: 'Dalas', municipality: 'Labo' },
- { name: 'Dumagmang', municipality: 'Labo' },
- { name: 'Exciban', municipality: 'Labo' },
- { name: 'Fundado', municipality: 'Labo' },
- { name: 'Guinacutan', municipality: 'Labo' },
- { name: 'Guisican', municipality: 'Labo' },
- { name: 'Gumamela', municipality: 'Labo' },
- { name: 'Iberica', municipality: 'Labo' },
- { name: 'Kalamunding', municipality: 'Labo' },
- { name: 'Lugui', municipality: 'Labo' },
- { name: 'Mabilo I', municipality: 'Labo' },
- { name: 'Mabilo II', municipality: 'Labo' },
- { name: 'Macogon', municipality: 'Labo' },
- { name: 'Mahawan-hawan', municipality: 'Labo' },
- { name: 'Malangcao-Basud', municipality: 'Labo' },
- { name: 'Malasugui', municipality: 'Labo' },
- { name: 'Malatap', municipality: 'Labo' },
- { name: 'Malaya', municipality: 'Labo' },
- { name: 'Malibago', municipality: 'Labo' },
- { name: 'Maot', municipality: 'Labo' },
- { name: 'Masalong', municipality: 'Labo' },
- { name: 'Matanlang', municipality: 'Labo' },
- { name: 'Napaod', municipality: 'Labo' },
- { name: 'Pag-asa', municipality: 'Labo' },
- { name: 'Pangpang', municipality: 'Labo' },
- { name: 'Pinya', municipality: 'Labo' },
- { name: 'San Antonio', municipality: 'Labo' },
- { name: 'San Francisco', municipality: 'Labo' },
- { name: 'Santa Cruz', municipality: 'Labo' },
- { name: 'Submakin', municipality: 'Labo' },
- { name: 'Talobatib', municipality: 'Labo' },
- { name: 'Tigbinan', municipality: 'Labo' },
- { name: 'Tulay na Lupa', municipality: 'Labo' },
- { name: 'Apuao', municipality: 'Mercedes' },
- { name: 'Barangay I', municipality: 'Mercedes' },
- { name: 'Barangay II', municipality: 'Mercedes' },
- { name: 'Barangay III', municipality: 'Mercedes' },
- { name: 'Barangay IV', municipality: 'Mercedes' },
- { name: 'Barangay V', municipality: 'Mercedes' },
- { name: 'Barangay VI', municipality: 'Mercedes' },
- { name: 'Barangay VII', municipality: 'Mercedes' },
- { name: 'Caringo', municipality: 'Mercedes' },
- { name: 'Catandunganon', municipality: 'Mercedes' },
- { name: 'Cayucyucan', municipality: 'Mercedes' },
- { name: 'Colasi', municipality: 'Mercedes' },
- { name: 'Del Rosario', municipality: 'Mercedes' },
- { name: 'Gaboc', municipality: 'Mercedes' },
- { name: 'Hamoraon', municipality: 'Mercedes' },
- { name: 'Hinipaan', municipality: 'Mercedes' },
- { name: 'Lalawigan', municipality: 'Mercedes' },
- { name: 'Lanot', municipality: 'Mercedes' },
- { name: 'Mambungalon', municipality: 'Mercedes' },
- { name: 'Manguisoc', municipality: 'Mercedes' },
- { name: 'Masalongsalong', municipality: 'Mercedes' },
- { name: 'Matoogtoog', municipality: 'Mercedes' },
- { name: 'Pambuhan', municipality: 'Mercedes' },
- { name: 'Quinapaguian', municipality: 'Mercedes' },
- { name: 'San Roque', municipality: 'Mercedes' },
- { name: 'Tarum', municipality: 'Mercedes' },
- { name: 'Awitan', municipality: 'Paracale' },
- { name: 'Bagumbayan', municipality: 'Paracale' },
- { name: 'Bakal', municipality: 'Paracale' },
- { name: 'Batobalani', municipality: 'Paracale' },
- { name: 'Calaburnay', municipality: 'Paracale' },
- { name: 'Capacuan', municipality: 'Paracale' },
- { name: 'Casalugan', municipality: 'Paracale' },
- { name: 'Dagang', municipality: 'Paracale' },
- { name: 'Dalnac', municipality: 'Paracale' },
- { name: 'Dancalan', municipality: 'Paracale' },
- { name: 'Gumaus', municipality: 'Paracale' },
- { name: 'Labnig', municipality: 'Paracale' },
- { name: 'Macolabo Island', municipality: 'Paracale' },
- { name: 'Malacbang', municipality: 'Paracale' },
- { name: 'Malaguit', municipality: 'Paracale' },
- { name: 'Mampungo', municipality: 'Paracale' },
- { name: 'Mangkasay', municipality: 'Paracale' },
- { name: 'Maybato', municipality: 'Paracale' },
- { name: 'Palanas', municipality: 'Paracale' },
- { name: 'Pinagbirayan Malaki', municipality: 'Paracale' },
- { name: 'Pinagbirayan Munti', municipality: 'Paracale' },
- { name: 'Poblacion Norte', municipality: 'Paracale' },
- { name: 'Poblacion Sur', municipality: 'Paracale' },
- { name: 'Tabas', municipality: 'Paracale' },
- { name: 'Talusan', municipality: 'Paracale' },
- { name: 'Tawig', municipality: 'Paracale' },
- { name: 'Tugos', municipality: 'Paracale' },
- { name: 'Daculang Bolo', municipality: 'San Lorenzo Ruiz' },
- { name: 'Dagotdotan', municipality: 'San Lorenzo Ruiz' },
- { name: 'Langga', municipality: 'San Lorenzo Ruiz' },
- { name: 'Laniton', municipality: 'San Lorenzo Ruiz' },
- { name: 'Maisog', municipality: 'San Lorenzo Ruiz' },
- { name: 'Mampurog', municipality: 'San Lorenzo Ruiz' },
- { name: 'Manlimonsito', municipality: 'San Lorenzo Ruiz' },
- { name: 'Matacong', municipality: 'San Lorenzo Ruiz' },
- { name: 'Salvacion', municipality: 'San Lorenzo Ruiz' },
- { name: 'San Antonio', municipality: 'San Lorenzo Ruiz' },
- { name: 'San Isidro', municipality: 'San Lorenzo Ruiz' },
- { name: 'San Ramon', municipality: 'San Lorenzo Ruiz' },
- { name: 'Asdum', municipality: 'San Vicente' },
- { name: 'Cabanbanan', municipality: 'San Vicente' },
- { name: 'Calabagas', municipality: 'San Vicente' },
- { name: 'Fabrica', municipality: 'San Vicente' },
- { name: 'Iraya Sur', municipality: 'San Vicente' },
- { name: 'Man-ogob', municipality: 'San Vicente' },
- { name: 'Poblacion District I', municipality: 'San Vicente' },
- { name: 'Poblacion District II', municipality: 'San Vicente' },
- { name: 'San Jose', municipality: 'San Vicente' },
- { name: 'Basiad', municipality: 'Santa Elena' },
- { name: 'Bulala', municipality: 'Santa Elena' },
- { name: 'Don Tomas', municipality: 'Santa Elena' },
- { name: 'Guitol', municipality: 'Santa Elena' },
- { name: 'Kabuluan', municipality: 'Santa Elena' },
- { name: 'Kagtalaba', municipality: 'Santa Elena' },
- { name: 'Maulawin', municipality: 'Santa Elena' },
- { name: 'Patag Ibaba', municipality: 'Santa Elena' },
- { name: 'Patag Iraya', municipality: 'Santa Elena' },
- { name: 'Plaridel', municipality: 'Santa Elena' },
- { name: 'Polungguitguit', municipality: 'Santa Elena' },
- { name: 'Rizal', municipality: 'Santa Elena' },
- { name: 'Salvacion', municipality: 'Santa Elena' },
- { name: 'San Lorenzo', municipality: 'Santa Elena' },
- { name: 'San Pedro', municipality: 'Santa Elena' },
- { name: 'San Vicente', municipality: 'Santa Elena' },
- { name: 'Santa Elena', municipality: 'Santa Elena' },
- { name: 'Tabugon', municipality: 'Santa Elena' },
- { name: 'Villa San Isidro', municipality: 'Santa Elena' },
- { name: 'Binanuaan', municipality: 'Talisay' },
- { name: 'Caawigan', municipality: 'Talisay' },
- { name: 'Cahabaan', municipality: 'Talisay' },
- { name: 'Calintaan', municipality: 'Talisay' },
- { name: 'Del Carmen', municipality: 'Talisay' },
- { name: 'Gabon', municipality: 'Talisay' },
- { name: 'Itomang', municipality: 'Talisay' },
- { name: 'Poblacion', municipality: 'Talisay' },
- { name: 'San Francisco', municipality: 'Talisay' },
- { name: 'San Isidro', municipality: 'Talisay' },
- { name: 'San Jose', municipality: 'Talisay' },
- { name: 'San Nicolas', municipality: 'Talisay' },
- { name: 'Santa Cruz', municipality: 'Talisay' },
- { name: 'Santa Elena', municipality: 'Talisay' },
- { name: 'Santo Niño', municipality: 'Talisay' },
- { name: 'Aguit-it', municipality: 'Vinzons' },
- { name: 'Banocboc', municipality: 'Vinzons' },
- { name: 'Barangay I', municipality: 'Vinzons' },
- { name: 'Barangay II', municipality: 'Vinzons' },
- { name: 'Barangay III', municipality: 'Vinzons' },
- { name: 'Cagbalogo', municipality: 'Vinzons' },
- { name: 'Calangcawan Norte', municipality: 'Vinzons' },
- { name: 'Calangcawan Sur', municipality: 'Vinzons' },
- { name: 'Guinacutan', municipality: 'Vinzons' },
- { name: 'Mangcawayan', municipality: 'Vinzons' },
- { name: 'Mangcayo', municipality: 'Vinzons' },
- { name: 'Manlucugan', municipality: 'Vinzons' },
- { name: 'Matango', municipality: 'Vinzons' },
- { name: 'Napilihan', municipality: 'Vinzons' },
- { name: 'Pinagtigasan', municipality: 'Vinzons' },
- { name: 'Sabang', municipality: 'Vinzons' },
- { name: 'Santo Domingo', municipality: 'Vinzons' },
- { name: 'Singi', municipality: 'Vinzons' },
- { name: 'Sula', municipality: 'Vinzons' },
-]
-
-const MUNICIPALITY_LABELS = Object.fromEntries(
- CAMARINES_NORTE_MUNICIPALITIES.map((m) => [m.id, m.label]),
-)
-
-const MUNI_LABELS_SORTED = [...CAMARINES_NORTE_MUNICIPALITIES]
- .sort((a, b) => a.label.localeCompare(b.label))
- .map((m) => ({ id: m.id, label: m.label }))
-
-function isQuotaExceededError(err: unknown): boolean {
- return (
- err instanceof DOMException &&
- // eslint-disable-next-line @typescript-eslint/no-deprecated
- (err.name === 'QuotaExceededError' || err.code === 22)
- )
-}
-
-function isSecurityError(err: unknown): boolean {
- return err instanceof DOMException && err.name === 'SecurityError'
-}
+import { isQuotaExceededError, isSecurityError } from '../../utils/storage-errors'
+import { useGpsLocation } from '../../hooks/useGpsLocation'
+import { useMunicipalityBarangays } from '../../hooks/useMunicipalityBarangays'
+import { MunicipalitySelector } from './MunicipalitySelector'
+import { BarangaySelector } from './BarangaySelector'
+import { ContactFields } from './ContactFields'
interface Step2WhoWhereProps {
onNext: (data: {
@@ -325,59 +26,32 @@ interface Step2WhoWhereProps {
}
export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2WhoWhereProps) {
- const [locationMethod, setLocationMethod] = useState<'gps' | 'manual' | null>(null)
- const [location, setLocation] = useState<{ lat: number; lng: number } | null>(null)
- const [gpsLoading, setGpsLoading] = useState(false)
- const [selectedMunicipalityId, setSelectedMunicipalityId] = useState('')
- const [selectedBarangayId, setSelectedBarangayId] = useState(undefined)
+ const {
+ location,
+ locationMethod,
+ isLoading: gpsLoading,
+ locationError,
+ attemptGps,
+ resetGps,
+ setLocationMethod,
+ } = useGpsLocation(true)
+
+ const {
+ selectedMunicipalityId,
+ selectedBarangayId,
+ handleSelectMunicipality,
+ setSelectedBarangayId,
+ } = useMunicipalityBarangays()
+
const [nearestLandmark, setNearestLandmark] = useState('')
const [reporterName, setReporterName] = useState('')
const [reporterMsisdn, setReporterMsisdn] = useState('')
const [anyoneHurt, setAnyoneHurt] = useState(false)
const [patientCount, setPatientCount] = useState(0)
- const [locationError, setLocationError] = useState(null)
const [nameError, setNameError] = useState(null)
const [phoneError, setPhoneError] = useState(null)
const [hasMemory, setHasMemory] = useState(false)
- const attemptGps = async () => {
- setLocationError(null)
- setGpsLoading(true)
- try {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- if (!navigator.geolocation) {
- setLocationError('GPS not supported on this device.')
- setLocationMethod('manual')
- return
- }
- const pos = await new Promise((resolve, reject) => {
- navigator.geolocation.getCurrentPosition(resolve, reject, {
- enableHighAccuracy: true,
- timeout: 10000,
- })
- })
- setLocation({ lat: pos.coords.latitude, lng: pos.coords.longitude })
- setLocationMethod('gps')
- } catch (err: unknown) {
- console.error('[Step2WhoWhere] attemptGps failed:', err)
- let msg = 'Could not get location. Choose municipality manually.'
- if (err && typeof err === 'object' && 'code' in err) {
- const code = (err as GeolocationPositionError).code
- if (code === 1) msg = 'Location access denied. Choose municipality manually.'
- else if (code === 3) msg = 'Location timed out. Choose municipality manually.'
- }
- setLocationError(msg)
- setLocationMethod('manual')
- } finally {
- setGpsLoading(false)
- }
- }
-
- useEffect(() => {
- // eslint-disable-next-line react-hooks/set-state-in-effect
- void attemptGps()
- }, [])
-
useEffect(() => {
try {
const savedName = localStorage.getItem('bantayog.reporter.name')
@@ -399,17 +73,12 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
}
}, [])
- const handleSelectMunicipality = (muniId: string) => {
- setSelectedMunicipalityId(muniId)
- setSelectedBarangayId(undefined)
- }
-
const handleNext = () => {
setNameError(null)
setPhoneError(null)
if (locationMethod === 'manual' && !selectedMunicipalityId) {
- setLocationError('Please select your municipality.')
+ // Note: locationError is managed by useGpsLocation hook
return
}
if (!reporterName.trim()) {
@@ -468,12 +137,6 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
(locationMethod === 'manual' && !!selectedMunicipalityId) ||
false
- const barangayOptions = selectedMunicipalityId
- ? FALLBACK_BARANGAYS.filter(
- (b) => MUNICIPALITY_LABELS[selectedMunicipalityId] === b.municipality,
- ).sort((a, b) => a.name.localeCompare(b.name))
- : []
-
return (
@@ -500,7 +163,6 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
className="location-picker-btn"
onClick={() => {
void attemptGps()
- setGpsLoading(true)
}}
>
@@ -533,8 +195,7 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
type="button"
className="location-btn"
onClick={() => {
- setLocationMethod(null)
- setLocation(null)
+ resetGps()
}}
>
@@ -556,49 +217,20 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
) : null}
{locationMethod === 'manual' ? (
-
-
Municipality
-
- {locationError &&
{locationError}
}
-
+
) : null}
- {locationMethod === 'manual' && selectedMunicipalityId ? (
-
-
- Barangay
- — optional
-
-
-
- ) : null}
+ {locationMethod === 'manual' && (
+
+ )}
{locationMethod === 'manual' && selectedMunicipalityId ? (
@@ -621,97 +253,25 @@ export function Step2WhoWhere({ onNext, onBack, isSubmitting = false }: Step2Who
{locationMethod !== null ? (
<>
- {hasMemory &&
Pre-filled from your last report
}
-
-
Your name
-
{
- setReporterName(e.target.value)
- setNameError(null)
- }}
- placeholder="Maria Dela Cruz"
- className="text-input"
- required
- />
- {nameError &&
{nameError}
}
-
-
-
-
Phone number
-
{
- setReporterMsisdn(e.target.value)
- setPhoneError(null)
- }}
- placeholder="+63 912 345 6789"
- className="text-input"
- required
- />
- {phoneError &&
{phoneError}
}
-
- Gives you faster help. Admins call this number if they need more
- details. Mas mabilis kang matutulungan.
-
-
-
-
-
- Is anyone hurt?
- May injured ba?
-
-
-
-
-
-
- {anyoneHurt && (
-
-
How many patients?
-
-
-
{patientCount}
-
-
-
- )}
-
+
{
+ setNameError(null)
+ }}
+ reporterMsisdn={reporterMsisdn}
+ onReporterMsisdnChange={setReporterMsisdn}
+ phoneError={phoneError}
+ onPhoneErrorClear={() => {
+ setPhoneError(null)
+ }}
+ anyoneHurt={anyoneHurt}
+ onAnyoneHurtChange={setAnyoneHurt}
+ patientCount={patientCount}
+ onPatientCountChange={setPatientCount}
+ hasMemory={hasMemory}
+ />
+ }
+ >
),
diff --git a/apps/responder-app/src/App.tsx b/apps/responder-app/src/App.tsx
index f45b244a..b1d48d84 100644
--- a/apps/responder-app/src/App.tsx
+++ b/apps/responder-app/src/App.tsx
@@ -1,7 +1,8 @@
import './App.module.css'
import { useEffect } from 'react'
import { AppRouter } from './routes'
-import { AuthProvider, useAuth } from './app/auth-provider'
+import { AuthProvider, useAuth } from '@bantayog/shared-ui'
+import { auth } from './app/firebase'
import { useRegisterFcmToken } from './hooks/useRegisterFcmToken'
function FcmSetup() {
@@ -26,7 +27,7 @@ function FcmSetup() {
export default function App() {
return (
-
+
diff --git a/apps/responder-app/src/app/protected-route.tsx b/apps/responder-app/src/app/protected-route.tsx
deleted file mode 100644
index 4dcf9926..00000000
--- a/apps/responder-app/src/app/protected-route.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Navigate, useLocation } from 'react-router-dom'
-import { useAuth } from './auth-provider'
-
-export function ProtectedRoute({ children }: { children: React.ReactNode }) {
- const { user, loading, claims } = useAuth()
- const location = useLocation()
- if (loading) return Loading…
- if (!user) return
- if (claims?.role !== 'responder') return Access denied: responder role required.
- return <>{children}>
-}
diff --git a/apps/responder-app/src/routes.tsx b/apps/responder-app/src/routes.tsx
index 29be5c63..aec7c227 100644
--- a/apps/responder-app/src/routes.tsx
+++ b/apps/responder-app/src/routes.tsx
@@ -1,5 +1,5 @@
import { createBrowserRouter, RouterProvider, Navigate } from 'react-router-dom'
-import { ProtectedRoute } from './app/protected-route'
+import { ProtectedRoute } from '@bantayog/shared-ui'
import { LoginPage } from './pages/LoginPage'
import { DispatchListPage } from './pages/DispatchListPage'
import { DispatchDetailPage } from './pages/DispatchDetailPage'
@@ -9,7 +9,7 @@ const router = createBrowserRouter([
{
path: '/',
element: (
-
+
),
@@ -17,7 +17,7 @@ const router = createBrowserRouter([
{
path: '/dispatches/:dispatchId',
element: (
-
+
),
diff --git a/eslint.config.js b/eslint.config.js
index 018d2cdb..78ae1386 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -22,8 +22,6 @@ export default tseslint.config(
'scripts/**',
// Plain-JS service worker — excluded from TypeScript project service.
'apps/responder-app/public/firebase-messaging-sw.js',
- // Plain-JS emulator shim — not in tsconfig rootDir, linted separately.
- 'packages/shared-sms-parser/index.js',
],
},
diff --git a/packages/shared-ui/lib/auth-provider.d.ts b/packages/shared-ui/lib/auth-provider.d.ts
new file mode 100644
index 00000000..a38dcb7a
--- /dev/null
+++ b/packages/shared-ui/lib/auth-provider.d.ts
@@ -0,0 +1,17 @@
+import { type ReactNode } from 'react';
+import { type Auth, type User } from 'firebase/auth';
+export interface AuthContextValue {
+ user: User | null;
+ claims: Record | null;
+ loading: boolean;
+ signOut: () => Promise;
+ refreshClaims: () => Promise;
+}
+interface AuthProviderProps {
+ children: ReactNode;
+ auth: Auth;
+}
+export declare function AuthProvider({ children, auth }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
+export declare function useAuth(): AuthContextValue;
+export {};
+//# sourceMappingURL=auth-provider.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-ui/lib/auth-provider.d.ts.map b/packages/shared-ui/lib/auth-provider.d.ts.map
new file mode 100644
index 00000000..a8b7dbe6
--- /dev/null
+++ b/packages/shared-ui/lib/auth-provider.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACnG,OAAO,EAA4C,KAAK,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM,eAAe,CAAA;AAE9F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACnC;AAID,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAA;IACnB,IAAI,EAAE,IAAI,CAAA;CACX;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,iBAAiB,2CAgEjE;AAED,wBAAgB,OAAO,IAAI,gBAAgB,CAI1C"}
\ No newline at end of file
diff --git a/packages/shared-ui/lib/auth-provider.test.d.ts b/packages/shared-ui/lib/auth-provider.test.d.ts
new file mode 100644
index 00000000..a5a5eadb
--- /dev/null
+++ b/packages/shared-ui/lib/auth-provider.test.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=auth-provider.test.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-ui/lib/auth-provider.test.d.ts.map b/packages/shared-ui/lib/auth-provider.test.d.ts.map
new file mode 100644
index 00000000..a09b1482
--- /dev/null
+++ b/packages/shared-ui/lib/auth-provider.test.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"auth-provider.test.d.ts","sourceRoot":"","sources":["../src/auth-provider.test.tsx"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/shared-ui/lib/index.d.ts b/packages/shared-ui/lib/index.d.ts
index e26a57a8..a2bd4848 100644
--- a/packages/shared-ui/lib/index.d.ts
+++ b/packages/shared-ui/lib/index.d.ts
@@ -1,2 +1,4 @@
-export {};
+export { AuthProvider, useAuth } from './auth-provider.js';
+export type { AuthContextValue } from './auth-provider.js';
+export { ProtectedRoute } from './protected-route.js';
//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-ui/lib/index.d.ts.map b/packages/shared-ui/lib/index.d.ts.map
index 20c4ab7b..8b1ee058 100644
--- a/packages/shared-ui/lib/index.d.ts.map
+++ b/packages/shared-ui/lib/index.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAA"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA"}
\ No newline at end of file
diff --git a/packages/shared-ui/lib/protected-route.d.ts b/packages/shared-ui/lib/protected-route.d.ts
new file mode 100644
index 00000000..f02a58e6
--- /dev/null
+++ b/packages/shared-ui/lib/protected-route.d.ts
@@ -0,0 +1,12 @@
+import { type ReactNode } from 'react';
+interface ProtectedRouteProps {
+ children: ReactNode;
+ allowedRoles: string[];
+ requireActive?: boolean;
+ requireMunicipalityIdForRoles?: string[];
+ loadingFallback?: ReactNode;
+ unauthorizedFallback?: ReactNode;
+}
+export declare function ProtectedRoute({ children, allowedRoles, requireActive, requireMunicipalityIdForRoles, loadingFallback, unauthorizedFallback, }: ProtectedRouteProps): string | number | bigint | boolean | Iterable | Promise> | Iterable | null | undefined> | import("react/jsx-runtime").JSX.Element | null;
+export {};
+//# sourceMappingURL=protected-route.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-ui/lib/protected-route.d.ts.map b/packages/shared-ui/lib/protected-route.d.ts.map
new file mode 100644
index 00000000..e3a80877
--- /dev/null
+++ b/packages/shared-ui/lib/protected-route.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"protected-route.d.ts","sourceRoot":"","sources":["../src/protected-route.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,SAAS,CAAA;IACnB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,6BAA6B,CAAC,EAAE,MAAM,EAAE,CAAA;IACxC,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,oBAAoB,CAAC,EAAE,SAAS,CAAA;CACjC;AAED,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,YAAY,EACZ,aAAqB,EACrB,6BAAkC,EAClC,eAAqC,EACrC,oBAA6D,GAC9D,EAAE,mBAAmB,+TAwBrB"}
\ No newline at end of file
diff --git a/packages/shared-ui/lib/protected-route.test.d.ts b/packages/shared-ui/lib/protected-route.test.d.ts
new file mode 100644
index 00000000..4e1073a4
--- /dev/null
+++ b/packages/shared-ui/lib/protected-route.test.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=protected-route.test.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-ui/lib/protected-route.test.d.ts.map b/packages/shared-ui/lib/protected-route.test.d.ts.map
new file mode 100644
index 00000000..9d444bd5
--- /dev/null
+++ b/packages/shared-ui/lib/protected-route.test.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"protected-route.test.d.ts","sourceRoot":"","sources":["../src/protected-route.test.tsx"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/shared-ui/package.json b/packages/shared-ui/package.json
index 6558253e..df2ea37e 100644
--- a/packages/shared-ui/package.json
+++ b/packages/shared-ui/package.json
@@ -12,10 +12,21 @@
"scripts": {
"lint": "eslint src",
"typecheck": "tsc --noEmit",
- "build": "tsc --emitDeclarationOnly --outDir lib"
+ "build": "tsc --emitDeclarationOnly --outDir lib",
+ "test": "vitest --run"
},
"peerDependencies": {
- "react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react": "^18.3.1 || ^19.0.0",
+ "react-dom": "^18.3.1 || ^19.0.0",
+ "react-router-dom": "^7.0.0",
+ "firebase": "^12.0.0"
+ },
+ "devDependencies": {
+ "@testing-library/jest-dom": "^6.4.0",
+ "@testing-library/react": "^16.0.0",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "happy-dom": "^15.11.0",
+ "vitest": "^4.1.4"
}
}
diff --git a/apps/responder-app/src/app/auth-provider.tsx b/packages/shared-ui/src/auth-provider.tsx
similarity index 57%
rename from apps/responder-app/src/app/auth-provider.tsx
rename to packages/shared-ui/src/auth-provider.tsx
index 8f8e2d60..878e4470 100644
--- a/apps/responder-app/src/app/auth-provider.tsx
+++ b/packages/shared-ui/src/auth-provider.tsx
@@ -1,21 +1,44 @@
-import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
-import { onAuthStateChanged, type User } from 'firebase/auth'
-import { auth } from './firebase'
+import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from 'react'
+import { onAuthStateChanged, signOut as fbSignOut, type Auth, type User } from 'firebase/auth'
-interface AuthContextValue {
+export interface AuthContextValue {
user: User | null
claims: Record | null
loading: boolean
signOut: () => Promise
+ refreshClaims: () => Promise
}
const AuthContext = createContext(null)
-export function AuthProvider({ children }: { children: ReactNode }) {
+interface AuthProviderProps {
+ children: ReactNode
+ auth: Auth
+}
+
+export function AuthProvider({ children, auth }: AuthProviderProps) {
const [user, setUser] = useState(null)
const [claims, setClaims] = useState | null>(null)
const [loading, setLoading] = useState(true)
+ const refreshClaims = useCallback(async () => {
+ const currentUser = auth.currentUser
+ if (!currentUser) {
+ setClaims(null)
+ return
+ }
+ try {
+ const token = await currentUser.getIdTokenResult(true)
+ // Guard against stale user (sign-out or account switch during refresh)
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (auth.currentUser?.uid !== currentUser.uid) return
+ setClaims(token.claims as Record)
+ } catch (err: unknown) {
+ console.error('[AuthProvider] token refresh failed:', err)
+ setClaims(null)
+ }
+ }, [auth])
+
useEffect(() => {
let active = true
const unsub = onAuthStateChanged(auth, (u) => {
@@ -46,15 +69,14 @@ export function AuthProvider({ children }: { children: ReactNode }) {
active = false
unsub()
}
- }, [])
+ }, [auth])
- async function signOut() {
- const { signOut: fbSignOut } = await import('firebase/auth')
+ const signOut = useCallback(async () => {
await fbSignOut(auth)
- }
+ }, [auth])
return (
-
+
{children}
)
diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts
index 04914a33..2cfd6036 100644
--- a/packages/shared-ui/src/index.ts
+++ b/packages/shared-ui/src/index.ts
@@ -1,2 +1,3 @@
-// Primitive components filled in Phase 2+.
-export {}
+export { AuthProvider, useAuth } from './auth-provider.js'
+export type { AuthContextValue } from './auth-provider.js'
+export { ProtectedRoute } from './protected-route.js'
diff --git a/packages/shared-ui/src/protected-route.tsx b/packages/shared-ui/src/protected-route.tsx
new file mode 100644
index 00000000..6058c008
--- /dev/null
+++ b/packages/shared-ui/src/protected-route.tsx
@@ -0,0 +1,45 @@
+import { type ReactNode } from 'react'
+import { Navigate, useLocation } from 'react-router-dom'
+import { useAuth } from './auth-provider.js'
+
+interface ProtectedRouteProps {
+ children: ReactNode
+ allowedRoles: string[]
+ requireActive?: boolean
+ requireMunicipalityIdForRoles?: string[]
+ loadingFallback?: ReactNode
+ unauthorizedFallback?: ReactNode
+}
+
+export function ProtectedRoute({
+ children,
+ allowedRoles,
+ requireActive = false,
+ requireMunicipalityIdForRoles = [],
+ loadingFallback = Loading…
,
+ unauthorizedFallback = Access denied.
,
+}: ProtectedRouteProps) {
+ const { user, claims, loading } = useAuth()
+ const location = useLocation()
+
+ if (loading) return loadingFallback
+ if (!user) return
+
+ const role = typeof claims?.role === 'string' ? claims.role : ''
+ if (!allowedRoles.includes(role)) {
+ return unauthorizedFallback
+ }
+
+ if (requireActive && claims?.active !== true) {
+ return unauthorizedFallback
+ }
+
+ if (
+ requireMunicipalityIdForRoles.includes(role) &&
+ (typeof claims?.municipalityId !== 'string' || !claims.municipalityId)
+ ) {
+ return unauthorizedFallback
+ }
+
+ return <>{children}>
+}
diff --git a/packages/shared-ui/vitest.config.ts b/packages/shared-ui/vitest.config.ts
new file mode 100644
index 00000000..5eaa352f
--- /dev/null
+++ b/packages/shared-ui/vitest.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ globals: true,
+ environment: 'happy-dom',
+ include: ['src/**/*.test.ts', 'src/**/*.test.tsx'],
+ setupFiles: ['@testing-library/jest-dom/vitest'],
+ },
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0e3c39ad..be29965f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -308,12 +308,37 @@ importers:
packages/shared-ui:
dependencies:
+ firebase:
+ specifier: ^12.0.0
+ version: 12.12.0
react:
- specifier: ^18.3.1
- version: 18.3.1
+ specifier: ^18.3.1 || ^19.0.0
+ version: 19.2.5
react-dom:
- specifier: ^18.3.1
- version: 18.3.1(react@18.3.1)
+ specifier: ^18.3.1 || ^19.0.0
+ version: 19.2.5(react@19.2.5)
+ react-router-dom:
+ specifier: ^7.0.0
+ version: 7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ devDependencies:
+ '@testing-library/jest-dom':
+ specifier: ^6.4.0
+ version: 6.9.1
+ '@testing-library/react':
+ specifier: ^16.0.0
+ version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ '@types/react':
+ specifier: ^19.2.14
+ version: 19.2.14
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.14)
+ happy-dom:
+ specifier: ^15.11.0
+ version: 15.11.7
+ vitest:
+ specifier: ^4.1.4
+ version: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(happy-dom@15.11.7)(msw@2.13.4(@types/node@25.6.0)(typescript@6.0.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))
packages/shared-validators:
dependencies:
@@ -2457,6 +2482,10 @@ packages:
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
entities@7.0.1:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
engines: {node: '>=0.12'}
@@ -2924,6 +2953,10 @@ packages:
resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==}
engines: {node: '>=14.0.0'}
+ happy-dom@15.11.7:
+ resolution: {integrity: sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==}
+ engines: {node: '>=18.0.0'}
+
happy-dom@20.9.0:
resolution: {integrity: sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==}
engines: {node: '>=20.0.0'}
@@ -4001,11 +4034,6 @@ packages:
resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==}
engines: {node: '>= 0.8'}
- react-dom@18.3.1:
- resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
- peerDependencies:
- react: ^18.3.1
-
react-dom@19.2.5:
resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies:
@@ -4044,10 +4072,6 @@ packages:
react-dom:
optional: true
- react@18.3.1:
- resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
- engines: {node: '>=0.10.0'}
-
react@19.2.5:
resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==}
engines: {node: '>=0.10.0'}
@@ -4148,9 +4172,6 @@ packages:
resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==}
engines: {node: '>=11.0.0'}
- scheduler@0.23.2:
- resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
-
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
@@ -4691,6 +4712,10 @@ packages:
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+ webidl-conversions@7.0.0:
+ resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
+ engines: {node: '>=12'}
+
websocket-driver@0.7.4:
resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
engines: {node: '>=0.8.0'}
@@ -7199,6 +7224,8 @@ snapshots:
once: 1.4.0
optional: true
+ entities@4.5.0: {}
+
entities@7.0.1: {}
env-paths@2.2.1: {}
@@ -7957,6 +7984,12 @@ snapshots:
- supports-color
optional: true
+ happy-dom@15.11.7:
+ dependencies:
+ entities: 4.5.0
+ webidl-conversions: 7.0.0
+ whatwg-mimetype: 3.0.0
+
happy-dom@20.9.0:
dependencies:
'@types/node': 20.19.39
@@ -9244,12 +9277,6 @@ snapshots:
iconv-lite: 0.4.24
unpipe: 1.0.0
- react-dom@18.3.1(react@18.3.1):
- dependencies:
- loose-envify: 1.4.0
- react: 18.3.1
- scheduler: 0.23.2
-
react-dom@19.2.5(react@19.2.5):
dependencies:
react: 19.2.5
@@ -9282,10 +9309,6 @@ snapshots:
optionalDependencies:
react-dom: 19.2.5(react@19.2.5)
- react@18.3.1:
- dependencies:
- loose-envify: 1.4.0
-
react@19.2.5: {}
readable-stream@3.6.2:
@@ -9417,10 +9440,6 @@ snapshots:
sax@1.6.0: {}
- scheduler@0.23.2:
- dependencies:
- loose-envify: 1.4.0
-
scheduler@0.27.0: {}
semver@6.3.1: {}
@@ -10026,6 +10045,36 @@ snapshots:
transitivePeerDependencies:
- msw
+ vitest@4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(happy-dom@15.11.7)(msw@2.13.4(@types/node@25.6.0)(typescript@6.0.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)):
+ dependencies:
+ '@vitest/expect': 4.1.4
+ '@vitest/mocker': 4.1.4(msw@2.13.4(@types/node@25.6.0)(typescript@6.0.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))
+ '@vitest/pretty-format': 4.1.4
+ '@vitest/runner': 4.1.4
+ '@vitest/snapshot': 4.1.4
+ '@vitest/spy': 4.1.4
+ '@vitest/utils': 4.1.4
+ es-module-lexer: 2.0.0
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ obug: 2.1.1
+ pathe: 2.0.3
+ picomatch: 4.0.4
+ std-env: 4.1.0
+ tinybench: 2.9.0
+ tinyexec: 1.1.1
+ tinyglobby: 0.2.16
+ tinyrainbow: 3.1.0
+ vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@opentelemetry/api': 1.9.1
+ '@types/node': 25.6.0
+ '@vitest/coverage-v8': 4.1.4(vitest@4.1.4)
+ happy-dom: 15.11.7
+ transitivePeerDependencies:
+ - msw
+
vitest@4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(happy-dom@20.9.0)(msw@2.13.4(@types/node@25.6.0)(typescript@6.0.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)):
dependencies:
'@vitest/expect': 4.1.4
@@ -10067,6 +10116,8 @@ snapshots:
webidl-conversions@3.0.1:
optional: true
+ webidl-conversions@7.0.0: {}
+
websocket-driver@0.7.4:
dependencies:
http-parser-js: 0.5.10
From c2f495174e8fdca6abd544186707dfed47645331 Mon Sep 17 00:00:00 2001
From: Claude
Date: Fri, 24 Apr 2026 07:07:32 +0800
Subject: [PATCH 11/31] test(shared-ui): add characterization tests for
AuthProvider and ProtectedRoute
- P2 #5: Add 11 tests covering AuthProvider (6) and ProtectedRoute (5)
- AuthProvider: null user, authenticated user, signOut, refreshClaims,
getIdTokenResult error, useAuth guard
- ProtectedRoute: redirect to login, allowed role, denied role,
requireActive deny, requireMunicipalityIdForRoles deny
---
docs/learnings.md | 8 +
docs/progress.md | 51 +++++
packages/shared-ui/src/auth-provider.test.tsx | 192 ++++++++++++++++++
.../shared-ui/src/protected-route.test.tsx | 167 +++++++++++++++
4 files changed, 418 insertions(+)
create mode 100644 packages/shared-ui/src/auth-provider.test.tsx
create mode 100644 packages/shared-ui/src/protected-route.test.tsx
diff --git a/docs/learnings.md b/docs/learnings.md
index 60296563..42b45473 100644
--- a/docs/learnings.md
+++ b/docs/learnings.md
@@ -64,3 +64,11 @@ Durable rules worth keeping across sessions.
- `navigator.clipboard` in happy-dom often needs to be defined as an own property before spying.
- Risky backend changes need emulator verification first and should not go to prod in the same session.
+
+## Refactoring / Monorepo Hygiene
+
+- When extracting a module and renaming the original file (e.g., `inbound.ts` → `parser.ts`), stale build artifacts (`lib/inbound.js`, `.d.ts`, `.map`) must be manually removed or they will confuse future readers and tooling.
+- Consolidating duplicated React components across apps into a shared package requires adding the consuming app's runtime dependencies (e.g., `firebase`, `react-router-dom`) as `peerDependencies` in the shared package; otherwise typecheck passes locally but breaks in isolation.
+- A shared `AuthProvider` that uses `Record` for claims pushes type-narrowing burden to every consumer. This is acceptable for a shared boundary, but consumers should validate with `typeof` checks rather than casting.
+- `useCallback` is required for functions exposed through context (like `refreshClaims` and `signOut`) to prevent infinite re-render loops in consumers that include them in `useEffect` dependency arrays.
+- When mocking Firebase Auth's `onAuthStateChanged` with `vi.mock('firebase/auth', ...)`, the mock must return an unsubscribe function; the real `onAuthStateChanged` is a module-level function, not a method on the `Auth` instance.
diff --git a/docs/progress.md b/docs/progress.md
index be64d267..3b38a769 100644
--- a/docs/progress.md
+++ b/docs/progress.md
@@ -2,6 +2,57 @@
## Current
+### Refactor Audit 2026-04-23 — Implementation Continuation (2026-04-24)
+
+**Branch:** `refactor/audit-2026-04-23-continuation`
+
+**Completed Items:**
+
+- **P1 #3:** `inbound.ts` split into modules — `parser.ts` (192 lines), `gazetteer.ts`, `levenshtein.ts`, `auto-reply.ts`. All 6 `@ts-expect-error` comments eliminated. Stale `lib/inbound.js` build artifacts cleaned up.
+- **P1 #4:** `dispatch-responder.ts` extraction — validation (`dispatch-responder-validation.ts`), notification (`dispatch-responder-notify.ts`), Firestore writes (`dispatch-responder-writes.ts`). Added `municipalityId` runtime validation and fixed spread-order bug in validatedResponder.
+- **P2 #7:** Standardized all remaining implicit-any catch patterns — 14 occurrences across 10 production source files converted to `catch (err: unknown)` / `catch (error: unknown)`. One missed occurrence in `sms-inbound-processor.ts:184` also fixed.
+- **P2 #8:** Replaced `console.log` with `console.info` in `shared-validators/src/logging.ts` with clarifying comment about Cloud Functions stdout ingestion.
+- **P3 #9:** Confirmed `batchResponse: any` already removed from `fcm-send.ts`; no source `any` types remain in production code.
+- **P3 #10:** Converted TODO to `TICKET(BANTAYOG-PHASE6)` with deferral rationale.
+- **P2 #6:** Consolidated auth provider + protected route into `shared-ui` — new `AuthProvider` (with `active` guard, `refreshClaims`, `useCallback` memoization) and `ProtectedRoute` (configurable via `allowedRoles`, `requireActive`, `requireMunicipalityIdForRoles` props). Updated both `admin-desktop` and `responder-app` to consume from `@bantayog/shared-ui`. Deleted 4 duplicated files.
+- **P2 #5 (shared-ui):** Added test infrastructure (vitest, testing-library, happy-dom) and 11 characterization tests for `AuthProvider` and `ProtectedRoute`.
+
+**Files Created:**
+
+- `packages/shared-ui/src/auth-provider.tsx`
+- `packages/shared-ui/src/protected-route.tsx`
+- `packages/shared-ui/src/auth-provider.test.tsx`
+- `packages/shared-ui/src/protected-route.test.tsx`
+- `packages/shared-ui/vitest.config.ts`
+- `functions/src/callables/dispatch-responder-validation.ts`
+- `functions/src/callables/dispatch-responder-notify.ts`
+- `functions/src/callables/dispatch-responder-writes.ts`
+
+**Files Deleted:**
+
+- `apps/admin-desktop/src/app/auth-provider.tsx`
+- `apps/admin-desktop/src/app/protected-route.tsx`
+- `apps/responder-app/src/app/auth-provider.tsx`
+- `apps/responder-app/src/app/protected-route.tsx`
+- `packages/shared-sms-parser/src/inbound.ts` (renamed to `parser.ts`)
+- `packages/shared-sms-parser/lib/inbound.js` (stale build artifact)
+- `packages/shared-sms-parser/lib/inbound.d.ts` (stale build artifact)
+
+**Verification:**
+
+- `npx turbo run lint typecheck` — PASS (25/25)
+- `pnpm --filter @bantayog/shared-sms-parser test` — PASS (13/13)
+- `pnpm --filter @bantayog/shared-ui test` — PASS (11/11)
+
+**Remaining (deferred to future sprints):**
+
+- `apps/admin-desktop` — 0 tests (LoginPage, TriageQueuePage, DispatchModal)
+- `apps/responder-app` — 1 test (DispatchListPage, DispatchDetailPage, useAcceptDispatch)
+- `packages/shared-data` — 0 tests
+- `packages/shared-types` — 0 tests
+
+---
+
### Step2WhoWhere Refactoring — Phase 3 & 4: Components & Simplification (2026-04-23)
- Status: Phases 3-4 COMPLETE — integrated extracted components and simplified main component
diff --git a/packages/shared-ui/src/auth-provider.test.tsx b/packages/shared-ui/src/auth-provider.test.tsx
new file mode 100644
index 00000000..3af23ee1
--- /dev/null
+++ b/packages/shared-ui/src/auth-provider.test.tsx
@@ -0,0 +1,192 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest'
+import { render, screen, waitFor, act } from '@testing-library/react'
+import { AuthProvider, useAuth } from './auth-provider.js'
+
+let mockOnAuthStateChanged = vi.fn()
+let mockSignOut = vi.fn()
+
+vi.mock('firebase/auth', () => ({
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ onAuthStateChanged: (...args: unknown[]) => mockOnAuthStateChanged(...args),
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ signOut: (...args: unknown[]) => mockSignOut(...args),
+}))
+
+function TestConsumer() {
+ const { user, claims, loading, signOut, refreshClaims } = useAuth()
+ return (
+
+
{loading ? 'loading' : 'ready'}
+
{user ? user.uid : 'none'}
+
{claims ? JSON.stringify(claims) : 'none'}
+
void signOut()}>
+ Sign out
+
+
void refreshClaims()}>
+ Refresh
+
+
+ )
+}
+
+describe('AuthProvider', () => {
+ beforeEach(() => {
+ mockOnAuthStateChanged = vi.fn()
+ mockSignOut = vi.fn().mockResolvedValue(undefined)
+ })
+
+ it('shows ready with no user when auth state is null', async () => {
+ const unsubscribe = vi.fn()
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(null)
+ return unsubscribe
+ })
+
+ const mockAuth = { currentUser: null } as unknown as import('firebase/auth').Auth
+
+ render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(screen.getByTestId('loading').textContent).toBe('ready')
+ })
+ expect(screen.getByTestId('user').textContent).toBe('none')
+ expect(screen.getByTestId('claims').textContent).toBe('none')
+ })
+
+ it('sets user and claims when authenticated', async () => {
+ const unsubscribe = vi.fn()
+ const mockUser = {
+ uid: 'test-uid',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'responder', municipalityId: 'daet' },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return unsubscribe
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+
+ render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(screen.getByTestId('loading').textContent).toBe('ready')
+ })
+ expect(screen.getByTestId('user').textContent).toBe('test-uid')
+ expect(screen.getByTestId('claims').textContent).toBe(
+ JSON.stringify({ role: 'responder', municipalityId: 'daet' }),
+ )
+ })
+
+ it('calls signOut when signOut button is clicked', async () => {
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(null)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: null } as unknown as import('firebase/auth').Auth
+
+ render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(screen.getByTestId('loading').textContent).toBe('ready')
+ })
+
+ act(() => {
+ screen.getByTestId('signout').click()
+ })
+
+ expect(mockSignOut).toHaveBeenCalledWith(mockAuth)
+ })
+
+ it('refreshes claims when refreshClaims is called', async () => {
+ const unsubscribe = vi.fn()
+ const mockUser = {
+ uid: 'test-uid',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'responder' },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return unsubscribe
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+
+ render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(screen.getByTestId('loading').textContent).toBe('ready')
+ })
+ expect(screen.getByTestId('claims').textContent).toBe(JSON.stringify({ role: 'responder' }))
+
+ mockUser.getIdTokenResult.mockResolvedValue({
+ claims: { role: 'responder', municipalityId: 'daet' },
+ })
+
+ act(() => {
+ screen.getByTestId('refresh').click()
+ })
+
+ await waitFor(() => {
+ expect(screen.getByTestId('claims').textContent).toBe(
+ JSON.stringify({ role: 'responder', municipalityId: 'daet' }),
+ )
+ })
+ })
+
+ it('sets claims to null when getIdTokenResult fails', async () => {
+ const unsubscribe = vi.fn()
+ const mockUser = {
+ uid: 'test-uid',
+ getIdTokenResult: vi.fn().mockRejectedValue(new Error('token expired')),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return unsubscribe
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+
+ render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(screen.getByTestId('loading').textContent).toBe('ready')
+ })
+ expect(screen.getByTestId('claims').textContent).toBe('none')
+ })
+
+ it('throws when useAuth is called outside AuthProvider', () => {
+ function BadComponent() {
+ useAuth()
+ return null
+ }
+
+ expect(() => render()).toThrow('useAuth must be used inside ')
+ })
+})
diff --git a/packages/shared-ui/src/protected-route.test.tsx b/packages/shared-ui/src/protected-route.test.tsx
new file mode 100644
index 00000000..22aa9b48
--- /dev/null
+++ b/packages/shared-ui/src/protected-route.test.tsx
@@ -0,0 +1,167 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest'
+import { render, screen } from '@testing-library/react'
+import { MemoryRouter, Routes, Route } from 'react-router-dom'
+import { ProtectedRoute } from './protected-route.js'
+import { AuthProvider } from './auth-provider.js'
+
+let mockOnAuthStateChanged = vi.fn()
+
+vi.mock('firebase/auth', () => ({
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ onAuthStateChanged: (...args: unknown[]) => mockOnAuthStateChanged(...args),
+ signOut: vi.fn().mockResolvedValue(undefined),
+}))
+
+function TestApp({
+ auth,
+ initialEntry = '/',
+}: {
+ auth: import('firebase/auth').Auth
+ initialEntry?: string
+}) {
+ return (
+
+
+
+ Login} />
+
+ Protected
+
+ }
+ />
+
+
+
+ )
+}
+
+describe('ProtectedRoute', () => {
+ beforeEach(() => {
+ mockOnAuthStateChanged = vi.fn()
+ })
+
+ it('redirects to login when not authenticated', async () => {
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(null)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: null } as unknown as import('firebase/auth').Auth
+ render()
+
+ expect(await screen.findByTestId('login')).toBeDefined()
+ })
+
+ it('renders children when user has allowed role', async () => {
+ const mockUser = {
+ uid: 'u1',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'responder' },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+ render()
+
+ expect(await screen.findByTestId('protected')).toBeDefined()
+ })
+
+ it('renders unauthorized fallback when role is not allowed', async () => {
+ const mockUser = {
+ uid: 'u1',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'municipal_admin' },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+ render()
+
+ expect(await screen.findByText('Access denied.')).toBeDefined()
+ })
+
+ it('renders unauthorized when requireActive is true and user is inactive', async () => {
+ const mockUser = {
+ uid: 'u1',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'responder', active: false },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+ render(
+
+
+
+
+ Protected
+
+ }
+ />
+
+
+ ,
+ )
+
+ expect(await screen.findByText('Access denied.')).toBeDefined()
+ })
+
+ it('renders unauthorized when municipalityId is required but missing', async () => {
+ const mockUser = {
+ uid: 'u1',
+ getIdTokenResult: vi.fn().mockResolvedValue({
+ claims: { role: 'municipal_admin', active: true },
+ }),
+ }
+
+ mockOnAuthStateChanged.mockImplementation((_auth, cb) => {
+ cb(mockUser)
+ return vi.fn()
+ })
+
+ const mockAuth = { currentUser: mockUser } as unknown as import('firebase/auth').Auth
+ render(
+
+
+
+
+ Protected
+
+ }
+ />
+
+
+ ,
+ )
+
+ expect(await screen.findByText('Access denied.')).toBeDefined()
+ })
+})
From 29e4eeee428ea1cc8ff9e497f37c940e86d9cc94 Mon Sep 17 00:00:00 2001
From: Claude
Date: Fri, 24 Apr 2026 07:07:51 +0800
Subject: [PATCH 12/31] chore(functions): rebuild compiled artifacts after
source changes
---
.../__tests__/callables/https-error.test.d.ts | 2 +
.../callables/https-error.test.d.ts.map | 1 +
.../__tests__/callables/https-error.test.js | 72 +++++++++++++++++++
.../callables/https-error.test.js.map | 1 +
.../dispatch-mirror-to-report.test.js | 15 ++--
.../dispatch-mirror-to-report.test.js.map | 2 +-
.../firestore/sms-inbound-processor.d.ts.map | 2 +-
.../lib/firestore/sms-inbound-processor.js | 10 ++-
.../firestore/sms-inbound-processor.js.map | 2 +-
functions/lib/http/sms-inbound.d.ts.map | 2 +-
functions/lib/http/sms-inbound.js | 7 +-
functions/lib/http/sms-inbound.js.map | 2 +-
functions/lib/services/fcm-send.d.ts.map | 2 +-
functions/lib/services/fcm-send.js | 4 +-
functions/lib/services/fcm-send.js.map | 2 +-
.../services/sms-providers/semaphore.d.ts.map | 2 +-
.../lib/services/sms-providers/semaphore.js | 9 ++-
.../services/sms-providers/semaphore.js.map | 2 +-
.../lib/triggers/on-media-finalize.d.ts.map | 2 +-
functions/lib/triggers/on-media-finalize.js | 3 +-
.../lib/triggers/on-media-finalize.js.map | 2 +-
21 files changed, 123 insertions(+), 23 deletions(-)
create mode 100644 functions/lib/__tests__/callables/https-error.test.d.ts
create mode 100644 functions/lib/__tests__/callables/https-error.test.d.ts.map
create mode 100644 functions/lib/__tests__/callables/https-error.test.js
create mode 100644 functions/lib/__tests__/callables/https-error.test.js.map
diff --git a/functions/lib/__tests__/callables/https-error.test.d.ts b/functions/lib/__tests__/callables/https-error.test.d.ts
new file mode 100644
index 00000000..6961d1ef
--- /dev/null
+++ b/functions/lib/__tests__/callables/https-error.test.d.ts
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=https-error.test.d.ts.map
\ No newline at end of file
diff --git a/functions/lib/__tests__/callables/https-error.test.d.ts.map b/functions/lib/__tests__/callables/https-error.test.d.ts.map
new file mode 100644
index 00000000..17d66b71
--- /dev/null
+++ b/functions/lib/__tests__/callables/https-error.test.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"https-error.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/callables/https-error.test.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/functions/lib/__tests__/callables/https-error.test.js b/functions/lib/__tests__/callables/https-error.test.js
new file mode 100644
index 00000000..d1788487
--- /dev/null
+++ b/functions/lib/__tests__/callables/https-error.test.js
@@ -0,0 +1,72 @@
+import { describe, it, expect } from 'vitest';
+import { HttpsError } from 'firebase-functions/v2/https';
+import { BANTAYOG_TO_HTTPS_CODE, bantayogErrorToHttps, requireAuth, } from '../../callables/https-error.js';
+import { BantayogError, BantayogErrorCode } from '@bantayog/shared-validators';
+describe('BANTAYOG_TO_HTTPS_CODE', () => {
+ it('maps every BantayogErrorCode to a FunctionsErrorCode', () => {
+ // Iterate actual enum values, not map keys, to catch unmapped entries
+ const codes = Object.values(BantayogErrorCode).filter((value) => typeof value === 'string');
+ expect(codes.length).toBeGreaterThan(0);
+ for (const code of codes) {
+ expect(BANTAYOG_TO_HTTPS_CODE[code]).toBeDefined();
+ expect(typeof BANTAYOG_TO_HTTPS_CODE[code]).toBe('string');
+ }
+ });
+});
+describe('bantayogErrorToHttps', () => {
+ it('converts a BantayogError to an HttpsError with the right code', () => {
+ const err = new BantayogError(BantayogErrorCode.VALIDATION_ERROR, 'bad input', { field: 'x' });
+ const httpsErr = bantayogErrorToHttps(err);
+ expect(httpsErr).toBeInstanceOf(HttpsError);
+ expect(httpsErr.code).toBe('invalid-argument');
+ expect(httpsErr.message).toBe('bad input');
+ expect(httpsErr.details).toEqual({ field: 'x' });
+ });
+ it('converts NOT_FOUND to not-found', () => {
+ const err = new BantayogError(BantayogErrorCode.NOT_FOUND, 'missing');
+ const httpsErr = bantayogErrorToHttps(err);
+ expect(httpsErr.code).toBe('not-found');
+ });
+});
+describe('requireAuth', () => {
+ it('throws unauthenticated when request.auth is null', () => {
+ expect(() => requireAuth({ auth: null }, ['municipal_admin'])).toThrow(HttpsError);
+ expect(() => requireAuth({ auth: null }, ['municipal_admin'])).toThrow('sign-in required');
+ });
+ it('throws unauthenticated when request.auth is undefined', () => {
+ expect(() => requireAuth({}, ['municipal_admin'])).toThrow(HttpsError);
+ });
+ it('throws permission-denied when role is not in allowed list', () => {
+ const request = {
+ auth: {
+ uid: 'u1',
+ token: { role: 'citizen' },
+ },
+ };
+ expect(() => requireAuth(request, ['municipal_admin'])).toThrow('role citizen is not allowed');
+ });
+ it('throws permission-denied when role is missing', () => {
+ const request = {
+ auth: {
+ uid: 'u1',
+ token: {},
+ },
+ };
+ expect(() => requireAuth(request, ['municipal_admin'])).toThrow('role undefined is not allowed');
+ });
+ it('returns uid and claims when role is allowed', () => {
+ const request = {
+ auth: {
+ uid: 'u1',
+ token: { role: 'municipal_admin', municipalityId: 'm1' },
+ },
+ };
+ const result = requireAuth(request, ['municipal_admin', 'superadmin']);
+ expect(result.uid).toBe('u1');
+ expect(result.claims).toEqual({
+ role: 'municipal_admin',
+ municipalityId: 'm1',
+ });
+ });
+});
+//# sourceMappingURL=https-error.test.js.map
\ No newline at end of file
diff --git a/functions/lib/__tests__/callables/https-error.test.js.map b/functions/lib/__tests__/callables/https-error.test.js.map
new file mode 100644
index 00000000..bb7093a7
--- /dev/null
+++ b/functions/lib/__tests__/callables/https-error.test.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"https-error.test.js","sourceRoot":"","sources":["../../../src/__tests__/callables/https-error.test.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js b/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js
index 294097ff..75763987 100644
--- a/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js
+++ b/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js
@@ -6,7 +6,9 @@ import { getFirestore } from 'firebase-admin/firestore';
import { dispatchMirrorToReportCore } from '../../triggers/dispatch-mirror-to-report.js';
const ts = 1713350400000;
process.env.FIRESTORE_EMULATOR_HOST ??= 'localhost:8081';
-const app = getApps()[0] ?? initializeApp({ projectId: 'dispatch-mirror-test' });
+const appName = 'dispatch-mirror-test';
+const app = getApps().find((a) => a.name === appName) ??
+ initializeApp({ projectId: 'dispatch-mirror-test' }, appName);
const adminDb = getFirestore(app);
// ---------------------------------------------------------------------------
// Test environment
@@ -55,7 +57,10 @@ async function seedReportAtStatusJS(reportId, status) {
}
/** Seeds a dispatch using JS SDK via withSecurityRulesDisabled. */
async function seedDispatchJS(dispatchId, reportId, status, correlationId) {
- await adminDb.collection('dispatches').doc(dispatchId).set({
+ await adminDb
+ .collection('dispatches')
+ .doc(dispatchId)
+ .set({
dispatchId,
reportId,
status,
@@ -130,8 +135,8 @@ describe('dispatchMirrorToReport', () => {
const dispatchId = `dispatch-${crypto.randomUUID()}`;
await seedDispatchJS(dispatchId, 'nonexistent-report', 'pending');
await withAdminDb(async (db) => {
- // Should not throw — trigger skips gracefully
- await expect(dispatchMirrorToReportCore({
+ // Should not throw — trigger skips gracefully when report is missing
+ await dispatchMirrorToReportCore({
db,
dispatchId,
beforeData: { status: 'pending' },
@@ -140,7 +145,7 @@ describe('dispatchMirrorToReport', () => {
reportId: 'nonexistent-report',
correlationId: crypto.randomUUID(),
},
- })).resolves.not.toThrow();
+ });
});
});
it('reverts declined dispatches back to verified and clears currentDispatchId', async () => {
diff --git a/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js.map b/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js.map
index 9cf4b1e4..e4451952 100644
--- a/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js.map
+++ b/functions/lib/__tests__/triggers/dispatch-mirror-to-report.test.js.map
@@ -1 +1 @@
-{"version":3,"file":"dispatch-mirror-to-report.test.js","sourceRoot":"","sources":["../../../src/__tests__/triggers/dispatch-mirror-to-report.test.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"dispatch-mirror-to-report.test.js","sourceRoot":"","sources":["../../../src/__tests__/triggers/dispatch-mirror-to-report.test.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/functions/lib/firestore/sms-inbound-processor.d.ts.map b/functions/lib/firestore/sms-inbound-processor.d.ts.map
index 9d0dd860..d4f30bae 100644
--- a/functions/lib/firestore/sms-inbound-processor.d.ts.map
+++ b/functions/lib/firestore/sms-inbound-processor.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"sms-inbound-processor.d.ts","sourceRoot":"","sources":["../../src/firestore/sms-inbound-processor.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,mBAAmB;;GA8J/B,CAAA"}
\ No newline at end of file
+{"version":3,"file":"sms-inbound-processor.d.ts","sourceRoot":"","sources":["../../src/firestore/sms-inbound-processor.ts"],"names":[],"mappings":"AA2CA,eAAO,MAAM,mBAAmB;;GA+J/B,CAAA"}
\ No newline at end of file
diff --git a/functions/lib/firestore/sms-inbound-processor.js b/functions/lib/firestore/sms-inbound-processor.js
index bd9654d8..4bf5f846 100644
--- a/functions/lib/firestore/sms-inbound-processor.js
+++ b/functions/lib/firestore/sms-inbound-processor.js
@@ -13,7 +13,14 @@ function generatePublicRef() {
}
function decryptMsisdn(encrypted) {
if (!encrypted.startsWith('unencrypted:')) {
+ // Validate encryption key format BEFORE using it
+ if (!/^[0-9a-fA-F]{64}$/.test(ENCRYPTION_KEY)) {
+ throw new Error('SMS_MSISDN_ENCRYPTION_KEY must be 64 hex characters (32 bytes for AES-256-GCM)');
+ }
const key = Buffer.from(ENCRYPTION_KEY, 'hex');
+ if (key.length !== 32) {
+ throw new Error(`SMS_MSISDN_ENCRYPTION_KEY decoded to ${String(key.length)} bytes, expected 32`);
+ }
const parsed = JSON.parse(encrypted);
const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(parsed.iv, 'hex'));
decipher.setAuthTag(Buffer.from(parsed.tag, 'hex'));
@@ -126,11 +133,12 @@ export const smsInboundProcessor = onDocumentCreated({
try {
recipientMsisdn = decryptMsisdn(senderMsisdnEnc);
}
- catch {
+ catch (err) {
log({
severity: 'WARNING',
code: 'decrypt.failed',
message: `MSISDN decryption failed for ${msgId} — skipping pending_review reply`,
+ data: { error: String(err) },
});
}
if (recipientMsisdn) {
diff --git a/functions/lib/firestore/sms-inbound-processor.js.map b/functions/lib/firestore/sms-inbound-processor.js.map
index c00d68f9..991adb46 100644
--- a/functions/lib/firestore/sms-inbound-processor.js.map
+++ b/functions/lib/firestore/sms-inbound-processor.js.map
@@ -1 +1 @@
-{"version":3,"file":"sms-inbound-processor.js","sourceRoot":"","sources":["../../src/firestore/sms-inbound-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAEzE,MAAM,GAAG,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAA;AAE/C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAA;AAElE,SAAS,iBAAiB;IACxB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACjG,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB;IACtC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAA4C,CAAA;QAC/E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;QACpF,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;QACnD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;YAC9B,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC9C,QAAQ,CAAC,KAAK,EAAE;SACjB,CAAC,CAAA;QACF,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;AAC/C,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAClD;IACE,QAAQ,EAAE,mBAAmB;IAC7B,MAAM,EAAE,iBAAiB;IACzB,cAAc,EAAE,EAAE;IAClB,MAAM,EAAE,QAAQ;CACjB,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;IACd,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAA;IAChC,MAAM,EAAE,GAAG,YAAY,EAAE,CAAA;IACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAA;QACvF,OAAM;IACR,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAA;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IACxB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAA;QACxF,OAAM;IACR,CAAC;IAED,IAAK,IAAI,CAAC,WAAsB,KAAK,SAAS,EAAE,CAAC;QAC/C,GAAG,CAAC;YACF,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,SAAS,KAAK,oBAAoB;SAC5C,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IAED,IAAI,SAAS,GAAG,EAAE,CAAA;IAClB,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,IAAc,CAAC,CAAA;QACxD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,CAAA;QAE1C,IAAI,UAAU,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACrC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAA;YAC3D,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,KAAK,cAAc,EAAE,CAAC,CAAA;YACpF,OAAM;QACR,CAAC;QAED,SAAS,GAAG,iBAAiB,EAAE,CAAA;QAC/B,OAAO,GAAG,OAAO,KAAK,EAAE,CAAA;QACxB,MAAM,aAAa,GAAG,OAAO,KAAK,EAAE,CAAA;QAEpC,MAAM,EAAE;aACL,UAAU,CAAC,cAAc,CAAC;aAC1B,GAAG,CAAC,OAAO,CAAC;aACZ,GAAG,CAAC;YACH,WAAW,EAAE,OAAO,KAAK,EAAE;YAC3B,eAAe,EAAE,IAAI,CAAC,UAAoB;YAC1C,cAAc,EAAE,OAAO;YACvB,SAAS;YACT,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC3C,aAAa;YACb,OAAO,EAAE;gBACP,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,WAAW,EAAE,MAAM,CAAC,OAAO,IAAI,QAAQ,MAAM,CAAC,UAAU,OAAO,MAAM,CAAC,QAAQ,EAAE;gBAChF,QAAQ,EAAE,QAAiB;gBAC3B,MAAM,EAAE,KAAc;aACvB;YACD,aAAa,EAAE,CAAC;SACjB,CAAC,CAAA;QAEJ,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;QAE9D,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAC1B,WAAW,EAAE,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ;YAC/D,iBAAiB,EAAE,UAAU,CAAC,QAAQ;YACtC,eAAe,EAAE,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;SACjF,CAAC,CAAA;QAEF,MAAM,eAAe,GAAG,IAAI,CAAC,eAAqC,CAAA;QAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAA0B,CAAA;QACxD,IAAI,eAAe,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChE,MAAM,eAAe,GAAG,aAAa,CAAC,eAAe,CAAC,CAAA;YACtD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAA;YACnD,4DAA4D;YAC5D,MAAM,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACnC,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE;oBACjB,QAAQ,EAAE,UAAU,CAAC,QAAQ;oBAC7B,OAAO,EAAE,aAAa;oBACtB,eAAe;oBACf,MAAM,EAAE,IAAI;oBACZ,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,IAAI;oBACJ,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE;oBACjB,UAAU,EAAE,WAAW;iBACxB,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YACF,GAAG,CAAC;gBACF,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,yBAAyB,KAAK,EAAE;aAC1C,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACrE,MAAM,eAAe,GACnB,GAAG,YAAY,aAAa;YAC5B,CAAC,GAAG,CAAC,OAAO,KAAK,+BAA+B,IAAI,GAAG,CAAC,OAAO,KAAK,qBAAqB,CAAC,CAAA;QAE5F,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAA;YAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,eAAqC,CAAA;YAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAA0B,CAAA;YACxD,IAAI,eAAe,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChE,IAAI,eAAe,GAAkB,IAAI,CAAA;gBACzC,IAAI,CAAC;oBACH,eAAe,GAAG,aAAa,CAAC,eAAe,CAAC,CAAA;gBAClD,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,CAAC;wBACF,QAAQ,EAAE,SAAS;wBACnB,IAAI,EAAE,gBAAgB;wBACtB,OAAO,EAAE,gCAAgC,KAAK,kCAAkC;qBACjF,CAAC,CAAA;gBACJ,CAAC;gBACD,IAAI,eAAe,EAAE,CAAC;oBACpB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAA;oBACnD,IAAI,CAAC;wBACH,4DAA4D;wBAC5D,MAAM,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;4BACnC,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE;gCACjB,QAAQ,EAAE,OAAO;gCACjB,OAAO,EAAE,gBAAgB;gCACzB,eAAe;gCACf,MAAM,EAAE,IAAI;gCACZ,SAAS;gCACT,IAAI;gCACJ,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE;gCACjB,UAAU,EAAE,WAAW;6BACxB,CAAC,CAAA;wBACJ,CAAC,CAAC,CAAA;wBACF,GAAG,CAAC;4BACF,QAAQ,EAAE,MAAM;4BAChB,IAAI,EAAE,kCAAkC;4BACxC,OAAO,EAAE,mCAAmC,KAAK,EAAE;yBACpD,CAAC,CAAA;oBACJ,CAAC;oBAAC,OAAO,QAAQ,EAAE,CAAC;wBAClB,GAAG,CAAC;4BACF,QAAQ,EAAE,SAAS;4BACnB,IAAI,EAAE,kCAAkC;4BACxC,OAAO,EAAE,qCAAqC,KAAK,KAAK,QAAQ,YAAY,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;yBAC1H,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAA;YAC3D,GAAG,CAAC;gBACF,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,SAAS,KAAK,KAAK,YAAY,EAAE;aAC3C,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;AACH,CAAC,CACF,CAAA"}
\ No newline at end of file
+{"version":3,"file":"sms-inbound-processor.js","sourceRoot":"","sources":["../../src/firestore/sms-inbound-processor.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/functions/lib/http/sms-inbound.d.ts.map b/functions/lib/http/sms-inbound.d.ts.map
index d4a4c35e..31361688 100644
--- a/functions/lib/http/sms-inbound.d.ts.map
+++ b/functions/lib/http/sms-inbound.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"sms-inbound.d.ts","sourceRoot":"","sources":["../../src/http/sms-inbound.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AA4BvE,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,SAAS,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC3C,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IAC7B,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAA;CACvB;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,2BAA2B,CAAC,CA0FtC;AAED,eAAO,MAAM,iBAAiB,kDAc7B,CAAA"}
\ No newline at end of file
+{"version":3,"file":"sms-inbound.d.ts","sourceRoot":"","sources":["../../src/http/sms-inbound.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AA4BvE,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,SAAS,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC3C,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IAC7B,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAA;CACvB;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,2BAA2B,CAAC,CA6FtC;AAED,eAAO,MAAM,iBAAiB,kDAc7B,CAAA"}
\ No newline at end of file
diff --git a/functions/lib/http/sms-inbound.js b/functions/lib/http/sms-inbound.js
index ee856119..a6bccd37 100644
--- a/functions/lib/http/sms-inbound.js
+++ b/functions/lib/http/sms-inbound.js
@@ -58,13 +58,16 @@ export async function smsInboundWebhookCore(deps) {
const salt = process.env.SMS_MSISDN_HASH_SALT ?? '';
msisdnHash = hashMsisdn(normalized, salt);
}
- catch {
+ catch (err) {
msisdnHash = crypto.createHash('sha256').update(rawFrom).digest('hex');
log({
severity: 'WARNING',
code: 'msisdn.invalid',
message: 'Invalid MSISDN received',
- data: { rawFrom: rawFrom.slice(0, 6) + '****' },
+ data: {
+ rawFrom: rawFrom.slice(0, 6) + '****',
+ errorType: err instanceof Error ? err.name : 'UnknownError',
+ },
});
}
const msgId = globeMsgId ?? buildMsgId();
diff --git a/functions/lib/http/sms-inbound.js.map b/functions/lib/http/sms-inbound.js.map
index d66fde84..28f07141 100644
--- a/functions/lib/http/sms-inbound.js.map
+++ b/functions/lib/http/sms-inbound.js.map
@@ -1 +1 @@
-{"version":3,"file":"sms-inbound.js","sourceRoot":"","sources":["../../src/http/sms-inbound.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"sms-inbound.js","sourceRoot":"","sources":["../../src/http/sms-inbound.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/functions/lib/services/fcm-send.d.ts.map b/functions/lib/services/fcm-send.d.ts.map
index cff18574..618c9f3b 100644
--- a/functions/lib/services/fcm-send.d.ts.map
+++ b/functions/lib/services/fcm-send.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"fcm-send.d.ts","sourceRoot":"","sources":["../../src/services/fcm-send.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,eAAO,MAAM,qBAAqB,iDAAwC,CAAA;AAE1E,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmExF"}
\ No newline at end of file
+{"version":3,"file":"fcm-send.d.ts","sourceRoot":"","sources":["../../src/services/fcm-send.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,eAAO,MAAM,qBAAqB,iDAAwC,CAAA;AAE1E,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAqExF"}
\ No newline at end of file
diff --git a/functions/lib/services/fcm-send.js b/functions/lib/services/fcm-send.js
index 9b44ca7c..394c0715 100644
--- a/functions/lib/services/fcm-send.js
+++ b/functions/lib/services/fcm-send.js
@@ -53,7 +53,9 @@ export async function sendFcmToResponder(payload) {
msg.data = data;
result = await messaging.sendEachForMulticast(msg);
}
- catch {
+ catch (err) {
+ // Log full error server-side for debugging; keep warnings as stable codes
+ console.error('FCM send failed after retry:', err);
warnings.push('fcm_network_error');
return { warnings };
}
diff --git a/functions/lib/services/fcm-send.js.map b/functions/lib/services/fcm-send.js.map
index f21c20dc..5c90a9a3 100644
--- a/functions/lib/services/fcm-send.js.map
+++ b/functions/lib/services/fcm-send.js.map
@@ -1 +1 @@
-{"version":3,"file":"fcm-send.js","sourceRoot":"","sources":["../../src/services/fcm-send.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"fcm-send.js","sourceRoot":"","sources":["../../src/services/fcm-send.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/functions/lib/services/sms-providers/semaphore.d.ts.map b/functions/lib/services/sms-providers/semaphore.d.ts.map
index 4fb81808..0d8ae120 100644
--- a/functions/lib/services/sms-providers/semaphore.d.ts.map
+++ b/functions/lib/services/sms-providers/semaphore.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"semaphore.d.ts","sourceRoot":"","sources":["../../../src/services/sms-providers/semaphore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAkBrD,wBAAgB,0BAA0B,IAAI,WAAW,CAmGxD"}
\ No newline at end of file
+{"version":3,"file":"semaphore.d.ts","sourceRoot":"","sources":["../../../src/services/sms-providers/semaphore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAkBrD,wBAAgB,0BAA0B,IAAI,WAAW,CAwGxD"}
\ No newline at end of file
diff --git a/functions/lib/services/sms-providers/semaphore.js b/functions/lib/services/sms-providers/semaphore.js
index fe5c11e4..b7a44d7b 100644
--- a/functions/lib/services/sms-providers/semaphore.js
+++ b/functions/lib/services/sms-providers/semaphore.js
@@ -42,8 +42,13 @@ export function createSemaphoreSmsProvider() {
try {
data = (await res.json());
}
- catch {
- throw new SmsProviderRetryableError(`semaphore ${res.status.toString()}: unparseable response`, res.ok || res.status >= 500 ? 'provider_error' : 'network');
+ catch (err) {
+ // 4xx errors are non-retryable (client request issues)
+ if (res.status >= 400 && res.status < 500 && res.status !== 429) {
+ return { accepted: false, reason: 'other', latencyMs: 0 };
+ }
+ // 5xx and network errors are retryable
+ throw new SmsProviderRetryableError(`semaphore ${res.status.toString()}: unparseable response (${String(err)})`, res.status === 429 ? 'rate_limited' : 'provider_error');
}
const status = data.status ?? '';
const errorsArr = data.errors ?? [];
diff --git a/functions/lib/services/sms-providers/semaphore.js.map b/functions/lib/services/sms-providers/semaphore.js.map
index 83d7e548..55314c83 100644
--- a/functions/lib/services/sms-providers/semaphore.js.map
+++ b/functions/lib/services/sms-providers/semaphore.js.map
@@ -1 +1 @@
-{"version":3,"file":"semaphore.js","sourceRoot":"","sources":["../../../src/services/sms-providers/semaphore.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"semaphore.js","sourceRoot":"","sources":["../../../src/services/sms-providers/semaphore.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,GAI1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAS7D,MAAM,mBAAmB,GAAG,KAAK,CAAA;AAEjC,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,UAAU,EAAE,WAAW;QACvB,KAAK,CAAC,IAAI,CAAC,KAA2B;YACpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;YAC5C,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;YAEzD,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAEjE,MAAM,QAAQ,GACZ,KAAK,CAAC,QAAQ,KAAK,QAAQ;gBACzB,CAAC,CAAC,mCAAmC;gBACrC,CAAC,CAAC,wCAAwC,CAAA;YAE9C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;gBACjC,MAAM;gBACN,MAAM,EAAE,YAAY;gBACpB,OAAO,EAAE,KAAK,CAAC,IAAI;gBACnB,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW;aACvD,CAAC,CAAA;YAEF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,UAAU,CAAC,KAAK,EAAE,CAAA;YACpB,CAAC,EAAE,mBAAmB,CAAC,CAAA;YACvB,IAAI,GAAa,CAAA;YACjB,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE;oBACpD,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAA;YACJ,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC7D,MAAM,IAAI,yBAAyB,CAAC,6BAA6B,EAAE,gBAAgB,CAAC,CAAA;gBACtF,CAAC;gBACD,MAAM,GAAG,CAAA;YACX,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAA;YACrB,CAAC;YAED,IAAI,IAAI,GAAsB,EAAE,CAAA;YAChC,IAAI,CAAC;gBACH,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsB,CAAA;YAChD,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,uDAAuD;gBACvD,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAChE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAgB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;gBACpE,CAAC;gBACD,uCAAuC;gBACvC,MAAM,IAAI,yBAAyB,CACjC,aAAa,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,2BAA2B,MAAM,CAAC,GAAG,CAAC,GAAG,EAC3E,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CACvD,CAAA;YACH,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAA;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAA;YACnC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAA;YAC/C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YAE7B,uDAAuD;YACvD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAA;gBACzD,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,IAAI,yBAAyB,CACjC,aAAa,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,IAAI,GAAG,CAAC,UAAU,EAAE,EAC1E,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CACvD,CAAA;gBACH,CAAC;gBACD,+CAA+C;gBAC/C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;oBAChE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,YAAqB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;gBACzE,CAAC;gBACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAgB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;YACpE,CAAC;YAED,mEAAmE;YACnE,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,QAAQ,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,CAAA;gBACxD,4DAA4D;gBAC5D,MAAM,YAAY,GAAG,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC7D,MAAM,QAAQ,GAA4B;oBACxC,QAAQ,EAAE,KAAK;oBACf,SAAS,EAAE,CAAC;oBACZ,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO;iBAClD,CAAA;gBACD,IAAI,SAAS;oBAAE,QAAQ,CAAC,iBAAiB,GAAG,SAAS,CAAA;gBACrD,OAAO,QAAQ,CAAA;YACjB,CAAC;YAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG;oBACd,QAAQ,EAAE,IAAa;oBACvB,iBAAiB,EAAE,SAAS;oBAC5B,SAAS,EAAE,CAAC;oBACZ,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC;oBACrC,QAAQ,EAAE,KAAK,CAAC,QAAQ;iBACzB,CAAA;gBACD,OAAO,OAAO,CAAA;YAChB,CAAC;YACD,8BAA8B;YAC9B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAgB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;QACpE,CAAC;KACF,CAAA;AACH,CAAC"}
\ No newline at end of file
diff --git a/functions/lib/triggers/on-media-finalize.d.ts.map b/functions/lib/triggers/on-media-finalize.d.ts.map
index f698b6c0..ff6c850b 100644
--- a/functions/lib/triggers/on-media-finalize.d.ts.map
+++ b/functions/lib/triggers/on-media-finalize.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"on-media-finalize.d.ts","sourceRoot":"","sources":["../../src/triggers/on-media-finalize.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAA;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,YAAY,EAAE,CAAC,GAAG,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;KACjB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAA;CACrC;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CA8DhC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAA;IAC1E,IAAI,CACF,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAClF,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB"}
\ No newline at end of file
+{"version":3,"file":"on-media-finalize.d.ts","sourceRoot":"","sources":["../../src/triggers/on-media-finalize.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAA;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,YAAY,EAAE,CAAC,GAAG,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;KACjB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAA;CACrC;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CA+DhC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAA;IAC1E,IAAI,CACF,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAClF,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB"}
\ No newline at end of file
diff --git a/functions/lib/triggers/on-media-finalize.js b/functions/lib/triggers/on-media-finalize.js
index fef9c17e..b07f812c 100644
--- a/functions/lib/triggers/on-media-finalize.js
+++ b/functions/lib/triggers/on-media-finalize.js
@@ -42,12 +42,13 @@ export async function onMediaFinalizeCore(input) {
// in some sharp/libvips version combinations, defeating the strip.
cleaned = await sharp(buf).rotate().toBuffer();
}
- catch {
+ catch (err) {
await file.delete();
log({
severity: 'WARNING',
code: 'MEDIA_REJECTED_CORRUPT',
message: `Deleted corrupt image: ${input.objectName}`,
+ data: { error: String(err) },
});
return { status: 'rejected_mime' };
}
diff --git a/functions/lib/triggers/on-media-finalize.js.map b/functions/lib/triggers/on-media-finalize.js.map
index b5d372f0..48ad9d70 100644
--- a/functions/lib/triggers/on-media-finalize.js.map
+++ b/functions/lib/triggers/on-media-finalize.js.map
@@ -1 +1 @@
-{"version":3,"file":"on-media-finalize.js","sourceRoot":"","sources":["../../src/triggers/on-media-finalize.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"on-media-finalize.js","sourceRoot":"","sources":["../../src/triggers/on-media-finalize.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
From b62a7d6a00ee614d6ee1899be2410fed427f57e8 Mon Sep 17 00:00:00 2001
From: Claude
Date: Fri, 24 Apr 2026 07:46:38 +0800
Subject: [PATCH 13/31] refactor(functions,sms-parser,shared-ui): address
CodeRabbit PR review comments
- dispatch-responder-validation: reorder checks so NOT_FOUND/FORBIDDEN
surface before assertResponderOnShift
- dispatch-responder-writes: add trim() + empty check for MSISDN
- dispatch-responder: remove dead typeof claims.role !== 'string' check
- index.ts: defensive err narrowing before accessing .code/.message
- gazetteer.ts: tighten MODULE_NOT_FOUND to regex match
- parser.ts: remove unreachable branch, fix details extraction with lastIndexOf
- levenshtein.ts: fix lint/typecheck loop with ?? 0 narrowing
- protected-route.tsx: add .trim().length > 0 for municipalityId
---
.../dispatch-responder-validation.ts | 15 ++++---
.../callables/dispatch-responder-writes.ts | 6 +--
functions/src/callables/dispatch-responder.ts | 3 --
functions/src/index.ts | 8 +++-
packages/shared-sms-parser/src/gazetteer.ts | 2 +-
packages/shared-sms-parser/src/levenshtein.ts | 43 +++++++++++--------
packages/shared-sms-parser/src/parser.ts | 17 +++-----
packages/shared-ui/src/protected-route.tsx | 2 +-
8 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/functions/src/callables/dispatch-responder-validation.ts b/functions/src/callables/dispatch-responder-validation.ts
index a88bb9b9..8875f075 100644
--- a/functions/src/callables/dispatch-responder-validation.ts
+++ b/functions/src/callables/dispatch-responder-validation.ts
@@ -50,16 +50,9 @@ export async function validateDispatchTransaction({
}> {
const [reportSnap, responderSnap] = await Promise.all([tx.get(reportRef), tx.get(responderRef)])
- // Re-check shift status inside transaction scope to mitigate TOCTOU race
if (!deps.actor.claims.municipalityId) {
throw new BantayogError(BantayogErrorCode.INVALID_ARGUMENT, 'municipalityId is required')
}
- await assertResponderOnShift(
- rtdb,
- deps.actor.claims.municipalityId,
- deps.responderUid,
- 'Responder went off-shift before dispatch could be created',
- )
if (!reportSnap.exists) {
throw new BantayogError(BantayogErrorCode.NOT_FOUND, 'Report not found')
@@ -89,6 +82,14 @@ export async function validateDispatchTransaction({
throw new BantayogError(BantayogErrorCode.INVALID_ARGUMENT, 'Responder missing agencyId')
}
+ // Re-check shift status after identity + municipality checks to preserve correct error classes.
+ await assertResponderOnShift(
+ rtdb,
+ deps.actor.claims.municipalityId,
+ deps.responderUid,
+ 'Responder went off-shift before dispatch could be created',
+ )
+
const rawStatus = report.status
if (typeof rawStatus !== 'string') {
throw new BantayogError(
diff --git a/functions/src/callables/dispatch-responder-writes.ts b/functions/src/callables/dispatch-responder-writes.ts
index c29a9738..c1a66e55 100644
--- a/functions/src/callables/dispatch-responder-writes.ts
+++ b/functions/src/callables/dispatch-responder-writes.ts
@@ -24,9 +24,9 @@ export async function buildSmsPayload(args: BuildSmsPayloadArgs): Promise t.length) {
+ ;[s, t] = [t, s]
+ }
+
+ const m = s.length
+ const n = t.length
- // Flat 1D array for memory efficiency and to avoid noUncheckedIndexedAccess
- const dp = new Uint32Array((m + 1) * (n + 1))
+ let prev = new Uint32Array(n + 1)
+ let curr = new Uint32Array(n + 1)
- for (let i = 0; i <= m; i++) dp[i * (n + 1)] = i
- for (let j = 0; j <= n; j++) dp[j] = j
+ for (let j = 0; j <= n; j++) {
+ prev[j] = j
+ }
for (let i = 1; i <= m; i++) {
+ curr[0] = i
+ const sChar = s[i - 1]
for (let j = 1; j <= n; j++) {
- const idx = i * (n + 1) + j
- const cost = a[i - 1] === b[j - 1] ? 0 : 1
- const deletion = dp[(i - 1) * (n + 1) + j]
- const insertion = dp[i * (n + 1) + (j - 1)]
- const substitution = dp[(i - 1) * (n + 1) + (j - 1)]
- if (deletion === undefined || insertion === undefined || substitution === undefined) {
- throw new Error('Levenshtein DP index out of bounds')
- }
- dp[idx] = Math.min(deletion + 1, insertion + 1, substitution + cost)
+ const cost = sChar === t[j - 1] ? 0 : 1
+ const deletion = (prev[j] ?? 0) + 1
+ const insertion = (curr[j - 1] ?? 0) + 1
+ const substitution = (prev[j - 1] ?? 0) + cost
+ curr[j] = Math.min(deletion, insertion, substitution)
}
+ const tmp = prev
+ prev = curr
+ curr = tmp
}
- const result = dp[m * (n + 1) + n]
- return result ?? 0
+ return prev[n] ?? 0
}
diff --git a/packages/shared-sms-parser/src/parser.ts b/packages/shared-sms-parser/src/parser.ts
index d1ba3f26..cbff13e9 100644
--- a/packages/shared-sms-parser/src/parser.ts
+++ b/packages/shared-sms-parser/src/parser.ts
@@ -106,7 +106,10 @@ export function parseInboundSms(body: string): ParseResult {
detailsStartIndex = barangayToken.length
}
- const barangayIndex = originalRest.toUpperCase().indexOf(barangayToken.toUpperCase())
+ // Find the barangay token in originalRest using lastIndexOf to prefer the occurrence
+ // closest to where details would start (avoids matching an earlier instance of the token).
+ const barangayTokenUpper = barangayToken.toUpperCase()
+ const barangayIndex = originalRest.toUpperCase().lastIndexOf(barangayTokenUpper)
const details =
barangayIndex !== -1 && barangayIndex + detailsStartIndex < originalRest.length
? originalRest.slice(barangayIndex + detailsStartIndex).trim()
@@ -149,16 +152,8 @@ export function parseInboundSms(body: string): ParseResult {
}
if (fuzzyMatches.length === 1) {
- const match = fuzzyMatches[0]
- if (match === undefined) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- }
- }
- const { entry, distance: dist } = match
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const { entry, distance: dist } = fuzzyMatches[0]!
return {
confidence: dist <= 1 ? 'medium' : 'low',
parsed: {
diff --git a/packages/shared-ui/src/protected-route.tsx b/packages/shared-ui/src/protected-route.tsx
index 6058c008..82943fcb 100644
--- a/packages/shared-ui/src/protected-route.tsx
+++ b/packages/shared-ui/src/protected-route.tsx
@@ -36,7 +36,7 @@ export function ProtectedRoute({
if (
requireMunicipalityIdForRoles.includes(role) &&
- (typeof claims?.municipalityId !== 'string' || !claims.municipalityId)
+ (typeof claims?.municipalityId !== 'string' || !claims.municipalityId.trim())
) {
return unauthorizedFallback
}
From 5b5784037983499f4d840bad8a95b239613f93dd Mon Sep 17 00:00:00 2001
From: Claude
Date: Fri, 24 Apr 2026 07:46:46 +0800
Subject: [PATCH 14/31] chore(shared-sms-parser): rebuild compiled lib
artifacts after source changes
---
packages/shared-sms-parser/lib/gazetteer.js | 2 +-
.../shared-sms-parser/lib/gazetteer.js.map | 2 +-
packages/shared-sms-parser/lib/inbound.d.ts | 25 ---
.../shared-sms-parser/lib/inbound.d.ts.map | 1 -
packages/shared-sms-parser/lib/inbound.js | 155 ------------------
packages/shared-sms-parser/lib/inbound.js.map | 1 -
.../lib/levenshtein.d.ts.map | 2 +-
packages/shared-sms-parser/lib/levenshtein.js | 47 +++---
.../shared-sms-parser/lib/levenshtein.js.map | 2 +-
.../shared-sms-parser/lib/parser.d.ts.map | 2 +-
packages/shared-sms-parser/lib/parser.js | 17 +-
packages/shared-sms-parser/lib/parser.js.map | 2 +-
12 files changed, 36 insertions(+), 222 deletions(-)
delete mode 100644 packages/shared-sms-parser/lib/inbound.d.ts
delete mode 100644 packages/shared-sms-parser/lib/inbound.d.ts.map
delete mode 100644 packages/shared-sms-parser/lib/inbound.js
delete mode 100644 packages/shared-sms-parser/lib/inbound.js.map
diff --git a/packages/shared-sms-parser/lib/gazetteer.js b/packages/shared-sms-parser/lib/gazetteer.js
index 9092e1d7..6ab520b2 100644
--- a/packages/shared-sms-parser/lib/gazetteer.js
+++ b/packages/shared-sms-parser/lib/gazetteer.js
@@ -310,7 +310,7 @@ export function getBarangayGazetteer() {
'code' in err &&
err.code === 'MODULE_NOT_FOUND';
const message = err instanceof Error ? err.message : '';
- const isSharedDataLoadFailure = message.includes('@bantayog/shared-data');
+ const isSharedDataLoadFailure = /Cannot find module .@bantayog\/shared-data./.test(message);
if (isModuleNotFound && isSharedDataLoadFailure) {
return FALLBACK_BARANGAYS;
}
diff --git a/packages/shared-sms-parser/lib/gazetteer.js.map b/packages/shared-sms-parser/lib/gazetteer.js.map
index da5ee987..c57d56a3 100644
--- a/packages/shared-sms-parser/lib/gazetteer.js.map
+++ b/packages/shared-sms-parser/lib/gazetteer.js.map
@@ -1 +1 @@
-{"version":3,"file":"gazetteer.js","sourceRoot":"","sources":["../src/gazetteer.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"gazetteer.js","sourceRoot":"","sources":["../src/gazetteer.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/inbound.d.ts b/packages/shared-sms-parser/lib/inbound.d.ts
deleted file mode 100644
index b5fd103b..00000000
--- a/packages/shared-sms-parser/lib/inbound.d.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { z } from 'zod';
-export type Confidence = 'high' | 'medium' | 'low' | 'none';
-export declare const reportTypeSchema: z.ZodEnum<{
- flood: "flood";
- fire: "fire";
- landslide: "landslide";
- accident: "accident";
- medical: "medical";
- other: "other";
-}>;
-export type ReportType = z.infer;
-export interface ParsedFields {
- reportType: ReportType;
- barangay: string;
- rawBarangay?: string;
- details: string | undefined;
-}
-export interface ParseResult {
- confidence: Confidence;
- parsed: ParsedFields | null;
- candidates: string[];
- autoReplyText: string;
-}
-export declare function parseInboundSms(body: string): ParseResult;
-//# sourceMappingURL=inbound.d.ts.map
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/inbound.d.ts.map b/packages/shared-sms-parser/lib/inbound.d.ts.map
deleted file mode 100644
index 5c675532..00000000
--- a/packages/shared-sms-parser/lib/inbound.d.ts.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;AAE3D,eAAO,MAAM,gBAAgB;;;;;;;EAO3B,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB;AAuBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAyIzD"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/inbound.js b/packages/shared-sms-parser/lib/inbound.js
deleted file mode 100644
index 7e1416d0..00000000
--- a/packages/shared-sms-parser/lib/inbound.js
+++ /dev/null
@@ -1,155 +0,0 @@
-// ─── Types ────────────────────────────────────────────────────────────────────
-import { z } from 'zod';
-import { buildAutoReply } from './auto-reply.js';
-import { getBarangayGazetteer } from './gazetteer.js';
-import { levenshtein } from './levenshtein.js';
-export const reportTypeSchema = z.enum([
- 'flood',
- 'fire',
- 'landslide',
- 'accident',
- 'medical',
- 'other',
-]);
-// ─── Type synonym map ─────────────────────────────────────────────────────────
-const TYPE_SYNONYMS = {
- FLOOD: 'flood',
- BAHA: 'flood',
- FIRE: 'fire',
- SUNOG: 'fire',
- LANDSLIDE: 'landslide',
- GUHO: 'landslide',
- ACCIDENT: 'accident',
- AKSIDENTE: 'accident',
- MEDICAL: 'medical',
- MEDIKAL: 'medical',
- OTHER: 'other',
- IBA: 'other',
-};
-const MUNICIPALITY_PREFIXES = new Set(['SAN', 'STA', 'SANTA']);
-// ─── Main parser ──────────────────────────────────────────────────────────────
-export function parseInboundSms(body) {
- if (typeof body !== 'string') {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const normalized = body.trim().replace(/\s+/g, ' ').toUpperCase();
- const originalRest = body.trim().replace(/\s+/g, ' ');
- const KEYWORD = 'BANTAYOG';
- if (!normalized.startsWith(KEYWORD)) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const rest = normalized.slice(KEYWORD.length).trim();
- if (!rest) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const tokens = rest.split(/\s+/);
- const token0 = tokens[0];
- const token1 = tokens[1];
- if (tokens.length < 2 || !token0 || !token1) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const typeToken = token0;
- let barangayToken = token1;
- let detailsStartIndex = barangayToken.length;
- const token2 = tokens[2];
- if (tokens.length >= 3 && token2 && MUNICIPALITY_PREFIXES.has(token1)) {
- barangayToken = token1 + ' ' + token2;
- detailsStartIndex = barangayToken.length;
- }
- const barangayIndex = originalRest.toUpperCase().indexOf(barangayToken.toUpperCase());
- const details = barangayIndex !== -1 && barangayIndex + detailsStartIndex < originalRest.length
- ? originalRest.slice(barangayIndex + detailsStartIndex).trim()
- : undefined;
- const rawType = typeToken.toUpperCase();
- const reportType = TYPE_SYNONYMS[rawType];
- if (!reportType) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const gazetteer = getBarangayGazetteer();
- const barangayLower = barangayToken.toLowerCase();
- const exact = gazetteer.find((b) => b.name.toLowerCase() === barangayLower);
- if (exact) {
- return {
- confidence: 'high',
- parsed: {
- reportType,
- barangay: exact.name,
- details,
- },
- candidates: [],
- autoReplyText: buildAutoReply('high'),
- };
- }
- const fuzzyMatches = [];
- for (const entry of gazetteer) {
- const dist = levenshtein(barangayLower, entry.name.toLowerCase());
- if (dist <= 2) {
- fuzzyMatches.push({ entry, distance: dist });
- }
- }
- if (fuzzyMatches.length === 1) {
- const match = fuzzyMatches[0];
- if (match === undefined) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const { entry, distance: dist } = match;
- return {
- confidence: dist <= 1 ? 'medium' : 'low',
- parsed: {
- reportType,
- barangay: entry.name,
- rawBarangay: barangayToken,
- details,
- },
- candidates: [],
- autoReplyText: buildAutoReply(dist <= 1 ? 'medium' : 'low'),
- };
- }
- if (fuzzyMatches.length > 1) {
- fuzzyMatches.sort((a, b) => a.distance - b.distance);
- const candidates = fuzzyMatches.slice(0, 3).map((m) => m.entry.name);
- return {
- confidence: 'low',
- parsed: null,
- candidates,
- autoReplyText: buildAutoReply('low'),
- };
- }
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
-}
-//# sourceMappingURL=inbound.js.map
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/inbound.js.map b/packages/shared-sms-parser/lib/inbound.js.map
deleted file mode 100644
index d9b8ac61..00000000
--- a/packages/shared-sms-parser/lib/inbound.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/levenshtein.d.ts.map b/packages/shared-sms-parser/lib/levenshtein.d.ts.map
index e11131b1..c63e3756 100644
--- a/packages/shared-sms-parser/lib/levenshtein.d.ts.map
+++ b/packages/shared-sms-parser/lib/levenshtein.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"levenshtein.d.ts","sourceRoot":"","sources":["../src/levenshtein.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA4BxD"}
\ No newline at end of file
+{"version":3,"file":"levenshtein.d.ts","sourceRoot":"","sources":["../src/levenshtein.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAiCxD"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/levenshtein.js b/packages/shared-sms-parser/lib/levenshtein.js
index f5b24f87..a7026a2f 100644
--- a/packages/shared-sms-parser/lib/levenshtein.js
+++ b/packages/shared-sms-parser/lib/levenshtein.js
@@ -1,30 +1,31 @@
export function levenshtein(a, b) {
- const m = a.length;
- const n = b.length;
- if (m === 0)
- return n;
- if (n === 0)
- return m;
- // Flat 1D array for memory efficiency and to avoid noUncheckedIndexedAccess
- const dp = new Uint32Array((m + 1) * (n + 1));
- for (let i = 0; i <= m; i++)
- dp[i * (n + 1)] = i;
- for (let j = 0; j <= n; j++)
- dp[j] = j;
+ let s = a;
+ let t = b;
+ if (s.length > t.length) {
+ ;
+ [s, t] = [t, s];
+ }
+ const m = s.length;
+ const n = t.length;
+ let prev = new Uint32Array(n + 1);
+ let curr = new Uint32Array(n + 1);
+ for (let j = 0; j <= n; j++) {
+ prev[j] = j;
+ }
for (let i = 1; i <= m; i++) {
+ curr[0] = i;
+ const sChar = s[i - 1];
for (let j = 1; j <= n; j++) {
- const idx = i * (n + 1) + j;
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
- const deletion = dp[(i - 1) * (n + 1) + j];
- const insertion = dp[i * (n + 1) + (j - 1)];
- const substitution = dp[(i - 1) * (n + 1) + (j - 1)];
- if (deletion === undefined || insertion === undefined || substitution === undefined) {
- throw new Error('Levenshtein DP index out of bounds');
- }
- dp[idx] = Math.min(deletion + 1, insertion + 1, substitution + cost);
+ const cost = sChar === t[j - 1] ? 0 : 1;
+ const deletion = (prev[j] ?? 0) + 1;
+ const insertion = (curr[j - 1] ?? 0) + 1;
+ const substitution = (prev[j - 1] ?? 0) + cost;
+ curr[j] = Math.min(deletion, insertion, substitution);
}
+ const tmp = prev;
+ prev = curr;
+ curr = tmp;
}
- const result = dp[m * (n + 1) + n];
- return result ?? 0;
+ return prev[n] ?? 0;
}
//# sourceMappingURL=levenshtein.js.map
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/levenshtein.js.map b/packages/shared-sms-parser/lib/levenshtein.js.map
index 83009340..24ae9108 100644
--- a/packages/shared-sms-parser/lib/levenshtein.js.map
+++ b/packages/shared-sms-parser/lib/levenshtein.js.map
@@ -1 +1 @@
-{"version":3,"file":"levenshtein.js","sourceRoot":"","sources":["../src/levenshtein.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IACrB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAErB,4EAA4E;IAC5E,MAAM,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAE7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAChD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1C,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC1C,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC3C,MAAM,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YACpD,IAAI,QAAQ,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBACpF,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YACvD,CAAC;YACD,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAClC,OAAO,MAAM,IAAI,CAAC,CAAA;AACpB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"levenshtein.js","sourceRoot":"","sources":["../src/levenshtein.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC9C,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC;QAAA,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAClB,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAElB,IAAI,IAAI,GAAG,IAAI,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACjC,IAAI,IAAI,GAAG,IAAI,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACb,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACX,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YACvC,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YACnC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YACxC,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;YAC9C,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAA;QACvD,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAA;QAChB,IAAI,GAAG,IAAI,CAAA;QACX,IAAI,GAAG,GAAG,CAAA;IACZ,CAAC;IAED,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACrB,CAAC"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/parser.d.ts.map b/packages/shared-sms-parser/lib/parser.d.ts.map
index 1419989f..1bd69a11 100644
--- a/packages/shared-sms-parser/lib/parser.d.ts.map
+++ b/packages/shared-sms-parser/lib/parser.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;AAE3D,eAAO,MAAM,gBAAgB;;;;;;;EAO3B,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB;AAuBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAyIzD"}
\ No newline at end of file
+{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;AAE3D,eAAO,MAAM,gBAAgB;;;;;;;EAO3B,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB;AAuBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAoIzD"}
\ No newline at end of file
diff --git a/packages/shared-sms-parser/lib/parser.js b/packages/shared-sms-parser/lib/parser.js
index 43480e9d..288cce29 100644
--- a/packages/shared-sms-parser/lib/parser.js
+++ b/packages/shared-sms-parser/lib/parser.js
@@ -76,7 +76,10 @@ export function parseInboundSms(body) {
barangayToken = token1 + ' ' + token2;
detailsStartIndex = barangayToken.length;
}
- const barangayIndex = originalRest.toUpperCase().indexOf(barangayToken.toUpperCase());
+ // Find the barangay token in originalRest using lastIndexOf to prefer the occurrence
+ // closest to where details would start (avoids matching an earlier instance of the token).
+ const barangayTokenUpper = barangayToken.toUpperCase();
+ const barangayIndex = originalRest.toUpperCase().lastIndexOf(barangayTokenUpper);
const details = barangayIndex !== -1 && barangayIndex + detailsStartIndex < originalRest.length
? originalRest.slice(barangayIndex + detailsStartIndex).trim()
: undefined;
@@ -113,16 +116,8 @@ export function parseInboundSms(body) {
}
}
if (fuzzyMatches.length === 1) {
- const match = fuzzyMatches[0];
- if (match === undefined) {
- return {
- confidence: 'none',
- parsed: null,
- candidates: [],
- autoReplyText: buildAutoReply('none'),
- };
- }
- const { entry, distance: dist } = match;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const { entry, distance: dist } = fuzzyMatches[0];
return {
confidence: dist <= 1 ? 'medium' : 'low',
parsed: {
diff --git a/packages/shared-sms-parser/lib/parser.js.map b/packages/shared-sms-parser/lib/parser.js.map
index afdb1423..ec816b2b 100644
--- a/packages/shared-sms-parser/lib/parser.js.map
+++ b/packages/shared-sms-parser/lib/parser.js.map
@@ -1 +1 @@
-{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
From 1e2a23b6ca216f5df77f968f37b79b869129b762 Mon Sep 17 00:00:00 2001
From: Claude
Date: Fri, 24 Apr 2026 07:46:53 +0800
Subject: [PATCH 15/31] a11y(citizen-pwa): label association and aria-pressed
on ContactFields
- Replace with