docs(api): add mobile coding agent spec
This commit is contained in:
@@ -160,6 +160,7 @@ Those routes still exist for backend/internal compatibility, but mobile/frontend
|
|||||||
|
|
||||||
- [Authentication](./authentication.md)
|
- [Authentication](./authentication.md)
|
||||||
- [Unified API](./unified-api.md)
|
- [Unified API](./unified-api.md)
|
||||||
|
- [Mobile Coding Agent Spec](./mobile-coding-agent-spec.md)
|
||||||
- [Mobile Frontend Implementation Spec](./mobile-frontend-implementation-spec.md)
|
- [Mobile Frontend Implementation Spec](./mobile-frontend-implementation-spec.md)
|
||||||
- [Staff Shifts](./staff-shifts.md)
|
- [Staff Shifts](./staff-shifts.md)
|
||||||
- [Core API](./core-api.md)
|
- [Core API](./core-api.md)
|
||||||
|
|||||||
387
docs/BACKEND/API_GUIDES/V2/mobile-coding-agent-spec.md
Normal file
387
docs/BACKEND/API_GUIDES/V2/mobile-coding-agent-spec.md
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
# Mobile Coding Agent Spec
|
||||||
|
|
||||||
|
This document is the frontend handoff spec for an AI coding agent working on the mobile applications against the v2 backend.
|
||||||
|
|
||||||
|
Use this as the primary implementation brief.
|
||||||
|
|
||||||
|
Base URL:
|
||||||
|
|
||||||
|
- `https://krow-api-v2-933560802882.us-central1.run.app`
|
||||||
|
|
||||||
|
Supporting docs:
|
||||||
|
|
||||||
|
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/authentication.md`
|
||||||
|
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/unified-api.md`
|
||||||
|
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/mobile-frontend-implementation-spec.md`
|
||||||
|
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/staff-shifts.md`
|
||||||
|
|
||||||
|
## 1) Non-negotiable rules
|
||||||
|
|
||||||
|
- Use the unified base URL only.
|
||||||
|
- Do not call `/query/*`, `/commands/*`, or `/core/*` directly from frontend.
|
||||||
|
- Send `Authorization: Bearer <firebase-id-token>` on protected routes.
|
||||||
|
- Send `Idempotency-Key` on every write route.
|
||||||
|
- Treat `order`, `shift`, `shiftRole`, and `assignment` as different objects.
|
||||||
|
- For staff shift applications, `roleId` must come from the response of `GET /staff/shifts/open`.
|
||||||
|
|
||||||
|
## 2) What is implemented now
|
||||||
|
|
||||||
|
Safe to build against now:
|
||||||
|
|
||||||
|
- client auth/session
|
||||||
|
- client dashboard, billing, coverage, hubs, vendors, managers, team members, orders, reports
|
||||||
|
- client coverage reviews, worker rating, block/unblock, late-worker cancellation
|
||||||
|
- client swap review and dispatch-team management
|
||||||
|
- staff auth/session
|
||||||
|
- staff dashboard, availability, payments, shifts, profile, tax forms, bank accounts, benefits, documents, attire, certificates
|
||||||
|
- staff clock-in, clock-out, location streaming, swap request, completed-shift submission
|
||||||
|
- upload, signed URL, verification, and rapid-order processing
|
||||||
|
|
||||||
|
Not part of this implementation spec:
|
||||||
|
|
||||||
|
- backend `/auth/refresh`
|
||||||
|
- SMS or email notification fallback
|
||||||
|
- AI-driven report insights
|
||||||
|
- AI-driven personalized shift matching
|
||||||
|
- full NFC attestation enforcement
|
||||||
|
- chat backend
|
||||||
|
|
||||||
|
## 3) Auth implementation
|
||||||
|
|
||||||
|
### Client app
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
- `POST /auth/client/sign-in`
|
||||||
|
- `POST /auth/client/sign-up`
|
||||||
|
- `GET /auth/session`
|
||||||
|
- `POST /auth/client/sign-out`
|
||||||
|
|
||||||
|
Do not build a separate refresh route.
|
||||||
|
|
||||||
|
Token refresh remains on the Firebase client SDK side.
|
||||||
|
|
||||||
|
### Staff app
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
- `POST /auth/staff/phone/start`
|
||||||
|
- `POST /auth/staff/phone/verify`
|
||||||
|
- `GET /auth/session`
|
||||||
|
- `POST /auth/staff/sign-out`
|
||||||
|
|
||||||
|
Important:
|
||||||
|
|
||||||
|
- `POST /auth/staff/phone/start` can return `mode = CLIENT_FIREBASE_SDK`
|
||||||
|
- when that happens, the app must complete Firebase phone verification on-device
|
||||||
|
- after that, the app must call `POST /auth/staff/phone/verify` with the Firebase `idToken`
|
||||||
|
|
||||||
|
Do not assume staff auth is a fully backend-managed OTP flow.
|
||||||
|
|
||||||
|
## 4) Core data model assumptions
|
||||||
|
|
||||||
|
- `order`: client-facing staffing request
|
||||||
|
- `shift`: a scheduled work instance under an order
|
||||||
|
- `shiftRole`: a role slot inside a shift
|
||||||
|
- `application`: worker applies to a `shiftRole`
|
||||||
|
- `assignment`: worker is actually attached to a shift
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `GET /staff/shifts/open` returns opportunities, not assignments
|
||||||
|
- `GET /staff/shifts/assigned` returns active assigned shifts
|
||||||
|
- `GET /client/orders/view` is the timeline/read model for client
|
||||||
|
- `POST /client/orders/:orderId/edit` and `POST /client/orders/:orderId/cancel` apply to future shifts only
|
||||||
|
|
||||||
|
## 5) Client app screen mapping
|
||||||
|
|
||||||
|
### Home
|
||||||
|
|
||||||
|
- `GET /client/session`
|
||||||
|
- `GET /client/dashboard`
|
||||||
|
- `GET /client/reorders`
|
||||||
|
|
||||||
|
### Billing
|
||||||
|
|
||||||
|
- `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`
|
||||||
|
|
||||||
|
Coverage review payload:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"assignmentId": "uuid",
|
||||||
|
"rating": 4,
|
||||||
|
"comment": "Strong performance on the shift",
|
||||||
|
"markAsBlocked": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- worker rating happens through `POST /client/coverage/reviews`
|
||||||
|
- blocking a worker is done through the same endpoint using `markAsBlocked`
|
||||||
|
- dispatch ranking order is:
|
||||||
|
1. `CORE`
|
||||||
|
2. `CERTIFIED_LOCATION`
|
||||||
|
3. `MARKETPLACE`
|
||||||
|
|
||||||
|
Swap management flow:
|
||||||
|
|
||||||
|
1. worker requests swap
|
||||||
|
2. backend moves original assignment to `SWAP_REQUESTED`
|
||||||
|
3. replacement workers see the shift in `GET /staff/shifts/open`
|
||||||
|
4. client/ops reads `GET /client/coverage/swap-requests`
|
||||||
|
5. client/ops reads `GET /client/coverage/dispatch-candidates`
|
||||||
|
6. client/ops resolves or cancels the swap request
|
||||||
|
7. if unresolved and expired, backend auto-cancels it
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
- `POST /rapid-orders/process`
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- use `POST /rapid-orders/process` for the single-call rapid-order flow
|
||||||
|
- recent orders should expect total price and hourly rate fields
|
||||||
|
- order edit and cancel only affect future shifts
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `POST /client/shift-managers` creates an invited manager identity
|
||||||
|
- if `hubId` is present, backend links the manager to that hub too
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
|
||||||
|
Important:
|
||||||
|
|
||||||
|
- these are operational reports
|
||||||
|
- this is not the same as the separate AI insights research issue
|
||||||
|
|
||||||
|
## 6) Staff app screen mapping
|
||||||
|
|
||||||
|
### Home
|
||||||
|
|
||||||
|
- `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:
|
||||||
|
|
||||||
|
- use `roleId` from the open-shifts response
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
|
||||||
|
Staff shift detail and list rules:
|
||||||
|
|
||||||
|
- assigned shifts include `clientName`, `hourlyRate`, `totalRate`, `startTime`, `endTime`
|
||||||
|
- shift detail includes `clientName`, `latitude`, `longitude`, `hourlyRate`, `totalRate`
|
||||||
|
- completed shifts include `date`, `clientName`, `startTime`, `endTime`, `hourlyRate`, `totalRate`
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
|
||||||
|
Clock-in payload rules:
|
||||||
|
|
||||||
|
- if using NFC, send `nfcTagId`
|
||||||
|
- if using geo, send `latitude`, `longitude`, `accuracyMeters`
|
||||||
|
- send `overrideReason` only when geo override is allowed
|
||||||
|
- send `proofNonce` and `proofTimestamp` on attendance writes
|
||||||
|
- send `attestationProvider` and `attestationToken` only if the device has them
|
||||||
|
|
||||||
|
Clock-in read rules:
|
||||||
|
|
||||||
|
`GET /staff/clock-in/shifts/today` returns fields including:
|
||||||
|
|
||||||
|
- `clientName`
|
||||||
|
- `hourlyRate`
|
||||||
|
- `totalRate`
|
||||||
|
- `latitude`
|
||||||
|
- `longitude`
|
||||||
|
- `clockInMode`
|
||||||
|
- `allowClockInOverride`
|
||||||
|
- `geofenceRadiusMeters`
|
||||||
|
- `nfcTagId`
|
||||||
|
|
||||||
|
Policy values:
|
||||||
|
|
||||||
|
- `NFC_REQUIRED`
|
||||||
|
- `GEO_REQUIRED`
|
||||||
|
- `EITHER`
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
|
||||||
|
Profile data rules:
|
||||||
|
|
||||||
|
- `GET /staff/profile/documents` returns documents only
|
||||||
|
- `GET /staff/profile/attire` returns attire only
|
||||||
|
- `GET /staff/profile/tax-forms` returns tax forms only
|
||||||
|
- `GET /staff/profile/certificates` returns certificates only
|
||||||
|
- benefit summary and benefit history are separate endpoints
|
||||||
|
|
||||||
|
### FAQ
|
||||||
|
|
||||||
|
- `GET /staff/faqs`
|
||||||
|
- `GET /staff/faqs/search?q=...`
|
||||||
|
|
||||||
|
## 7) Upload flows
|
||||||
|
|
||||||
|
### General upload pattern
|
||||||
|
|
||||||
|
For documents, attire, and certificates:
|
||||||
|
|
||||||
|
1. `POST /upload-file`
|
||||||
|
2. `POST /create-signed-url`
|
||||||
|
3. upload bytes to storage
|
||||||
|
4. `POST /verifications`
|
||||||
|
5. finalize using the appropriate staff route
|
||||||
|
|
||||||
|
Staff upload routes:
|
||||||
|
|
||||||
|
- `POST /staff/profile/photo`
|
||||||
|
- `POST /staff/profile/documents/:documentId/upload`
|
||||||
|
- `PUT /staff/profile/documents/:documentId/upload`
|
||||||
|
- `POST /staff/profile/attire/:documentId/upload`
|
||||||
|
- `PUT /staff/profile/attire/:documentId/upload`
|
||||||
|
- `POST /staff/profile/certificates`
|
||||||
|
- `DELETE /staff/profile/certificates/:certificateId`
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- backend treats verification-linked file state as the source of truth
|
||||||
|
- frontend may still send `fileUri` or `photoUrl`, but verification linkage wins
|
||||||
|
|
||||||
|
## 8) What the coding agent should not assume
|
||||||
|
|
||||||
|
- do not invent a backend refresh route
|
||||||
|
- do not assume swap is staff-only; there is now a client/ops review side
|
||||||
|
- do not assume documents and attire share the same read endpoint
|
||||||
|
- do not assume backend direct CRUD on internal services
|
||||||
|
- do not assume AI reports, SMS fallback, or full NFC attestation are available
|
||||||
|
|
||||||
|
## 9) Suggested implementation order for the coding agent
|
||||||
|
|
||||||
|
1. auth/session flows
|
||||||
|
2. client home + orders + coverage
|
||||||
|
3. staff home + shifts + clock-in
|
||||||
|
4. profile sections and upload flows
|
||||||
|
5. reports and billing polish
|
||||||
|
6. swap review and dispatch-team management
|
||||||
|
|
||||||
|
## 10) Definition of done for frontend integration
|
||||||
|
|
||||||
|
Frontend implementation is aligned when:
|
||||||
|
|
||||||
|
- every screen calls the unified v2 routes only
|
||||||
|
- every write sends an `Idempotency-Key`
|
||||||
|
- staff shift apply uses `roleId` from open shifts
|
||||||
|
- clock-in respects `clockInMode`
|
||||||
|
- swap request uses the staff endpoint and swap review uses the client coverage endpoints
|
||||||
|
- documents, attire, certificates, and tax forms use their correct route families
|
||||||
Reference in New Issue
Block a user