feat(backend): implement v2 domain slice and live smoke
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
# M4 API Catalog (Core Only)
|
||||
|
||||
Status: Active
|
||||
Date: 2026-02-24
|
||||
Date: 2026-03-11
|
||||
Owner: Technical Lead
|
||||
Environment: dev
|
||||
|
||||
## 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.
|
||||
|
||||
## Related next-slice contract
|
||||
Verification pipeline design (attire, government ID, certification):
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
# M4 Core API Frontend Guide (Dev)
|
||||
|
||||
Status: Active
|
||||
Last updated: 2026-02-27
|
||||
Last updated: 2026-03-11
|
||||
Audience: Web and mobile frontend developers
|
||||
|
||||
Related guide:
|
||||
1. `docs/MILESTONES/M4/planning/m4-v2-frontend-migration-guide.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.
|
||||
|
||||
## 1) Base URLs (dev)
|
||||
1. Core API: `https://krow-core-api-e3g6witsvq-uc.a.run.app`
|
||||
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:
|
||||
@@ -293,7 +302,7 @@ Authorization: Bearer <firebase-id-token>
|
||||
## 5.1 Signed URL request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-e3g6witsvq-uc.a.run.app/core/create-signed-url', {
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/create-signed-url', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
@@ -310,7 +319,7 @@ const data = await res.json();
|
||||
## 5.2 Model request
|
||||
```ts
|
||||
const token = await firebaseAuth.currentUser?.getIdToken();
|
||||
const res = await fetch('https://krow-core-api-e3g6witsvq-uc.a.run.app/core/invoke-llm', {
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/invoke-llm', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
@@ -331,7 +340,7 @@ 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-e3g6witsvq-uc.a.run.app/core/rapid-orders/transcribe', {
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/rapid-orders/transcribe', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
@@ -349,7 +358,7 @@ 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-e3g6witsvq-uc.a.run.app/core/rapid-orders/parse', {
|
||||
const res = await fetch('https://krow-core-api-v2-e3g6witsvq-uc.a.run.app/core/rapid-orders/parse', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
|
||||
@@ -178,11 +178,17 @@ Tables:
|
||||
3. `workforce`
|
||||
4. `applications`
|
||||
5. `assignments`
|
||||
6. `staff_reviews`
|
||||
7. `staff_favorites`
|
||||
|
||||
Rules:
|
||||
1. One active workforce relation per `(vendor_id, staff_id)`.
|
||||
2. One application per `(shift_id, role_id, staff_id)` unless versioned intentionally.
|
||||
3. Assignment state transitions only through command APIs.
|
||||
4. Business quality signals are relational:
|
||||
- `staff_reviews` stores rating and review text from businesses,
|
||||
- `staff_favorites` stores reusable staffing preferences,
|
||||
- aggregate rating is materialized on `staffs`.
|
||||
|
||||
## 4.5 Compliance and Verification
|
||||
Tables:
|
||||
@@ -222,19 +228,22 @@ Rules:
|
||||
|
||||
## 4.9 Attendance, Timesheets, and Offense Governance
|
||||
Tables:
|
||||
1. `attendance_events` (append-only: clock-in/out, source, correction metadata)
|
||||
2. `attendance_sessions` (derived work session per assignment)
|
||||
3. `timesheets` (approval-ready payroll snapshot)
|
||||
4. `timesheet_adjustments` (manual edits with reason and actor)
|
||||
5. `offense_policies` (tenant/business scoped policy set)
|
||||
6. `offense_rules` (threshold ladder and consequence)
|
||||
7. `offense_events` (actual violation events)
|
||||
8. `enforcement_actions` (warning, suspension, disable, block)
|
||||
1. `clock_points` (approved tap and geo validation points per business or venue)
|
||||
2. `attendance_events` (append-only: clock-in/out, source, NFC, geo, correction metadata)
|
||||
3. `attendance_sessions` (derived work session per assignment)
|
||||
4. `timesheets` (approval-ready payroll snapshot)
|
||||
5. `timesheet_adjustments` (manual edits with reason and actor)
|
||||
6. `offense_policies` (tenant/business scoped policy set)
|
||||
7. `offense_rules` (threshold ladder and consequence)
|
||||
8. `offense_events` (actual violation events)
|
||||
9. `enforcement_actions` (warning, suspension, disable, block)
|
||||
|
||||
Rules:
|
||||
1. Attendance corrections are additive events, not destructive overwrites.
|
||||
2. Offense consequences are computed from policy + history and persisted as explicit actions.
|
||||
3. Manual overrides require actor, reason, and timestamp in audit trail.
|
||||
2. NFC and geo validation happens against `clock_points`, not hardcoded client logic.
|
||||
3. Rejected attendance attempts are still logged as events for audit.
|
||||
4. Offense consequences are computed from policy + history and persisted as explicit actions.
|
||||
5. Manual overrides require actor, reason, and timestamp in audit trail.
|
||||
|
||||
## 4.10 Stakeholder Network Extensibility
|
||||
Tables:
|
||||
|
||||
@@ -96,6 +96,8 @@ erDiagram
|
||||
| `shift_managers` | `id` | `shift_id -> shifts.id`, `team_member_id -> team_members.id` | `(shift_id, team_member_id)` |
|
||||
| `applications` | `id` | `tenant_id -> tenants.id`, `shift_id -> shifts.id`, `role_id -> roles.id`, `staff_id -> staffs.id` | `(shift_id, role_id, staff_id)` |
|
||||
| `assignments` | `id` | `tenant_id -> tenants.id`, `shift_role_id -> shift_roles.id`, `workforce_id -> workforce.id` | `(shift_role_id, workforce_id)` active |
|
||||
| `staff_reviews` | `id` | `tenant_id -> tenants.id`, `business_id -> businesses.id`, `staff_id -> staffs.id`, `assignment_id -> assignments.id` | `(business_id, assignment_id, staff_id)` |
|
||||
| `staff_favorites` | `id` | `tenant_id -> tenants.id`, `business_id -> businesses.id`, `staff_id -> staffs.id` | `(business_id, staff_id)` |
|
||||
|
||||
### 4.2 Diagram
|
||||
|
||||
@@ -122,6 +124,11 @@ erDiagram
|
||||
STAFFS ||--o{ APPLICATIONS : applies
|
||||
SHIFT_ROLES ||--o{ ASSIGNMENTS : allocates
|
||||
WORKFORCE ||--o{ ASSIGNMENTS : executes
|
||||
BUSINESSES ||--o{ STAFF_REVIEWS : rates
|
||||
STAFFS ||--o{ STAFF_REVIEWS : receives
|
||||
ASSIGNMENTS ||--o{ STAFF_REVIEWS : references
|
||||
BUSINESSES ||--o{ STAFF_FAVORITES : favorites
|
||||
STAFFS ||--o{ STAFF_FAVORITES : selected
|
||||
```
|
||||
```
|
||||
|
||||
@@ -131,7 +138,8 @@ erDiagram
|
||||
|
||||
| Model | Primary key | Foreign keys | Important unique keys |
|
||||
|---|---|---|---|
|
||||
| `attendance_events` | `id` | `tenant_id -> tenants.id`, `assignment_id -> assignments.id` | `(assignment_id, source_event_id)` |
|
||||
| `clock_points` | `id` | `tenant_id -> tenants.id`, `business_id -> businesses.id` | `(tenant_id, nfc_tag_uid)` nullable |
|
||||
| `attendance_events` | `id` | `tenant_id -> tenants.id`, `assignment_id -> assignments.id`, `clock_point_id -> clock_points.id` | append-only event log |
|
||||
| `attendance_sessions` | `id` | `tenant_id -> tenants.id`, `assignment_id -> assignments.id` | one open session per assignment |
|
||||
| `timesheets` | `id` | `tenant_id -> tenants.id`, `assignment_id -> assignments.id`, `staff_id -> staffs.id` | `(assignment_id)` |
|
||||
| `timesheet_adjustments` | `id` | `timesheet_id -> timesheets.id`, `actor_user_id -> users.id` | - |
|
||||
@@ -144,6 +152,8 @@ erDiagram
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
BUSINESSES ||--o{ CLOCK_POINTS : defines
|
||||
CLOCK_POINTS ||--o{ ATTENDANCE_EVENTS : validates
|
||||
ASSIGNMENTS ||--o{ ATTENDANCE_EVENTS : emits
|
||||
ASSIGNMENTS ||--o{ ATTENDANCE_SESSIONS : opens
|
||||
ASSIGNMENTS ||--o{ TIMESHEETS : settles
|
||||
|
||||
303
docs/MILESTONES/M4/planning/m4-v2-frontend-migration-guide.md
Normal file
303
docs/MILESTONES/M4/planning/m4-v2-frontend-migration-guide.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# M4 V2 Frontend Migration Guide
|
||||
|
||||
Status: Active
|
||||
Last updated: 2026-03-11
|
||||
Audience: Web and mobile frontend developers
|
||||
|
||||
## 1) Purpose
|
||||
This document tells frontend exactly how to migrate toward the v2 backend services on this branch.
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user