feat(attendance): add notification delivery and NFC security foundation
This commit is contained in:
@@ -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