feat(api): complete unified v2 mobile surface

This commit is contained in:
zouantchaw
2026-03-13 17:02:24 +01:00
parent 817a39e305
commit b455455a49
39 changed files with 7726 additions and 506 deletions

View File

@@ -2,33 +2,48 @@
This is the frontend-facing source of truth for the v2 backend.
## 1) Frontend entrypoint
## 1) Use one base URL
Frontend should target one public base URL:
Frontend should call one public gateway:
```env
API_V2_BASE_URL=<krow-api-v2-url>
API_V2_BASE_URL=https://krow-api-v2-933560802882.us-central1.run.app
```
The unified v2 gateway exposes:
Frontend should not call the internal `core`, `command`, or `query` Cloud Run services directly.
- `/auth/*`
- `/core/*`
- `/commands/*`
- `/query/*`
- `/query/client/*`
- `/query/staff/*`
## 2) Current status
Internal services still stay separate behind that gateway.
The unified v2 gateway is ready for frontend integration in `dev`.
## 2) Internal service split
What was validated live against the deployed stack:
| Use case | Internal service |
| --- | --- |
| File upload, signed URLs, model calls, verification helpers | `core-api-v2` |
| Business writes and workflow actions | `command-api-v2` |
| Screen reads and mobile read models | `query-api-v2` |
| Frontend-facing single host and auth wrappers | `krow-api-v2` |
- client sign-in
- staff auth bootstrap
- client dashboard, billing, coverage, hubs, vendors, managers, team members, orders, and reports
- client hub and order write 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, 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
source ~/.nvm/nvm.sh
nvm use 23.5.0
node backend/unified-api/scripts/live-smoke-v2-unified.mjs
```
The demo tenant can be reset with:
```bash
source ~/.nvm/nvm.sh
nvm use 23.5.0
cd backend/command-api
npm run seed:v2-demo
```
## 3) Auth and headers
@@ -38,13 +53,19 @@ Protected routes require:
Authorization: Bearer <firebase-id-token>
```
Command routes also require:
Write routes also require:
```http
Idempotency-Key: <unique-per-user-action>
```
All services return the same error envelope:
For now:
- backend wraps sign-in and sign-out
- frontend can keep using Firebase token refresh on the client
- backend is the only thing frontend should call for session-oriented API flows
All routes return the same error envelope:
```json
{
@@ -55,83 +76,35 @@ All services return the same error envelope:
}
```
## 4) What frontend can use now on this branch
## 4) Route model
### Unified gateway
Frontend sees one base URL and one route shape:
- `POST /auth/client/sign-in`
- `POST /auth/client/sign-up`
- `POST /auth/sign-out`
- `POST /auth/client/sign-out`
- `POST /auth/staff/sign-out`
- `GET /auth/session`
- Proxy access to `/core/*`, `/commands/*`, `/query/*`
- `/auth/*`
- `/client/*`
- `/staff/*`
- direct upload aliases like `/upload-file` and `/staff/profile/*`
### Client read routes
Internally, the gateway still forwards to:
- `GET /query/client/session`
- `GET /query/client/dashboard`
- `GET /query/client/reorders`
- `GET /query/client/billing/accounts`
- `GET /query/client/billing/invoices/pending`
- `GET /query/client/billing/invoices/history`
- `GET /query/client/billing/current-bill`
- `GET /query/client/billing/savings`
- `GET /query/client/billing/spend-breakdown`
- `GET /query/client/coverage`
- `GET /query/client/coverage/stats`
- `GET /query/client/hubs`
- `GET /query/client/cost-centers`
- `GET /query/client/vendors`
- `GET /query/client/vendors/:vendorId/roles`
- `GET /query/client/hubs/:hubId/managers`
- `GET /query/client/orders/view`
| Frontend use case | Internal service |
| --- | --- |
| auth/session wrapper | `krow-api-v2` |
| uploads, signed URLs, model calls, verification workflows | `core-api-v2` |
| writes and workflow actions | `command-api-v2` |
| reads and mobile read models | `query-api-v2` |
### Staff read routes
## 5) Frontend integration rule
- `GET /query/staff/session`
- `GET /query/staff/dashboard`
- `GET /query/staff/profile-completion`
- `GET /query/staff/availability`
- `GET /query/staff/clock-in/shifts/today`
- `GET /query/staff/clock-in/status`
- `GET /query/staff/payments/summary`
- `GET /query/staff/payments/history`
- `GET /query/staff/payments/chart`
- `GET /query/staff/shifts/assigned`
- `GET /query/staff/shifts/open`
- `GET /query/staff/shifts/pending`
- `GET /query/staff/shifts/cancelled`
- `GET /query/staff/shifts/completed`
- `GET /query/staff/shifts/:shiftId`
- `GET /query/staff/profile/sections`
- `GET /query/staff/profile/personal-info`
- `GET /query/staff/profile/industries`
- `GET /query/staff/profile/skills`
- `GET /query/staff/profile/documents`
- `GET /query/staff/profile/certificates`
- `GET /query/staff/profile/bank-accounts`
- `GET /query/staff/profile/benefits`
Use the unified routes first.
### Existing v2 routes still valid
Do not build new frontend work on:
- `/core/*` routes documented in `core-api.md`
- `/commands/*` routes documented in `command-api.md`
- `/query/tenants/*` routes documented in `query-api.md`
- `/query/tenants/*`
- `/commands/*`
- `/core/*`
## 5) Remaining gaps after this slice
Still not implemented yet:
- staff phone OTP wrapper endpoints
- hub write flows
- hub NFC assignment write route
- invoice approve and dispute commands
- staff apply / decline / request swap commands
- staff profile update commands
- availability write commands
- reports suite
- durable verification persistence in `core-api-v2`
Those routes still exist for backend/internal compatibility, but mobile/frontend migration should target the unified surface documented in [Unified API](./unified-api.md).
## 6) Docs
@@ -139,4 +112,4 @@ Still not implemented yet:
- [Core API](./core-api.md)
- [Command API](./command-api.md)
- [Query API](./query-api.md)
- [Mobile gap analysis](./mobile-api-gap-analysis.md)
- [Mobile API Reconciliation](./mobile-api-gap-analysis.md)

