6.4 KiB
6.4 KiB
M4 API Catalog (Implementation Contract)
Status: Active (Planning + Route Inventory)
Date: 2026-02-24
Owner: Technical Lead
Environment: dev
Frontend source of truth
For frontend implementation, use:
docs/MILESTONES/M4/planning/m4-core-api-frontend-guide.md
Reason:
- this catalog is the broader M4 planning contract
- the frontend guide is the exact deployed request/response contract
1) Scope and purpose
This file defines the backend endpoint contract for the M4 foundation build.
2) Global API rules
- Canonical route groups:
/core/*for foundational integration routes/commands/*for business-critical writes
- Foundation phase security model:
- authenticated user required
- role map enforcement deferred
- policy hook required in handler design
- Standard error envelope:
{
"code": "STRING_CODE",
"message": "Human readable message",
"details": {},
"requestId": "optional-request-id"
}
- Required request headers:
Authorization: Bearer <firebase-token>X-Request-Id: <uuid>(optional but recommended)
- Required response headers:
X-Request-Id
- Validation:
- all input validated server-side
- reject unknown/invalid fields
- Logging:
- route
- requestId
- actorId
- latencyMs
- outcome
- Timeouts and retries:
- command writes must be retry-safe
- use idempotency keys for command write routes
- Idempotency storage:
- store in Cloud SQL table
- key scope:
userId + route + idempotencyKey - key retention: 24 hours
- repeated key returns original response payload
3) Compatibility aliases (transition)
POST /uploadFile->POST /core/upload-filePOST /createSignedUrl->POST /core/create-signed-urlPOST /invokeLLM->POST /core/invoke-llm
4) Rate-limit baseline (initial)
/core/invoke-llm: 60 requests per minute per user/core/upload-file: 30 requests per minute per user/core/create-signed-url: 120 requests per minute per user/commands/*: 60 requests per minute per user
4.1 Timeout baseline (initial)
/core/invoke-llm: 20-second hard timeout- other
/core/*routes: 10-second timeout /commands/*routes: 15-second timeout
5) Core routes
5.1 Upload file
- Method and route:
POST /core/upload-file - Auth: required
- Idempotency key: optional
- Request: multipart form data
file(required)category(optional)visibility(optional:publicorprivate)
- Success
200:
{
"fileUri": "gs://bucket/path/file.ext",
"contentType": "application/pdf",
"size": 12345,
"bucket": "krow-uploads-private",
"path": "documents/staff/..."
}
- Errors:
UNAUTHENTICATEDINVALID_FILE_TYPEFILE_TOO_LARGEUPLOAD_FAILED
5.2 Create signed URL
- Method and route:
POST /core/create-signed-url - Auth: required
- Idempotency key: optional
- Request:
{
"fileUri": "gs://bucket/path/file.ext",
"expiresInSeconds": 300
}
- Success
200:
{
"signedUrl": "https://...",
"expiresAt": "2026-02-24T15:00:00Z"
}
- Errors:
UNAUTHENTICATEDFORBIDDEN_FILE_ACCESSINVALID_EXPIRES_INSIGN_URL_FAILED
5.3 Invoke model
- Method and route:
POST /core/invoke-llm - Auth: required
- Idempotency key: optional
- Request:
{
"prompt": "...",
"responseJsonSchema": {},
"fileUrls": []
}
- Success
200:
{
"result": {},
"model": "provider/model-name",
"latencyMs": 980
}
- Errors:
UNAUTHENTICATEDINVALID_SCHEMAMODEL_TIMEOUTMODEL_FAILED
- Provider default:
- Vertex AI Gemini
5.4 Health check
- Method and route:
GET /healthz - Auth: optional (internal policy)
- Success
200:
{
"ok": true,
"service": "krow-backend",
"version": "commit-or-tag"
}
5.5 Storage bucket policy defaults (dev)
- Public bucket:
krow-workforce-dev-public - Private bucket:
krow-workforce-dev-private - Private objects are never returned directly; only signed URLs are returned.
6) Command routes (wave 1)
6.1 Create order
- Method and route:
POST /commands/orders/create - Auth: required
- Idempotency key: required
- Purpose: create order + shifts + roles atomically
- Replaces:
apps/web/src/features/operations/orders/components/CreateOrderDialog.tsxapps/mobile/packages/features/client/home/lib/src/presentation/widgets/shift_order_form_sheet.dartapps/mobile/packages/features/client/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart
6.2 Update order
- Method and route:
POST /commands/orders/{orderId}/update - Auth: required
- Idempotency key: required
- Purpose: policy-safe multi-entity order update
- Replaces:
apps/web/src/features/operations/orders/EditOrder.tsxapps/mobile/packages/features/client/view_orders/lib/src/presentation/widgets/view_order_card.dart
6.3 Cancel order
- Method and route:
POST /commands/orders/{orderId}/cancel - Auth: required
- Idempotency key: required
- Purpose: enforce cancellation policy and return explicit conflict code
- Replaces:
apps/web/src/features/operations/orders/OrderDetail.tsx
6.4 Change shift status
- Method and route:
POST /commands/shifts/{shiftId}/change-status - Auth: required
- Idempotency key: required
- Purpose: enforce state transitions server-side
- Replaces:
apps/web/src/features/operations/tasks/TaskBoard.tsx
6.5 Assign staff
- Method and route:
POST /commands/shifts/{shiftId}/assign-staff - Auth: required
- Idempotency key: required
- Purpose: assign + count update + conflict checks atomically
- Replaces:
apps/web/src/features/operations/orders/components/AssignStaffModal.tsx
6.6 Accept shift
- Method and route:
POST /commands/shifts/{shiftId}/accept - Auth: required
- Idempotency key: required
- Purpose: application + counters + rollback-safe behavior in one command
- Replaces:
apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart
7) Locked defaults before coding starts
- Idempotency keys are stored in Cloud SQL with 24-hour retention.
- Request validation library is
zod. - Validation schema location is
backend/<service>/src/contracts/. - Storage buckets are:
krow-workforce-dev-publickrow-workforce-dev-private
- Model provider is Vertex AI Gemini with a 20-second timeout for
/core/invoke-llm.
8) Target response-time objectives (p95)
/healthzunder 200ms/core/create-signed-urlunder 500ms/commands/*under 1500ms/core/invoke-llmunder 15000ms