feat(attendance): add notification delivery and NFC security foundation
This commit is contained in:
@@ -22,16 +22,17 @@ What was validated live against the deployed stack:
|
||||
- staff auth bootstrap
|
||||
- client dashboard, billing, coverage, hubs, vendors, managers, team members, orders, and reports
|
||||
- client coverage incident feed for geofence and override review
|
||||
- client hub, order, coverage review, and late-worker cancellation flows
|
||||
- client hub, order, coverage review, device token, and late-worker cancellation flows
|
||||
- client invoice approve and dispute
|
||||
- staff dashboard, availability, payments, shifts, profile sections, documents, certificates, attire, bank accounts, benefits, and time card
|
||||
- staff availability, profile, tax form, bank account, shift apply, shift accept, clock-in, clock-out, location stream upload, and swap request
|
||||
- staff availability, profile, tax form, bank account, shift apply, shift accept, push token registration, clock-in, clock-out, location stream upload, and swap request
|
||||
- direct file upload helpers and verification job creation through the unified host
|
||||
- client and staff sign-out
|
||||
|
||||
The live validation command is:
|
||||
|
||||
```bash
|
||||
export FIREBASE_WEB_API_KEY="$(gcloud secrets versions access latest --secret=firebase-web-api-key --project=krow-workforce-dev)"
|
||||
source ~/.nvm/nvm.sh
|
||||
nvm use 23.5.0
|
||||
node backend/unified-api/scripts/live-smoke-v2-unified.mjs
|
||||
@@ -101,10 +102,12 @@ Important operational rules:
|
||||
|
||||
- outside-geofence clock-ins can be accepted only when override is enabled and a written reason is provided
|
||||
- NFC mismatches are rejected and are not overrideable
|
||||
- attendance proof logs are durable in SQL and raw object storage
|
||||
- device push tokens are durable in SQL and can be registered separately for client and staff apps
|
||||
- background location streams are stored as raw batch payloads in the private v2 bucket and summarized in SQL for query speed
|
||||
- incident review lives on `GET /client/coverage/incidents`
|
||||
- confirmed late-worker recovery is exposed on `POST /client/coverage/late-workers/:assignmentId/cancel`
|
||||
- queued manager alerts are written to `notification_outbox`; this is durable notification orchestration, not a full push delivery worker yet
|
||||
- queued alerts are written to `notification_outbox`, dispatched by Cloud Run job `krow-notification-dispatcher-v2`, and recorded in `notification_deliveries`
|
||||
|
||||
## 5) Route model
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ The gateway keeps backend services separate internally, but frontend should trea
|
||||
|
||||
### Client writes
|
||||
|
||||
- `POST /client/devices/push-tokens`
|
||||
- `DELETE /client/devices/push-tokens`
|
||||
- `POST /client/orders/one-time`
|
||||
- `POST /client/orders/recurring`
|
||||
- `POST /client/orders/permanent`
|
||||
@@ -113,6 +115,8 @@ The gateway keeps backend services separate internally, but frontend should trea
|
||||
### Staff writes
|
||||
|
||||
- `POST /staff/profile/setup`
|
||||
- `POST /staff/devices/push-tokens`
|
||||
- `DELETE /staff/devices/push-tokens`
|
||||
- `POST /staff/clock-in`
|
||||
- `POST /staff/clock-out`
|
||||
- `POST /staff/location-streams`
|
||||
@@ -170,11 +174,40 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
- For `POST /staff/clock-in` and `POST /staff/clock-out`:
|
||||
- send `nfcTagId` when clocking with NFC
|
||||
- send `latitude`, `longitude`, and `accuracyMeters` when clocking with geolocation
|
||||
- send `proofNonce` and `proofTimestamp` for attendance-proof logging; these are most important on NFC paths
|
||||
- send `attestationProvider` and `attestationToken` only when the device has a real attestation result to forward
|
||||
- send `overrideReason` only when the worker is bypassing a geofence failure and the shift/hub allows overrides
|
||||
- `POST /staff/location-streams` is for the background tracking loop after a worker is already clocked in.
|
||||
- `GET /client/coverage/incidents` is the review feed for geofence breaches, missing-location batches, and clock-in overrides.
|
||||
- `POST /client/coverage/late-workers/:assignmentId/cancel` is the client-side recovery action when lateness is confirmed by incident evidence or elapsed grace time.
|
||||
- Raw location stream payloads are stored in the private v2 bucket; SQL only stores the summary and incident index.
|
||||
- Push delivery is backed by:
|
||||
- SQL token registry in `device_push_tokens`
|
||||
- durable queue in `notification_outbox`
|
||||
- per-attempt delivery records in `notification_deliveries`
|
||||
- Cloud Run job `krow-notification-dispatcher-v2`
|
||||
|
||||
### Push token request example
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "FCM",
|
||||
"platform": "IOS",
|
||||
"pushToken": "expo-or-fcm-device-token",
|
||||
"deviceId": "iphone-15-pro-max",
|
||||
"appVersion": "2.0.0",
|
||||
"appBuild": "2000",
|
||||
"locale": "en-US",
|
||||
"timezone": "America/Los_Angeles"
|
||||
}
|
||||
```
|
||||
|
||||
Push-token delete requests may send `tokenId` or `pushToken` either:
|
||||
|
||||
- as JSON in the request body
|
||||
- or as query params on the `DELETE` URL
|
||||
|
||||
Using query params is safer when the client stack or proxy is inconsistent about forwarding `DELETE` bodies.
|
||||
|
||||
### Clock-in request example
|
||||
|
||||
@@ -186,6 +219,8 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
"latitude": 37.4221,
|
||||
"longitude": -122.0841,
|
||||
"accuracyMeters": 12,
|
||||
"proofNonce": "nonce-generated-on-device",
|
||||
"proofTimestamp": "2026-03-16T09:00:00.000Z",
|
||||
"overrideReason": "Parking garage entrance is outside the marked hub geofence",
|
||||
"capturedAt": "2026-03-16T09:00:00.000Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user