View File

@@ -1,66 +1,45 @@
# Mobile API Gap Analysis
# Mobile API Reconciliation
Source compared against implementation:
- `/Users/wiel/Downloads/mobile-backend-api-specification.md`
- `mobile-backend-api-specification.md`
## Implemented in this slice
## Result
- unified frontend-facing base URL design
- client auth wrapper for email/password sign-in and sign-up
- auth session and sign-out endpoints
- client read surface for dashboard, billing, coverage, hubs, vendor lookup, and date-range order items
- staff read surface for dashboard, availability, clock-in reads, payments, shifts, and profile sections
- schema support for:
- cost centers
- hub managers
- recurring staff availability
- staff benefits
- seed support for:
- authenticated demo staff user
- cost center and hub manager data
- staff benefits and availability
- attire and tax-form example documents
The current mobile v2 surface is implemented behind the unified gateway and validated live in `dev`.
## Still missing
That includes:
### Auth
- auth session routes
- client dashboard, billing, coverage, hubs, vendor lookup, managers, team members, orders, and reports
- client order, hub, coverage review, and invoice write flows
- staff dashboard, availability, payments, shifts, profile sections, documents, attire, certificates, bank accounts, benefits, privacy, and frequently asked questions
- staff availability, tax forms, emergency contacts, bank account, shift decision, clock-in/out, and swap write flows
- upload and verification flows for profile photo, government document, attire, and certificates
- staff phone OTP start
- staff OTP verify
- staff profile setup endpoint
## What was validated live
### Client writes
The live smoke executed successfully against:
- hub create
- hub update
- hub delete
- hub NFC assignment
- assign manager to hub
- invoice approve
- invoice dispute
- `https://krow-api-v2-933560802882.us-central1.run.app`
- Firebase demo users
- `krow-sql-v2`
- `krow-core-api-v2`
- `krow-command-api-v2`
- `krow-query-api-v2`
### Staff writes
The validation script is:
- availability update
- availability quick set
- shift apply
- shift decline
- request swap
- personal info update
- preferred locations update
- profile photo upload wrapper
```bash
node backend/unified-api/scripts/live-smoke-v2-unified.mjs
```
### Reports
## Remaining work
- report summary
- daily ops
- spend
- coverage
- forecast
- performance
- no-show
The remaining items are not blockers for current mobile frontend migration.
### Core persistence
They are follow-up items:
- `core-api-v2` verification jobs still need durable SQL persistence
- extend the same unified pattern to new screens added after the current mobile specification
- add stronger observability and contract automation around the unified route surface
- keep refining reporting and financial read models as product scope expands

View File

