Files
Krow-workspace/docs/BACKEND/API_GUIDES/V2/mobile-frontend-implementation-spec.md
2026-03-18 12:56:14 +01:00

306 lines
9.0 KiB
Markdown

# Mobile Frontend Implementation Spec
This is the shortest path for frontend to implement the v2 mobile clients against the unified backend.
Base URL:
- `https://krow-api-v2-933560802882.us-central1.run.app`
Use this doc together with:
- [Authentication](./authentication.md)
- [Unified API](./unified-api.md)
- [Staff Shifts](./staff-shifts.md)
## 1) Global rules
- Use unified routes only.
- Send `Authorization: Bearer <firebase-id-token>` on protected routes.
- Send `Idempotency-Key` on all write routes.
- Do not call `/query/*`, `/commands/*`, or `/core/*` directly from frontend.
## 2) Core model frontend should assume
- `order` is the client-facing request for staffing.
- `shift` is the concrete scheduled unit of work under an order.
- `shiftRole` is the role slot inside a shift that staff apply to.
- `assignment` is the worker-to-shift record once a worker is attached.
Important consequences:
- `GET /staff/shifts/open` returns open shift-role opportunities.
- `POST /staff/shifts/:shiftId/apply` must send the `roleId` from that response.
- `GET /client/orders/view` is the timeline/read model for the client app.
- `POST /client/orders/:orderId/edit` and `POST /client/orders/:orderId/cancel` only affect future shifts.
## 3) Auth implementation
### Client app
- sign in with `POST /auth/client/sign-in`
- sign up with `POST /auth/client/sign-up`
- hydrate session with `GET /auth/session`
- sign out with `POST /auth/client/sign-out`
### Staff app
- start phone auth with `POST /auth/staff/phone/start`
- complete phone auth with `POST /auth/staff/phone/verify`
- hydrate session with `GET /auth/session`
- sign out with `POST /auth/staff/sign-out`
Token refresh:
- keep using Firebase client SDK refresh behavior
- there is no backend `/auth/refresh` route
## 4) Client app screen mapping
### Home / dashboard
- `GET /client/session`
- `GET /client/dashboard`
- `GET /client/reorders`
### Billing / payments
- `GET /client/billing/accounts`
- `GET /client/billing/invoices/pending`
- `GET /client/billing/invoices/history`
- `GET /client/billing/current-bill`
- `GET /client/billing/savings`
- `GET /client/billing/spend-breakdown`
- `POST /client/billing/invoices/:invoiceId/approve`
- `POST /client/billing/invoices/:invoiceId/dispute`
### Coverage
- `GET /client/coverage?date=YYYY-MM-DD`
- `GET /client/coverage/stats?date=YYYY-MM-DD`
- `GET /client/coverage/core-team?date=YYYY-MM-DD`
- `GET /client/coverage/incidents?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD`
- `GET /client/coverage/blocked-staff`
- `GET /client/coverage/swap-requests?status=OPEN`
- `GET /client/coverage/dispatch-teams`
- `GET /client/coverage/dispatch-candidates?shiftId=uuid&roleId=uuid`
- `POST /client/coverage/reviews`
- `POST /client/coverage/late-workers/:assignmentId/cancel`
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
- `POST /client/coverage/dispatch-teams/memberships`
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
Use `POST /client/coverage/reviews` when the business is rating a worker after coverage review.
Payload may include:
```json
{
"staffId": "uuid",
"assignmentId": "uuid",
"rating": 4,
"feedback": "Strong performance on the shift",
"markAsFavorite": true,
"markAsBlocked": false
}
```
If `markAsFavorite` is `true`, backend adds that worker to the business favorites list. If `markAsFavorite` is `false`, backend removes them from that list. If `markAsBlocked` is `true`, backend blocks that worker for that business and rejects future apply or assign attempts until a later review sets `markAsBlocked: false`.
Swap-management rule:
- use `GET /client/coverage/swap-requests` as the client review feed
- use `GET /client/coverage/dispatch-candidates` for the ranked replacement list
- use `POST /client/coverage/swap-requests/:swapRequestId/resolve` when ops selects a replacement
- use `POST /client/coverage/swap-requests/:swapRequestId/cancel` when ops wants to close the swap request without replacement
Dispatch-priority rule:
1. `CORE`
2. `CERTIFIED_LOCATION`
3. `MARKETPLACE`
### Orders
- `GET /client/orders/view`
- `GET /client/orders/:orderId/reorder-preview`
- `POST /client/orders/one-time`
- `POST /client/orders/recurring`
- `POST /client/orders/permanent`
- `POST /client/orders/:orderId/edit`
- `POST /client/orders/:orderId/cancel`
Rapid-order flow:
- use `POST /rapid-orders/process` for the single-call transcribe-and-parse flow
### Hubs and managers
- `GET /client/hubs`
- `GET /client/cost-centers`
- `GET /client/hubs/:hubId/managers`
- `GET /client/team-members`
- `POST /client/shift-managers`
- `POST /client/hubs`
- `PUT /client/hubs/:hubId`
- `DELETE /client/hubs/:hubId`
- `POST /client/hubs/:hubId/assign-nfc`
- `POST /client/hubs/:hubId/managers`
`POST /client/shift-managers` is the fastest path to create an invited manager identity for a business. If `hubId` is provided, backend also links that manager to the hub.
### Reports
- `GET /client/reports/summary?date=YYYY-MM-DD`
- `GET /client/reports/daily-ops?date=YYYY-MM-DD`
- `GET /client/reports/spend?date=YYYY-MM-DD`
- `GET /client/reports/coverage?date=YYYY-MM-DD`
- `GET /client/reports/forecast?date=YYYY-MM-DD`
- `GET /client/reports/performance?date=YYYY-MM-DD`
- `GET /client/reports/no-show?date=YYYY-MM-DD`
## 5) Staff app screen mapping
### Home / dashboard
- `GET /staff/session`
- `GET /staff/dashboard`
- `GET /staff/profile-completion`
### Availability
- `GET /staff/availability`
- `PUT /staff/availability`
- `POST /staff/availability/quick-set`
### Find shifts
- `GET /staff/shifts/open`
- `POST /staff/shifts/:shiftId/apply`
Rule:
- send the `roleId` from the open-shifts response
- this is the concrete `shift_roles.id`
### My shifts
- `GET /staff/shifts/pending`
- `GET /staff/shifts/assigned`
- `GET /staff/shifts/cancelled`
- `GET /staff/shifts/completed`
- `GET /staff/shifts/:shiftId`
- `POST /staff/shifts/:shiftId/accept`
- `POST /staff/shifts/:shiftId/decline`
- `POST /staff/shifts/:shiftId/request-swap`
- `POST /staff/shifts/:shiftId/submit-for-approval`
Current swap behavior:
- backend records the swap request
- assignment moves to `SWAP_REQUESTED`
- shift becomes visible in the replacement pool
- client/ops can review and resolve swap requests through the coverage endpoints
- if the swap request expires without coverage, backend auto-cancels it and alerts both the manager path and the original worker
### Clock in / clock out
- `GET /staff/clock-in/shifts/today`
- `GET /staff/clock-in/status`
- `POST /staff/clock-in`
- `POST /staff/clock-out`
- `POST /staff/location-streams`
Frontend should respect:
- `clockInMode`
- `allowClockInOverride`
- `latitude`
- `longitude`
- `geofenceRadiusMeters`
- `nfcTagId`
Clock-in proof rules:
- use `nfcTagId` for NFC clocking
- use `latitude`, `longitude`, and `accuracyMeters` for geolocation clocking
- send `overrideReason` only when a geofence override is allowed
- send `proofNonce` and `proofTimestamp` on attendance writes
### Payments
- `GET /staff/payments/summary`
- `GET /staff/payments/history`
- `GET /staff/payments/chart`
### Profile
- `GET /staff/profile/sections`
- `GET /staff/profile/personal-info`
- `GET /staff/profile/industries`
- `GET /staff/profile/skills`
- `GET /staff/profile/documents`
- `GET /staff/profile/attire`
- `GET /staff/profile/tax-forms`
- `GET /staff/profile/emergency-contacts`
- `GET /staff/profile/certificates`
- `GET /staff/profile/bank-accounts`
- `GET /staff/profile/benefits`
- `GET /staff/profile/benefits/history`
- `GET /staff/profile/time-card`
- `GET /staff/profile/privacy`
- `PUT /staff/profile/personal-info`
- `PUT /staff/profile/experience`
- `PUT /staff/profile/locations`
- `POST /staff/profile/emergency-contacts`
- `PUT /staff/profile/emergency-contacts/:contactId`
- `PUT /staff/profile/tax-forms/:formType`
- `POST /staff/profile/tax-forms/:formType/submit`
- `POST /staff/profile/bank-accounts`
- `PUT /staff/profile/privacy`
Document model rule:
- `GET /staff/profile/documents` returns only documents
- `GET /staff/profile/attire` returns attire items
- `GET /staff/profile/tax-forms` returns tax-form rows
- `GET /staff/profile/certificates` returns certificates
### FAQ
- `GET /staff/faqs`
- `GET /staff/faqs/search?q=...`
## 6) Upload implementation
For documents, attire, and certificates:
1. `POST /upload-file`
2. `POST /create-signed-url`
3. upload file bytes to storage with the signed URL
4. `POST /verifications`
5. finalize with:
- `PUT /staff/profile/documents/:documentId/upload`
- `PUT /staff/profile/attire/:documentId/upload`
- `POST /staff/profile/certificates`
Use the verification-linked file as the source of truth.
## 7) What frontend should not assume
- do not assume order edit mutates past shifts
- do not assume swap resolution is complete beyond the request step
- do not assume raw `/query/*` or `/commands/*` routes are stable for app integration
- do not assume blocked workers can still apply to future shifts for that business
## 8) Demo reset
To reset dev demo data:
```bash
source ~/.nvm/nvm.sh
nvm use 23.5.0
cd backend/command-api
npm run seed:v2-demo
```