From 2149e6435a5ceda4a15cef3179cfe13969f04ad2 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Tue, 18 Aug 2026 22:08:41 +0400 Subject: [PATCH] docs: final backend handoff - revision endpoints, response-shape additions, close-out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates FRONTEND-API-SURFACE-COMPLETE.md to cover everything built after it was first generated - this is the final version for this pass, not a snapshot mid-way through. Added, none of which existed in the doc before: - §18: the 4 marketplace revision endpoints (create draft/validate/ publish/rollback) - built this session, missing from the census entirely. Flags the same draft/validated/preview/published ambiguity already documented in the model itself, so backend sees it without having to read source. - §19: RoutingContext as an optional field addition on GET /api/admin/v2/orders/{id} - not a new endpoint, a response-shape ask. - §20: order pricing-breakdown fields (unitPriceMinor, lineTotalMinor, priceSnapshotId, discountMinor, fxQuoteId, deliveryMinor) feeding the new total-formula panel. States plainly that the panel shows nothing rather than a wrong number while these are absent. - §21: 8 optional dashboard-metrics fields (GMV, conversion, moderation queue, etc.) - explicitly labelled a genuine ask, not a confirmed contract, since no spec exists for this endpoint at all (§15). - §22: states directly that the frontend's new double-click guard does not replace backend idempotency enforcement and was never meant to - closes one UI race, does nothing for a retried request or a duplicate webhook. Counts updated (47->51 specified, 86->90 total; +3 response-shape asks that aren't new endpoints). Closing section states the one item genuinely blocked pending a live backend (F60, the full acceptance-path E2E) so nobody mistakes "frontend backlog complete" for "nothing left to build." Co-Authored-By: Claude Opus 5 --- docs/backend/FRONTEND-API-SURFACE-COMPLETE.md | 97 +++++++++++++++++-- docs/backend/README.md | 2 +- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/docs/backend/FRONTEND-API-SURFACE-COMPLETE.md b/docs/backend/FRONTEND-API-SURFACE-COMPLETE.md index 68bba05..3145cb3 100644 --- a/docs/backend/FRONTEND-API-SURFACE-COMPLETE.md +++ b/docs/backend/FRONTEND-API-SURFACE-COMPLETE.md @@ -1,6 +1,8 @@ # Complete Frontend API Surface — Master Endpoint List -Generated 2026-08-18 directly from source (every `this.http.get/post/patch/put/delete` call across `src/app/core/`, `src/app/features/admin/`, `src/app/services/api.service.ts`). This is not a design document — it is a **census**: every endpoint this codebase currently calls or will call once its gateway swap goes live, in one place, cross-referenced against the contracts that already exist. +Generated 2026-08-18, updated same day after the frontend backlog (F1–F65) closed. Directly from source (every `this.http.get/post/patch/put/delete` call across `src/app/core/`, `src/app/features/admin/`, `src/app/services/api.service.ts`). This is not a design document — it is a **census**: every endpoint this codebase currently calls or will call once its gateway swap goes live, in one place, cross-referenced against the contracts that already exist. + +**This is the final handoff doc for this pass.** Frontend work is done except one item that genuinely cannot be finished without a live backend (§19). Everything else — every gateway, every model, every invariant — is written, tested, and pushed. What follows is everything backend needs to make it real. **Why this exists.** The individual Phase/Track contracts in this directory each cover one domain well. Nothing until now listed the *entire* surface in one pass, so a backend dev building against these docs had no way to see what's fully specified, what's inferred-and-needs-confirmation, and what has no contract at all. This closes that gap. @@ -253,20 +255,103 @@ Contract: [PARTNER-PROVISIONING-API-CONTRACT.md](PARTNER-PROVISIONING-API-CONTRA | GET | `/api/backoffice/categories` | `api-backoffice-data.provider.ts` | | GET | (tenant bootstrap URL) | `api-bootstrap.provider.ts` — see `BACKEND-HANDOFF.md` §1a | +## 18. Marketplace publish/revision model — ✅ Specified + +Contract: [PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) §5. Frontend core built (`marketplace-revision-*.gateway.ts`), not yet wired into the project editor's UI — see §20. + +| Method | Path | Called from | +|---|---|---| +| POST | `/api/admin/v2/marketplaces/{id}/revisions` | `marketplace-revision-api.gateway.ts` — create draft | +| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/validate` | `marketplace-revision-api.gateway.ts` | +| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/publish` | `marketplace-revision-api.gateway.ts` | +| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/rollback` | `marketplace-revision-api.gateway.ts` — creates a NEW revision, never mutates the old one | + +**One real ambiguity in §5 itself, flagged for confirmation, not guessed silently:** the pipeline is described as 4 stages (`draft → validated → preview → publish`) but only 3 write endpoints exist (validate/publish/rollback) — there is no dedicated "move to preview" call. The frontend model assumes `POST .../validate` moves a revision straight to `preview` (the state `publish` requires), treating `validated` as a value the caller may never observe. **Confirm this is correct before implementing** — if the real response returns `status: 'validated'` and requires a separate step to reach `preview`, the frontend model and this doc both need updating. + +## 19. RoutingContext on payments — carried through, not yet backend-verified + +Contract: [PARTNER-PROVISIONING-API-CONTRACT.md](PARTNER-PROVISIONING-API-CONTRACT.md) §7, [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §6.5. Not a separate endpoint — a field addition backend needs to populate on existing responses: + +```ts +routing?: { + companyId: string; + routingPath: string[]; + leafNodeId: string; + environment: 'TEST' | 'LIVE'; + merchantReference: string; + providerPaymentId: string; +} +``` + +Frontend added this as an **optional** field on `AdminOrder` (`admin-order.model.ts`) and renders it on the order detail page when present. Nothing breaks if it's absent — but nothing shows the payment-point attribution either until backend populates it on `GET /api/admin/v2/orders/{id}`. + +## 20. Order pricing breakdown — same pattern, different fields + +Contract: [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §5.3. Optional fields added to `AdminOrderItem` and `AdminOrder`: + +```ts +// per line +unitPriceMinor?: number; +lineTotalMinor?: number; +priceSnapshotId?: string; +discountMinor?: number; + +// per order +fxQuoteId?: string; +deliveryMinor?: number; +``` + +Frontend renders a "total formula" panel on the order detail page (`order-total-formula.component.ts`) reconstructing `total = sum(unitPrice*qty) - discounts + delivery`, with the FX quote used. **It refuses to show a partial breakdown** — every line must carry `unitPriceMinor` or the panel says "not available" instead of a number that's silently wrong. Populate these fields on `GET /api/admin/v2/orders/{id}` to make it real; until then it correctly shows nothing. + +## 21. Dashboard metrics — 8 new optional fields, no shape confirmed + +Contract intent: [PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) §7's target metric list — no contract doc defines `GET /api/admin/v2/dashboard/metrics`'s response shape (§15 already flagged this endpoint has no spec at all). Frontend added these as optional fields on `AdminDashboardMetrics`, each rendering `'unknown'` (not a fabricated `'healthy'`) while absent: + +```ts +gmvMinor?: number; +currency?: string; +paidOrdersCount?: number; +conversionRate?: number; // 0-1, not a percentage +paymentFailureRate?: number; // 0-1 +moderationQueueCount?: number; +lowStockCount?: number; +unmatchedEventsCount?: number; +integrationHealthyCount?: number; +integrationTotalCount?: number; +``` + +This is a genuine ask, not a confirmed contract — §15's recommendation to write a real spec for this endpoint still stands. These field names are what the frontend already expects; change them here first if backend needs different ones. + +## 22. Idempotency — frontend now guards, backend enforcement is still required + +The frontend added a client-side guard against double-submitting checkout (a real bug: double-clicking used to fire two `POST /api/v2/storefront/checkout` calls — fixed in `cart.component.ts`, `checkoutInFlight` signal). **This does not replace backend idempotency and was never meant to.** It closes one specific UI race; it does nothing for a retried request from a flaky network, a backgrounded tab resuming, or an actual duplicate webhook delivery. Contract requirements are unchanged and still required: + +- `PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md` §6.3 — webhook idempotency key = `provider + providerEventId` +- `PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md` §6.4 — order creation idempotency key = `checkoutSessionId` +- `PARTNER-PROVISIONING-API-CONTRACT.md` §5 — `Idempotency-Key` header semantics for all partner-API creates + --- ## Summary counts | Status | Count | |---|---| -| ✅ Specified | 47 | +| ✅ Specified | 51 | | ⚠️ Inferred (needs confirmation) | 24 | | ❌ Undocumented (legacy) | 15 | -| **Total distinct endpoints called** | **86** | +| **Total distinct endpoints called** | **90** | + +Plus 3 response-shape additions (§19–21) on existing endpoints — not new endpoints, new optional fields on responses those endpoints already return. ## What backend needs to do with this -1. **Build the ✅ rows as written** — they match an existing contract doc exactly. +1. **Build the ✅ rows as written** — they match an existing contract doc exactly. This includes §18's 4 revision endpoints, pending confirmation on the `validated`/`preview` ambiguity called out there. 2. **Confirm or correct every ⚠️ row** — each one has a comment at its call site in source explaining the inference. Search the codebase for `Inferred` to find all 24 in place, with the reasoning right next to the code. -3. **Write a contract for §15** (transactions, monitoring, moderation) — real UI, real gateways, zero spec. Highest-priority gap in this whole list. -4. **Decide the fate of §1** — 15 legacy endpoints with no contract at all, still live. Either document them as a stable, permanent surface, or set a Track N migration date. +3. **Populate the 3 optional field sets (§19–21)** on the endpoints that already exist — `routing` and pricing-breakdown fields on `GET /api/admin/v2/orders/{id}`, the 8 metric fields on `GET /api/admin/v2/dashboard/metrics`. Nothing on the frontend breaks while these are absent; nothing shows the real data either. +4. **Write a contract for §15** (transactions, monitoring, moderation) — real UI, real gateways, zero spec. Highest-priority gap in this whole list. +5. **Decide the fate of §1** — 15 legacy endpoints with no contract at all, still live. Either document them as a stable, permanent surface, or set a Track N migration date. +6. **Enforce idempotency server-side regardless of §22** — the frontend's double-click guard is a UI nicety, not a substitute for `Idempotency-Key`/`providerEventId` dedup. + +## One item that stays blocked until a real backend exists + +The frontend backlog (F1–F65, tracked this session) is complete except **F60: the full acceptance-path E2E** — seller → catalog → storefront → cart → checkout → payment → order → notification → fulfillment, in one test, against real infrastructure. Every other item is written, unit-tested, E2E-covered where an E2E test could prove something real, and pushed. This one cannot be honestly finished by mocking harder — it needs an actual backend to run against. Once even a minimal version of Phases 1–4 is live, this is the next thing to build (`docs/PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md` Track Q, Q3). diff --git a/docs/backend/README.md b/docs/backend/README.md index fb8b5f7..8c28705 100644 --- a/docs/backend/README.md +++ b/docs/backend/README.md @@ -2,7 +2,7 @@ > **New here? Start with [BACKEND-HANDOFF.md](BACKEND-HANDOFF.md)** — reading order, current infrastructure state, auth surface, and what a working dev environment still needs. > -> **Want every endpoint in one place? [FRONTEND-API-SURFACE-COMPLETE.md](FRONTEND-API-SURFACE-COMPLETE.md)** — generated directly from source, all 86 endpoints the frontend currently calls, marked Specified / Inferred / Undocumented against the contracts below. Use it to see gaps across all contracts at once; use the individual Phase/Track docs for full entity shapes and invariants. +> **Want every endpoint in one place? [FRONTEND-API-SURFACE-COMPLETE.md](FRONTEND-API-SURFACE-COMPLETE.md)** — the final handoff doc. Generated directly from source, all 90 endpoints the frontend currently calls plus 3 response-shape additions on existing endpoints, marked Specified / Inferred / Undocumented against the contracts below. Use it to see gaps across all contracts at once; use the individual Phase/Track docs for full entity shapes and invariants. This directory is the complete set of wire contracts for building the backend behind [Product Plan v3.1](../PRODUCT-PLAN-v3.1-GAP-ANALYSIS.md). Each doc specifies entities, endpoints, and invariants only — never DB schema or service boundaries, which stay backend's own call.