docs(api): consolidate v2 frontend backend guides
This commit is contained in:
@@ -1,233 +1,10 @@
|
||||
# M4 API Catalog (Core Only)
|
||||
# Moved
|
||||
|
||||
Status: Active
|
||||
Date: 2026-03-11
|
||||
Owner: Technical Lead
|
||||
Environment: dev
|
||||
The canonical v2 backend API docs now live here:
|
||||
|
||||
## Frontend source of truth
|
||||
Use this file and `docs/MILESTONES/M4/planning/m4-core-api-frontend-guide.md` for core endpoint consumption.
|
||||
Use `docs/MILESTONES/M4/planning/m4-v2-frontend-migration-guide.md` for actual frontend migration sequencing across v2 services.
|
||||
- `docs/BACKEND/API_GUIDES/V2/README.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/core-api.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/command-api.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/query-api.md`
|
||||
|
||||
## Related next-slice contract
|
||||
Verification pipeline design (attire, government ID, certification):
|
||||
- `docs/MILESTONES/M4/planning/m4-verification-architecture-contract.md`
|
||||
|
||||
## 1) Scope and purpose
|
||||
This catalog defines the currently implemented core backend contract for M4.
|
||||
|
||||
## 2) Global API rules
|
||||
1. Route group in scope: `/core/*`.
|
||||
2. Compatibility aliases in scope:
|
||||
- `POST /uploadFile` -> `POST /core/upload-file`
|
||||
- `POST /createSignedUrl` -> `POST /core/create-signed-url`
|
||||
- `POST /invokeLLM` -> `POST /core/invoke-llm`
|
||||
3. Auth model:
|
||||
- `GET /health` is public in dev
|
||||
- all other routes require `Authorization: Bearer <firebase-id-token>`
|
||||
4. Standard error envelope:
|
||||
```json
|
||||
{
|
||||
"code": "STRING_CODE",
|
||||
"message": "Human readable message",
|
||||
"details": {},
|
||||
"requestId": "optional-request-id"
|
||||
}
|
||||
```
|
||||
5. Response header:
|
||||
- `X-Request-Id`
|
||||
|
||||
## 3) Core routes
|
||||
|
||||
## 3.1 Upload file
|
||||
1. Method and route: `POST /core/upload-file`
|
||||
2. Request format: `multipart/form-data`
|
||||
3. Fields:
|
||||
- `file` (required)
|
||||
- `visibility` (`public` or `private`, optional)
|
||||
- `category` (optional)
|
||||
4. Accepted types:
|
||||
- `application/pdf`
|
||||
- `image/jpeg`
|
||||
- `image/jpg`
|
||||
- `image/png`
|
||||
5. Max size: `10 MB` (default)
|
||||
6. Behavior: real upload to Cloud Storage.
|
||||
7. Success `200`:
|
||||
```json
|
||||
{
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/...",
|
||||
"contentType": "application/pdf",
|
||||
"size": 12345,
|
||||
"bucket": "krow-workforce-dev-private",
|
||||
"path": "uploads/<uid>/...",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
8. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `INVALID_FILE_TYPE`
|
||||
- `FILE_TOO_LARGE`
|
||||
|
||||
## 3.2 Create signed URL
|
||||
1. Method and route: `POST /core/create-signed-url`
|
||||
2. Request:
|
||||
```json
|
||||
{
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/file.pdf",
|
||||
"expiresInSeconds": 300
|
||||
}
|
||||
```
|
||||
3. Security checks:
|
||||
- bucket must be allowed
|
||||
- path must be owned by caller (`uploads/<caller_uid>/...`)
|
||||
- object must exist
|
||||
- `expiresInSeconds <= 900`
|
||||
4. Success `200`:
|
||||
```json
|
||||
{
|
||||
"signedUrl": "https://storage.googleapis.com/...",
|
||||
"expiresAt": "2026-02-24T15:22:28.105Z",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
5. Errors:
|
||||
- `VALIDATION_ERROR`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
|
||||
## 3.3 Invoke model
|
||||
1. Method and route: `POST /core/invoke-llm`
|
||||
2. Request:
|
||||
```json
|
||||
{
|
||||
"prompt": "...",
|
||||
"responseJsonSchema": {},
|
||||
"fileUrls": []
|
||||
}
|
||||
```
|
||||
3. Behavior:
|
||||
- real Vertex AI call
|
||||
- model default: `gemini-2.0-flash-001`
|
||||
- timeout default: `20 seconds`
|
||||
4. Rate limit:
|
||||
- `20 requests/minute` per user (default)
|
||||
- when exceeded: `429 RATE_LIMITED` and `Retry-After` header
|
||||
5. Success `200`:
|
||||
```json
|
||||
{
|
||||
"result": {},
|
||||
"model": "gemini-2.0-flash-001",
|
||||
"latencyMs": 367,
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
6. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `VALIDATION_ERROR`
|
||||
- `MODEL_TIMEOUT`
|
||||
- `MODEL_FAILED`
|
||||
- `RATE_LIMITED`
|
||||
|
||||
## 3.4 Create verification job
|
||||
1. Method and route: `POST /core/verifications`
|
||||
2. Auth: required
|
||||
3. Request:
|
||||
```json
|
||||
{
|
||||
"type": "attire",
|
||||
"subjectType": "worker",
|
||||
"subjectId": "worker_123",
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/file.pdf",
|
||||
"rules": {}
|
||||
}
|
||||
```
|
||||
4. Behavior:
|
||||
- validates `fileUri` ownership
|
||||
- requires file existence when `UPLOAD_MOCK=false` and `VERIFICATION_REQUIRE_FILE_EXISTS=true`
|
||||
- enqueues async verification
|
||||
5. Success `202`:
|
||||
```json
|
||||
{
|
||||
"verificationId": "ver_123",
|
||||
"status": "PENDING",
|
||||
"type": "attire",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
6. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `VALIDATION_ERROR`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
|
||||
## 3.5 Get verification status
|
||||
1. Method and route: `GET /core/verifications/{verificationId}`
|
||||
2. Auth: required
|
||||
3. Success `200`:
|
||||
```json
|
||||
{
|
||||
"verificationId": "ver_123",
|
||||
"status": "NEEDS_REVIEW",
|
||||
"type": "attire",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
4. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
|
||||
## 3.6 Review verification
|
||||
1. Method and route: `POST /core/verifications/{verificationId}/review`
|
||||
2. Auth: required
|
||||
3. Request:
|
||||
```json
|
||||
{
|
||||
"decision": "APPROVED",
|
||||
"note": "Manual review passed",
|
||||
"reasonCode": "MANUAL_REVIEW"
|
||||
}
|
||||
```
|
||||
4. Success `200`: status becomes `APPROVED` or `REJECTED`.
|
||||
5. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `VALIDATION_ERROR`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
|
||||
## 3.7 Retry verification
|
||||
1. Method and route: `POST /core/verifications/{verificationId}/retry`
|
||||
2. Auth: required
|
||||
3. Success `202`: status resets to `PENDING`.
|
||||
4. Errors:
|
||||
- `UNAUTHENTICATED`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
|
||||
## 3.8 Health
|
||||
1. Method and route: `GET /health`
|
||||
2. Success `200`:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"service": "krow-core-api",
|
||||
"version": "dev",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4) Locked defaults
|
||||
1. Validation library: `zod`.
|
||||
2. Validation schema location: `backend/core-api/src/contracts/`.
|
||||
3. Buckets:
|
||||
- `krow-workforce-dev-public`
|
||||
- `krow-workforce-dev-private`
|
||||
4. Model provider: Vertex AI Gemini.
|
||||
5. Max signed URL expiry: `900` seconds.
|
||||
6. LLM timeout: `20000` ms.
|
||||
7. LLM rate limit: `20` requests/minute/user.
|
||||
8. Verification access mode default: `authenticated`.
|
||||
9. Verification file existence check default: enabled (`VERIFICATION_REQUIRE_FILE_EXISTS=true`).
|
||||
10. Verification attire provider default in dev: `vertex` with model `gemini-2.0-flash-lite-001`.
|
||||
11. Verification government/certification providers: external adapters via configured provider URL/token.
|
||||
This file is kept only as a compatibility pointer.
|
||||
|
||||
@@ -1,384 +1,9 @@
|
||||
# M4 Core API Frontend Guide (Dev)
|
||||
# Moved
|
||||
|
||||
Status: Active
|
||||
Last updated: 2026-03-11
|
||||
Audience: Web and mobile frontend developers
|
||||
The canonical Core API frontend doc now lives here:
|
||||
|
||||
Related guide:
|
||||
1. `docs/MILESTONES/M4/planning/m4-v2-frontend-migration-guide.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/core-api.md`
|
||||
|
||||
Scope note:
|
||||
1. This file documents the core API contract only.
|
||||
2. For service readiness and migration sequencing across `core-api-v2`, `command-api-v2`, and `query-api-v2`, use the v2 frontend migration guide above.
|
||||
Start from:
|
||||
|
||||
## 1) Base URLs (dev)
|
||||
1. Core API v2: `https://krow-core-api-v2-e3g6witsvq-uc.a.run.app`
|
||||
2. Legacy core API: `https://krow-core-api-e3g6witsvq-uc.a.run.app`
|
||||
3. For new frontend integration on this branch, use the v2 URL.
|
||||
|
||||
## 2) Auth requirements
|
||||
1. Send Firebase ID token on protected routes:
|
||||
```http
|
||||
Authorization: Bearer <firebase-id-token>
|
||||
```
|
||||
2. Health route is public:
|
||||
- `GET /health`
|
||||
3. All other routes require Firebase token.
|
||||
|
||||
## 3) Standard error envelope
|
||||
```json
|
||||
{
|
||||
"code": "STRING_CODE",
|
||||
"message": "Human readable message",
|
||||
"details": {},
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4) Core API endpoints
|
||||
|
||||
## 4.1 Upload file
|
||||
1. Route: `POST /core/upload-file`
|
||||
2. Alias: `POST /uploadFile`
|
||||
3. Content type: `multipart/form-data`
|
||||
4. Form fields:
|
||||
- `file` (required)
|
||||
- `visibility` (optional: `public` or `private`, default `private`)
|
||||
- `category` (optional)
|
||||
5. Accepted file types:
|
||||
- `application/pdf`
|
||||
- `image/jpeg`
|
||||
- `image/jpg`
|
||||
- `image/png`
|
||||
- `audio/webm`
|
||||
- `audio/wav`
|
||||
- `audio/x-wav`
|
||||
- `audio/mpeg`
|
||||
- `audio/mp3`
|
||||
- `audio/mp4`
|
||||
- `audio/m4a`
|
||||
- `audio/aac`
|
||||
- `audio/ogg`
|
||||
- `audio/flac`
|
||||
6. Max upload size: `10 MB` (default)
|
||||
7. Current behavior: real upload to Cloud Storage (not mock)
|
||||
8. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/173...",
|
||||
"contentType": "application/pdf",
|
||||
"size": 12345,
|
||||
"bucket": "krow-workforce-dev-private",
|
||||
"path": "uploads/<uid>/173..._file.pdf",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4.2 Create signed URL
|
||||
1. Route: `POST /core/create-signed-url`
|
||||
2. Alias: `POST /createSignedUrl`
|
||||
3. Request body:
|
||||
```json
|
||||
{
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/file.pdf",
|
||||
"expiresInSeconds": 300
|
||||
}
|
||||
```
|
||||
4. Security checks:
|
||||
- bucket must be allowed (`krow-workforce-dev-public` or `krow-workforce-dev-private`)
|
||||
- path must be owned by caller (`uploads/<caller_uid>/...`)
|
||||
- object must exist
|
||||
- `expiresInSeconds` must be `<= 900`
|
||||
5. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"signedUrl": "https://storage.googleapis.com/...",
|
||||
"expiresAt": "2026-02-24T15:22:28.105Z",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
6. Typical errors:
|
||||
- `400 VALIDATION_ERROR` (bad payload or expiry too high)
|
||||
- `403 FORBIDDEN` (path not owned by caller)
|
||||
- `404 NOT_FOUND` (object does not exist)
|
||||
|
||||
## 4.3 Invoke model
|
||||
1. Route: `POST /core/invoke-llm`
|
||||
2. Alias: `POST /invokeLLM`
|
||||
3. Request body:
|
||||
```json
|
||||
{
|
||||
"prompt": "Return JSON with keys summary and risk.",
|
||||
"responseJsonSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"summary": { "type": "string" },
|
||||
"risk": { "type": "string" }
|
||||
},
|
||||
"required": ["summary", "risk"]
|
||||
},
|
||||
"fileUrls": []
|
||||
}
|
||||
```
|
||||
4. Current behavior: real Vertex model call (not mock)
|
||||
- model: `gemini-2.0-flash-001`
|
||||
- timeout: `20 seconds`
|
||||
5. Rate limit:
|
||||
- per-user `20 requests/minute` (default)
|
||||
- on limit: `429 RATE_LIMITED`
|
||||
- includes `Retry-After` header
|
||||
6. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"result": { "summary": "text", "risk": "Low" },
|
||||
"model": "gemini-2.0-flash-001",
|
||||
"latencyMs": 367,
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4.4 Rapid order transcribe (audio to text)
|
||||
1. Route: `POST /core/rapid-orders/transcribe`
|
||||
2. Auth: required
|
||||
3. Purpose: transcribe uploaded RAPID voice note into text for the RAPID input box.
|
||||
4. Request body:
|
||||
```json
|
||||
{
|
||||
"audioFileUri": "gs://krow-workforce-dev-private/uploads/<uid>/rapid-request.webm",
|
||||
"locale": "en-US",
|
||||
"promptHints": ["server", "urgent"]
|
||||
}
|
||||
```
|
||||
5. Security checks:
|
||||
- `audioFileUri` must be in allowed bucket
|
||||
- `audioFileUri` path must be owned by caller (`uploads/<caller_uid>/...`)
|
||||
- file existence is required in non-mock upload mode
|
||||
6. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"transcript": "Need 2 servers ASAP for 4 hours.",
|
||||
"confidence": 0.87,
|
||||
"language": "en-US",
|
||||
"warnings": [],
|
||||
"model": "gemini-2.0-flash-001",
|
||||
"latencyMs": 412,
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
7. Typical errors:
|
||||
- `400 VALIDATION_ERROR` (invalid payload)
|
||||
- `401 UNAUTHENTICATED` (missing/invalid bearer token)
|
||||
- `403 FORBIDDEN` (audio path not owned by caller)
|
||||
- `429 RATE_LIMITED` (model quota per user)
|
||||
- `502 MODEL_FAILED` (upstream model output/availability)
|
||||
|
||||
## 4.5 Rapid order parse (text to structured draft)
|
||||
1. Route: `POST /core/rapid-orders/parse`
|
||||
2. Auth: required
|
||||
3. Purpose: convert RAPID text into structured one-time order draft JSON for form prefill.
|
||||
4. Request body:
|
||||
```json
|
||||
{
|
||||
"text": "Need 2 servers ASAP for 4 hours",
|
||||
"locale": "en-US",
|
||||
"timezone": "America/New_York",
|
||||
"now": "2026-02-27T12:00:00.000Z"
|
||||
}
|
||||
```
|
||||
5. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"parsed": {
|
||||
"orderType": "ONE_TIME",
|
||||
"isRapid": true,
|
||||
"positions": [
|
||||
{ "role": "server", "count": 2 }
|
||||
],
|
||||
"startAt": "2026-02-27T12:00:00.000Z",
|
||||
"endAt": null,
|
||||
"durationMinutes": 240,
|
||||
"locationHint": null,
|
||||
"notes": null,
|
||||
"sourceText": "Need 2 servers ASAP for 4 hours"
|
||||
},
|
||||
"missingFields": [],
|
||||
"warnings": [],
|
||||
"confidence": {
|
||||
"overall": 0.72,
|
||||
"fields": {
|
||||
"positions": 0.86,
|
||||
"startAt": 0.9,
|
||||
"durationMinutes": 0.88
|
||||
}
|
||||
},
|
||||
"model": "gemini-2.0-flash-001",
|
||||
"latencyMs": 531,
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
6. Contract notes:
|
||||
- unknown request keys are rejected (`400 VALIDATION_ERROR`)
|
||||
- when information is missing/ambiguous, backend returns `missingFields` and `warnings`
|
||||
- frontend should use output to prefill one-time order and request user confirmation where needed
|
||||
|
||||
## 4.6 Create verification job
|
||||
1. Route: `POST /core/verifications`
|
||||
2. Auth: required
|
||||
3. Purpose: enqueue an async verification job for an uploaded file.
|
||||
4. Request body:
|
||||
```json
|
||||
{
|
||||
"type": "attire",
|
||||
"subjectType": "worker",
|
||||
"subjectId": "<worker-id>",
|
||||
"fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/file.pdf",
|
||||
"rules": {
|
||||
"dressCode": "black shoes"
|
||||
}
|
||||
}
|
||||
```
|
||||
5. Success `202` example:
|
||||
```json
|
||||
{
|
||||
"verificationId": "ver_123",
|
||||
"status": "PENDING",
|
||||
"type": "attire",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
6. Current machine processing behavior in dev:
|
||||
- `attire`: live vision check using Vertex Gemini Flash Lite model.
|
||||
- `government_id`: third-party adapter path (falls back to `NEEDS_REVIEW` if provider is not configured).
|
||||
- `certification`: third-party adapter path (falls back to `NEEDS_REVIEW` if provider is not configured).
|
||||
|
||||
## 4.7 Get verification status
|
||||
1. Route: `GET /core/verifications/{verificationId}`
|
||||
2. Auth: required
|
||||
3. Purpose: polling status from frontend.
|
||||
4. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"verificationId": "ver_123",
|
||||
"status": "NEEDS_REVIEW",
|
||||
"type": "attire",
|
||||
"review": null,
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4.8 Review verification
|
||||
1. Route: `POST /core/verifications/{verificationId}/review`
|
||||
2. Auth: required
|
||||
3. Purpose: final human decision for the verification.
|
||||
4. Request body:
|
||||
```json
|
||||
{
|
||||
"decision": "APPROVED",
|
||||
"note": "Manual review passed",
|
||||
"reasonCode": "MANUAL_REVIEW"
|
||||
}
|
||||
```
|
||||
5. Success `200` example:
|
||||
```json
|
||||
{
|
||||
"verificationId": "ver_123",
|
||||
"status": "APPROVED",
|
||||
"review": {
|
||||
"decision": "APPROVED",
|
||||
"reviewedBy": "<uid>"
|
||||
},
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## 4.9 Retry verification
|
||||
1. Route: `POST /core/verifications/{verificationId}/retry`
|
||||
2. Auth: required
|
||||
3. Purpose: requeue verification to run again.
|
||||
4. Success `202` example: status resets to `PENDING`.
|
||||
|
||||
## 5) Frontend fetch examples (web)
|
||||
|
||||
## 5.1 Signed URL request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/create-signed-url', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileUri: 'gs://krow-workforce-dev-private/uploads/<uid>/file.pdf',
|
||||
expiresInSeconds: 300,
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
```
|
||||
|
||||
## 5.2 Model request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/invoke-llm', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
prompt: 'Return JSON with status.',
|
||||
responseJsonSchema: {
|
||||
type: 'object',
|
||||
properties: { status: { type: 'string' } },
|
||||
required: ['status'],
|
||||
},
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
```
|
||||
|
||||
## 5.3 Rapid audio transcribe request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/rapid-orders/transcribe', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
audioFileUri: 'gs://krow-workforce-dev-private/uploads/<uid>/rapid-request.webm',
|
||||
locale: 'en-US',
|
||||
promptHints: ['server', 'urgent'],
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
```
|
||||
|
||||
## 5.4 Rapid text parse request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/rapid-orders/parse', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: 'Need 2 servers ASAP for 4 hours',
|
||||
locale: 'en-US',
|
||||
timezone: 'America/New_York',
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
```
|
||||
|
||||
## 6) Notes for frontend team
|
||||
1. Use canonical `/core/*` routes for new work.
|
||||
2. Aliases exist only for migration compatibility.
|
||||
3. `requestId` in responses should be logged client-side for debugging.
|
||||
4. For 429 on model route, retry with exponential backoff and respect `Retry-After`.
|
||||
5. Verification routes are now available in dev under `/core/verifications*`.
|
||||
6. Current verification processing is async and returns machine statuses first (`PENDING`, `PROCESSING`, `NEEDS_REVIEW`, etc.).
|
||||
7. Full verification design and policy details:
|
||||
`docs/MILESTONES/M4/planning/m4-verification-architecture-contract.md`.
|
||||
- `docs/BACKEND/API_GUIDES/V2/README.md`
|
||||
|
||||
@@ -1,303 +1,10 @@
|
||||
# M4 V2 Frontend Migration Guide
|
||||
# Moved
|
||||
|
||||
Status: Active
|
||||
Last updated: 2026-03-11
|
||||
Audience: Web and mobile frontend developers
|
||||
The canonical frontend-facing v2 backend docs now live here:
|
||||
|
||||
## 1) Purpose
|
||||
This document tells frontend exactly how to migrate toward the v2 backend services on this branch.
|
||||
- `docs/BACKEND/API_GUIDES/V2/README.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/core-api.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/command-api.md`
|
||||
- `docs/BACKEND/API_GUIDES/V2/query-api.md`
|
||||
|
||||
It is intentionally strict about readiness:
|
||||
1. `core-api-v2` is ready for frontend integration now for uploads, signed URLs, model calls, and verification workflows.
|
||||
2. `command-api-v2` now has a first real write slice backed by the v2 SQL schema and verified through live smoke tests.
|
||||
3. `query-api-v2` now has a first real read slice backed by the v2 SQL schema and verified through live smoke tests.
|
||||
|
||||
Frontend should not assume all three services are ready just because they are deployed.
|
||||
|
||||
## 2) Live dev service URLs
|
||||
1. Core API v2: `https://krow-core-api-v2-e3g6witsvq-uc.a.run.app`
|
||||
2. Command API v2: `https://krow-command-api-v2-e3g6witsvq-uc.a.run.app`
|
||||
3. Query API v2: `https://krow-query-api-v2-e3g6witsvq-uc.a.run.app`
|
||||
|
||||
## 3) Readiness summary
|
||||
|
||||
| Service | Status | Frontend guidance |
|
||||
| --- | --- | --- |
|
||||
| `core-api-v2` | Ready now with persistence caveat | Use for file upload, signed URLs, model calls, rapid order helpers, and verification flows |
|
||||
| `command-api-v2` | First production slice | Use for documented v2 write flows only |
|
||||
| `query-api-v2` | First production slice | Use for documented v2 read flows only |
|
||||
|
||||
## 4) Non-negotiable migration rules
|
||||
1. Do not point undocumented read screens to `query-api-v2` yet.
|
||||
2. Do not replace undocumented order, shift, or staffing mutations with `command-api-v2` yet.
|
||||
3. Do move all new service-style frontend work to `core-api-v2`.
|
||||
4. Do use command/query v2 for the routes listed in this document when building the new v2 clients.
|
||||
5. Any new frontend abstraction should separate:
|
||||
- `core service client`
|
||||
- `command service client`
|
||||
- `query service client`
|
||||
- `legacy Data Connect access`
|
||||
6. Build the frontend with switchable adapters so the command/query cutover is a client config change, not a rewrite.
|
||||
|
||||
## 5) Auth and headers
|
||||
All protected v2 routes currently require Firebase ID token:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <firebase-id-token>
|
||||
```
|
||||
|
||||
All services return:
|
||||
1. `X-Request-Id` response header
|
||||
2. Standard error envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "STRING_CODE",
|
||||
"message": "Human readable message",
|
||||
"details": {},
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
Additional rule for command routes:
|
||||
|
||||
```http
|
||||
Idempotency-Key: <unique-per-user-action>
|
||||
```
|
||||
|
||||
## 6) What frontend can migrate now
|
||||
|
||||
### 6.1 Move to `core-api-v2` now
|
||||
1. File uploads
|
||||
2. Signed download URL generation
|
||||
3. Rapid order voice transcription
|
||||
4. Rapid order structured parsing
|
||||
5. Generic model invocation
|
||||
6. Verification job creation
|
||||
7. Verification status polling
|
||||
8. Manual verification review and retry
|
||||
|
||||
### 6.2 Keep on existing stack for now
|
||||
1. Business reads
|
||||
2. Staff reads
|
||||
3. Shift lists and details outside the documented order detail shape
|
||||
4. Applications lists and details not yet served by query v2
|
||||
5. Payments and reporting reads
|
||||
|
||||
### 6.3 Move to command/query v2 now for the new v2 clients
|
||||
1. Order creation
|
||||
2. Order update
|
||||
3. Order cancel
|
||||
4. Shift assign staff
|
||||
5. Shift accept
|
||||
6. Shift status change
|
||||
7. Attendance clock-in and clock-out
|
||||
8. Favorite staff add and remove
|
||||
9. Staff review create
|
||||
10. Order list
|
||||
11. Order detail
|
||||
12. Favorite staff list
|
||||
13. Staff review summary
|
||||
14. Assignment attendance detail
|
||||
|
||||
## 7) Core API v2 routes frontend can use today
|
||||
Use this service for backend capabilities that should not run directly from the client.
|
||||
|
||||
Important caveat:
|
||||
1. File storage is real and backed by Google Cloud Storage.
|
||||
2. Verification job state is not yet persisted to the v2 SQL schema.
|
||||
3. Frontend can integrate with these routes now, but do not treat verification history as mission-critical durable state yet.
|
||||
|
||||
Base URL:
|
||||
|
||||
```text
|
||||
https://krow-core-api-v2-e3g6witsvq-uc.a.run.app
|
||||
```
|
||||
|
||||
Routes:
|
||||
1. `POST /core/upload-file`
|
||||
2. `POST /core/create-signed-url`
|
||||
3. `POST /core/invoke-llm`
|
||||
4. `POST /core/rapid-orders/transcribe`
|
||||
5. `POST /core/rapid-orders/parse`
|
||||
6. `POST /core/verifications`
|
||||
7. `GET /core/verifications/:verificationId`
|
||||
8. `POST /core/verifications/:verificationId/review`
|
||||
9. `POST /core/verifications/:verificationId/retry`
|
||||
10. `GET /health`
|
||||
|
||||
For request and response examples, use:
|
||||
1. `docs/MILESTONES/M4/planning/m4-core-api-frontend-guide.md`
|
||||
2. `docs/MILESTONES/M4/planning/m4-api-catalog.md`
|
||||
|
||||
## 8) Command API v2 routes ready for the first migration slice
|
||||
These routes are deployed and backed by the v2 SQL schema. They enforce auth, policy gate, and idempotency.
|
||||
|
||||
Base URL:
|
||||
|
||||
```text
|
||||
https://krow-command-api-v2-e3g6witsvq-uc.a.run.app
|
||||
```
|
||||
|
||||
Routes:
|
||||
1. `POST /commands/orders/create`
|
||||
2. `POST /commands/orders/:orderId/update`
|
||||
3. `POST /commands/orders/:orderId/cancel`
|
||||
4. `POST /commands/shifts/:shiftId/change-status`
|
||||
5. `POST /commands/shifts/:shiftId/assign-staff`
|
||||
6. `POST /commands/shifts/:shiftId/accept`
|
||||
7. `POST /commands/attendance/clock-in`
|
||||
8. `POST /commands/attendance/clock-out`
|
||||
9. `POST /commands/businesses/:businessId/favorite-staff`
|
||||
10. `DELETE /commands/businesses/:businessId/favorite-staff/:staffId`
|
||||
11. `POST /commands/assignments/:assignmentId/reviews`
|
||||
12. `GET /health`
|
||||
13. `GET /readyz`
|
||||
|
||||
Implemented now:
|
||||
1. `POST /commands/orders/create`
|
||||
2. `POST /commands/orders/:orderId/update`
|
||||
3. `POST /commands/orders/:orderId/cancel`
|
||||
4. `POST /commands/shifts/:shiftId/change-status`
|
||||
5. `POST /commands/shifts/:shiftId/assign-staff`
|
||||
6. `POST /commands/shifts/:shiftId/accept`
|
||||
7. `POST /commands/attendance/clock-in`
|
||||
8. `POST /commands/attendance/clock-out`
|
||||
9. `POST /commands/businesses/:businessId/favorite-staff`
|
||||
10. `DELETE /commands/businesses/:businessId/favorite-staff/:staffId`
|
||||
11. `POST /commands/assignments/:assignmentId/reviews`
|
||||
|
||||
Live verification completed on 2026-03-11:
|
||||
1. order create
|
||||
2. order update
|
||||
3. order cancel
|
||||
4. shift assign staff
|
||||
5. shift accept
|
||||
6. shift status change
|
||||
7. attendance clock-in
|
||||
8. attendance clock-out
|
||||
9. favorite add
|
||||
10. favorite list
|
||||
11. review create
|
||||
12. review summary
|
||||
13. order list/detail
|
||||
14. attendance detail
|
||||
|
||||
Order creation request contract:
|
||||
|
||||
```json
|
||||
{
|
||||
"tenantId": "uuid",
|
||||
"businessId": "uuid",
|
||||
"vendorId": "uuid",
|
||||
"orderNumber": "ORD-1001",
|
||||
"title": "Cafe Event Staffing",
|
||||
"serviceType": "EVENT",
|
||||
"shifts": [
|
||||
{
|
||||
"shiftCode": "SHIFT-1",
|
||||
"title": "Morning Shift",
|
||||
"startsAt": "2026-03-11T08:00:00.000Z",
|
||||
"endsAt": "2026-03-11T16:00:00.000Z",
|
||||
"requiredWorkers": 2,
|
||||
"roles": [
|
||||
{
|
||||
"roleCode": "BARISTA",
|
||||
"roleName": "Barista",
|
||||
"workersNeeded": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Order creation success response:
|
||||
|
||||
```json
|
||||
{
|
||||
"orderId": "uuid",
|
||||
"orderNumber": "ORD-1001",
|
||||
"status": "OPEN",
|
||||
"shiftCount": 1,
|
||||
"shiftIds": ["uuid"],
|
||||
"idempotencyKey": "abc-123",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
Important:
|
||||
1. This is the first real write slice, not the full command surface.
|
||||
2. Frontend should migrate only the documented routes.
|
||||
3. Reuse one idempotency key per user action and never retry with a new key unless the UI is creating a brand new action.
|
||||
4. The old `501` placeholders for order update, order cancel, shift status change, and shift assign staff are now implemented.
|
||||
|
||||
## 9) Query API v2 routes ready for the first migration slice
|
||||
Base URL:
|
||||
|
||||
```text
|
||||
https://krow-query-api-v2-e3g6witsvq-uc.a.run.app
|
||||
```
|
||||
|
||||
Current routes:
|
||||
1. `GET /health`
|
||||
2. `GET /healthz`
|
||||
3. `GET /readyz`
|
||||
4. `GET /query/tenants/:tenantId/orders`
|
||||
5. `GET /query/tenants/:tenantId/orders/:orderId`
|
||||
6. `GET /query/tenants/:tenantId/businesses/:businessId/favorite-staff`
|
||||
7. `GET /query/tenants/:tenantId/staff/:staffId/review-summary`
|
||||
8. `GET /query/tenants/:tenantId/assignments/:assignmentId/attendance`
|
||||
|
||||
Frontend can point the new v2 clients to these routes now. Frontend should not point any undocumented screen, list, detail page, dashboard, or reporting view to `query-api-v2` yet.
|
||||
|
||||
## 10) Recommended frontend adapter shape
|
||||
Frontend should isolate backend calls behind service adapters instead of calling routes inline in screens.
|
||||
|
||||
Suggested split:
|
||||
1. `coreApiClient`
|
||||
2. `commandApiClient`
|
||||
3. `queryApiClient`
|
||||
4. `legacyDataConnectClient`
|
||||
|
||||
Suggested cutover plan:
|
||||
1. Move service-style operations to `coreApiClient` first.
|
||||
2. Add `commandApiClient` now as the write path for the documented v2 write routes.
|
||||
3. Add `queryApiClient` now as the read path for the documented v2 read routes.
|
||||
4. Keep everything else on `legacyDataConnectClient` until the replacement route exists.
|
||||
5. Expand migration route-by-route instead of big-bang switching whole apps.
|
||||
|
||||
## 11) Frontend implementation checklist
|
||||
1. Add three environment variables:
|
||||
- `CORE_API_V2_BASE_URL`
|
||||
- `COMMAND_API_V2_BASE_URL`
|
||||
- `QUERY_API_V2_BASE_URL`
|
||||
2. Add shared auth header injection using Firebase ID token.
|
||||
3. Add shared response envelope parsing.
|
||||
4. Add request ID logging in frontend network layer.
|
||||
5. Add `Idempotency-Key` generation utility for command calls.
|
||||
6. Build command/query clients behind feature flags or adapter switches.
|
||||
7. Start integration with `core-api-v2`, `command-api-v2`, and `query-api-v2` for the documented routes only.
|
||||
|
||||
## 12) Frontend do and do not
|
||||
Do:
|
||||
1. Treat `core-api-v2` as the real backend entrypoint for uploads, model work, and verification.
|
||||
2. Treat documented command/query v2 routes as the real backend entrypoint for the first v2 domain slice.
|
||||
3. Build migration-safe abstractions now.
|
||||
4. Keep old reads and writes isolated so they can be swapped cleanly later.
|
||||
|
||||
Do not:
|
||||
1. Hardcode v2 command success as if business action is complete.
|
||||
2. Point undocumented dashboards or reports to query v2 yet.
|
||||
3. Remove current Data Connect code until the replacement route actually exists and is verified.
|
||||
|
||||
## 13) Practical migration sequence
|
||||
1. Replace existing upload helpers with `core-api-v2`.
|
||||
2. Replace signed URL generation with `core-api-v2`.
|
||||
3. Point rapid order helpers to `core-api-v2`.
|
||||
4. Point attire and document verification flows to `core-api-v2`.
|
||||
5. Introduce command client wrapper with idempotency header support.
|
||||
6. Point new v2 order creation, shift accept, attendance, favorites, and reviews flows to `command-api-v2`.
|
||||
7. Point new v2 order list/detail, favorites, review summary, and attendance detail screens to `query-api-v2`.
|
||||
8. Point new v2 order update, order cancel, shift assign, and shift status flows to `command-api-v2`.
|
||||
9. Keep payments, reports, and remaining scheduling mutations on the legacy stack until the replacement routes exist.
|
||||
This file is kept only as a compatibility pointer.
|
||||
|
||||
Reference in New Issue
Block a user