@@ -1,50 +1,168 @@
# Unified API V2
This service exists so frontend can use one base URL without forcing backend into one codebase.
Frontend should use this service as the single base URL:
## Base idea
- `https://krow-api-v2-933560802882.us-central1.run.app`
Frontend talks to one service:
The gateway keeps backend services separate internally, but frontend should treat it as one API.
- `krow-api-v2`
## 1) Auth routes
That gateway does two things:
1. exposes auth/session endpoints
2. forwards requests to the right internal v2 service
## Route groups
### Auth
### Client auth
- `POST /auth/client/sign-in`
- `POST /auth/client/sign-up`
- `POST /auth/sign-out`
- `POST /auth/client/sign-out`
### Staff auth
- `POST /auth/staff/phone/start`
- `POST /auth/staff/phone/verify`
- `POST /auth/staff/sign-out`
### Shared auth
- `GET /auth/session`
- `POST /auth/sign-out`
### Proxy passthrough
## 2) Client routes
- `/core/*` -> `core-api-v2`
- `/commands/*` -> `command-api-v2`
- `/query/*` -> `query-api-v2`
### Client reads
### Mobile read models
- `GET /client/session`
- `GET /client/dashboard`
- `GET /client/reorders`
- `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`
- `GET /client/coverage`
- `GET /client/coverage/stats`
- `GET /client/coverage/core-team`
- `GET /client/hubs`
- `GET /client/cost-centers`
- `GET /client/vendors`
- `GET /client/vendors/:vendorId/roles`
- `GET /client/hubs/:hubId/managers`
- `GET /client/team-members`
- `GET /client/orders/view`
- `GET /client/orders/:orderId/reorder-preview`
- `GET /client/reports/summary`
- `GET /client/reports/daily-ops`
- `GET /client/reports/spend`
- `GET /client/reports/coverage`
- `GET /client/reports/forecast`
- `GET /client/reports/performance`
- `GET /client/reports/no-show`
These are served by `query-api-v2` but frontend should still call them through the unified host:
### Client writes
- `/query/client/*`
- `/query/staff/*`
- `POST /client/orders/one-time`
- `POST /client/orders/recurring`
- `POST /client/orders/permanent`
- `POST /client/orders/:orderId/edit`
- `POST /client/orders/:orderId/cancel`
- `POST /client/hubs`
- `PUT /client/hubs/:hubId`
- `DELETE /client/hubs/:hubId`
- `POST /client/hubs/:hubId/assign-nfc`
- `POST /client/hubs/:hubId/managers`
- `POST /client/billing/invoices/:invoiceId/approve`
- `POST /client/billing/invoices/:invoiceId/dispute`
- `POST /client/coverage/reviews`
- `POST /client/coverage/late-workers/:assignmentId/cancel`
## Why this shape
## 3) Staff routes
- frontend gets one base URL
- backend keeps separate read, write, and service helpers
- we can scale or refactor internals later without breaking frontend paths
### Staff reads
## Current auth note
- `GET /staff/session`
- `GET /staff/dashboard`
- `GET /staff/profile-completion`
- `GET /staff/availability`
- `GET /staff/clock-in/shifts/today`
- `GET /staff/clock-in/status`
- `GET /staff/payments/summary`
- `GET /staff/payments/history`
- `GET /staff/payments/chart`
- `GET /staff/shifts/assigned`
- `GET /staff/shifts/open`
- `GET /staff/shifts/pending`
- `GET /staff/shifts/cancelled`
- `GET /staff/shifts/completed`
- `GET /staff/shifts/:shiftId`
- `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/time-card`
- `GET /staff/profile/privacy`
- `GET /staff/faqs`
- `GET /staff/faqs/search`
Client email/password auth is wrapped here.
### Staff writes
Staff phone OTP is not wrapped here yet. That still needs its own proper provider-backed implementation rather than a fake backend OTP flow.
- `POST /staff/profile/setup`
- `POST /staff/clock-in`
- `POST /staff/clock-out`
- `PUT /staff/availability`
- `POST /staff/availability/quick-set`
- `POST /staff/shifts/:shiftId/apply`
- `POST /staff/shifts/:shiftId/accept`
- `POST /staff/shifts/:shiftId/decline`
- `POST /staff/shifts/:shiftId/request-swap`
- `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`
## 4) Upload and verification routes
These are exposed as direct unified aliases even though they are backed by `core-api-v2`.
### Generic core aliases
- `POST /upload-file`
- `POST /create-signed-url`
- `POST /invoke-llm`
- `POST /rapid-orders/transcribe`
- `POST /rapid-orders/parse`
- `POST /verifications`
- `GET /verifications/:verificationId`
- `POST /verifications/:verificationId/review`
- `POST /verifications/:verificationId/retry`
### Staff upload aliases
- `POST /staff/profile/photo`
- `POST /staff/profile/documents/:documentId/upload`
- `POST /staff/profile/attire/:documentId/upload`
- `POST /staff/profile/certificates`
- `DELETE /staff/profile/certificates/:certificateId`
## 5) Notes that matter for frontend
- `roleId` on `POST /staff/shifts/:shiftId/apply` is the concrete `shift_roles.id` for that shift, not the catalog role definition id.
- `accountType` on `POST /staff/profile/bank-accounts` accepts either lowercase or uppercase and is normalized by the backend.
- File upload routes return a storage path plus a signed URL. Frontend uploads the file directly to storage using that URL.
- Verification routes are durable in the v2 backend and were validated live through document, attire, and certificate upload flows.
## 6) Why this shape
- frontend gets one host
- backend keeps reads, writes, and service helpers separated
- routing can change internally later without forcing frontend rewrites