From fa6e5cd68b462b7f6576da8045ff56c08c9f40ae Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sun, 26 Jul 2026 22:41:57 +0400 Subject: [PATCH] docs(backend): add Seller Management section to BACKEND.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/BACKEND_API.md no longer exists as a live file (merged into BACKEND.md in an earlier consolidation pass, per that doc's own intro - only docs/archive/BACKEND_API.md remains, historical only). This mission's "update BACKEND_API.md" instruction is fulfilled by extending the doc that actually supersedes it: new §11 "Seller Management (Optional Capability)", added to the top-of-file table of contents, no existing section renumbered or altered. Every subsection explicitly tagged Implemented / Planned / Future, matching the same legend used in docs/architecture/foundation/ Seller-Management.md (the frontend-side capability doc this section is the backend counterpart to): - 11.2 Future entities: Marketplace (Implemented, existing TenantConfig unchanged), Seller/SellerBranding (Planned - frontend types exist, no backend schema), SellerUser/SellerSettings/ SellerInvitation (Future - no type, no concept, named for roadmap completeness only). - 11.3 Future endpoints: Seller CRUD/Activation/Invitations/Branding/ Analytics/Dashboard - all Future, none designed, each noted as following the existing mock-to-API-gateway pattern (SS8) once built. - 11.4 Authentication: SellerPermissionRole (4 roles) explicitly flagged as a separate vocabulary from the existing, live AdminRole - not merged, no guard wired, zero auth change. - 11.5 Domain resolution: market.com -> Marketplace is Implemented today (ADR-001, backend-Host-resolved); nike.market.com -> Marketplace -> Seller is Future, no backend resolves it - and per the storefront audit, needs no frontend routing change once it does. - 11.6 Bootstrap additions: modules/modules.sellerManagement documented as Implemented-as-contract (typed, always false/absent today); sellerScope/sellerBranding as Planned with an explicitly flagged open question (SellerConfig vs SellerBranding nesting not reconciled); permissions noted as existing/unrelated today. - 11.7 Checkout modes: Unified Order vs Split Orders - Future, not designed, flagged as the single most consequential undecided item for backend design given payments/refunds/reporting all depend on it. - 11.8 Product ownership: sellerId? on Item/AdminProduct/AdminOrder - Implemented as schema only (optional, absent = marketplace-owned, verified backward-compatible via tsc staying clean). Existing products remain valid with no migration required - NULL/absent ownership documented as a permanent state, not transitional. No backend implemented. No frontend code touched. Documentation only. --- docs/BACKEND.md | 213 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/docs/BACKEND.md b/docs/BACKEND.md index d82734b..4eefb80 100644 --- a/docs/BACKEND.md +++ b/docs/BACKEND.md @@ -59,6 +59,7 @@ background reading. 8. [Real Backend Implementation Guide](#8-real-backend-implementation-guide) 9. [Backend Checklist](#9-backend-checklist) 10. [Maintenance Mode](#10-maintenance-mode) +11. [Seller Management (Optional Capability)](#11-seller-management-optional-capability) --- ## 1. Bootstrap @@ -4975,6 +4976,218 @@ Each has a **Recommended default** — apply it unless flagged otherwise. --- +## 11. Seller Management (Optional Capability) + +Status legend for this section only (matches +`docs/architecture/foundation/Seller-Management.md`, the frontend-side +capability doc this section is the backend counterpart to): + +- **Implemented** — exists in frontend source today, verified. +- **Planned** — a typed contract or explicit ADR decision exists; no backend + or runtime behavior exists yet. +- **Future** — named for roadmap completeness only. No shape, contract, or + decision exists. Do not build against a Future item without a new ADR. + +**Nothing in this section is implemented on the backend, because no backend +exists yet for anything in this document.** Frontend-side preparation +(typed models, a disabled-by-default feature flag, one Backoffice +placeholder page) is real and is marked Implemented per item below; backend +work is entirely Planned or Future. This section documents the frontend's +existing preparation and the shape a backend should target — it does not +invent new frontend behavior, and per this section's mission, it must not +be read as backend implementation guidance beyond documentation. + +### 11.1 Overview + +Seller Management is an optional platform capability: a marketplace +(tenant) may host zero or more independent sellers, each scoped beneath it. +It is not a second tenancy tier — see §11.5 Domain Resolution. Full +frontend-side detail: `docs/architecture/foundation/Seller-Management.md` +and its companion ADR-011. + +### 11.2 Future entities + +None of these have a backend schema, migration, or storage decision yet. +Frontend typed equivalents (where they exist) are cited per entity. + +- **Marketplace** — **Implemented** (existing `TenantConfig`, unchanged by + this work). The plus a new **Planned** frontend-only reference type, + `MarketplaceRef` (`core/sellers/models/marketplace-ref.model.ts`): + `{id, slug, name}`, the minimal view of a marketplace as seen from a + seller record. Not a backend entity of its own — it's a projection of + the existing Marketplace/tenant entity. +- **Seller** — **Planned** (frontend type exists: `Seller`, + `core/sellers/models/seller.model.ts` — `id`, `marketplace: MarketplaceRef`, + `name`, `slug`, `status: SellerStatus`, optional `branding: SellerBranding`, + `createdAt`/`updatedAt`). No backend table, migration, or endpoint exists. +- **SellerUser** — **Future**. No frontend type exists for a user record + scoped to a specific seller (distinct from the existing marketplace-level + `AdminUser`, `features/admin/users/models/admin-user.model.ts`). Named + here for roadmap completeness only — shape not decided. +- **SellerBranding** — **Planned** (frontend type exists: `SellerBranding`, + `core/sellers/models/seller-branding.model.ts` — logo, banner, + description, contacts, address, theme overrides, every field optional). + No backend storage or rendering/precedence logic exists (frontend side of + precedence — falling back to marketplace branding — is also undecided, + per `Seller-Management.md` §6). +- **SellerSettings** — **Future**. No frontend type, no backend concept. + Distinct from `SellerBranding` (visual) — would cover operational + settings (e.g. notification preferences, payout details) if this + capability is ever built out. Not designed. +- **SellerInvitation** — **Future**. No frontend type, no backend concept. + The onboarding mechanism implied by the existing Phase 1 UI's "Request + Access" form (`features/admin/seller-management/pages/ + admin-seller-management-page.component.ts`) is a **mocked, client-side-only + submission today** — no email is sent, no invitation record is created, + nothing persists past the browser session. A real invitation flow + (backend-issued invitation token, acceptance, seller-account creation) is + entirely Future. + +### 11.3 Future endpoints + +No endpoint below exists. Each would follow this codebase's established +mock↔API-gateway pattern (§8) once built — that pattern is a statement of +intent here, not a designed URL/DTO contract. + +- **Seller CRUD** — **Future**. No `SellerRepository`/`SellerGateway` + interface exists yet (unlike e.g. Categories, §3.2, which already has + this seam). Would need `list/get/create/update/delete` following the + conventions in §2 (pagination, filtering, error envelope) once designed. +- **Seller Activation** — **Future**. Ties to `SellerStatus` + (`'pending' | 'active' | 'suspended' | 'disabled'`, frontend type only, + no transition logic anywhere) and to SellerInvitation above. No + state-machine, no endpoint, no decision on who can activate/suspend a + seller. +- **Seller Invitations** — **Future**. See SellerInvitation above — this + would be the endpoint surface for that entity, once it exists. +- **Seller Branding** — **Future** (endpoint). The `SellerBranding` type is + Planned (§11.2) but no read/write endpoint exists to serve or persist it. +- **Seller Analytics** — **Future**. The existing `AdminAnalyticsFacade` + (§3.20) already has no real aggregation endpoint for the marketplace as a + whole — per-seller analytics is a further layer on top of a gap that + isn't solved yet even without sellers. Not designed. +- **Seller Dashboard** — **Future**. Same reasoning as Seller Analytics; + the existing `AdminDashboardMetricsGateway.loadMetrics()` (§3, Dashboard) + is a bare no-arg call with no parameter to scope by seller even + syntactically — a seller dashboard is new surface, not an extension. + +### 11.4 Authentication + +**No authentication change of any kind exists in this work.** The four +roles below are a **Planned** vocabulary only +(`SellerPermissionRole`, `core/sellers/models/seller-permissions.model.ts`): +`marketplaceOwner`, `seller`, `sellerStaff`, `platformAdmin`. This is +**explicitly a separate vocabulary from the existing, live `AdminRole`** +(Owner/Manager/Support/ReadOnly, `core/auth/models/permission.model.ts`, +§4) — not merged, not wired into any guard, no route currently checks it. + +Closest existing hook (per +`Seller-Management-Backoffice-Readiness-Audit.md`): `AdminUser` already +carries an `AdminUserScope` field (`'marketplace' | 'office'` in seed +data) and a permission-array shape on `AdminRole` — the natural future home +for these four roles, but today it's used for display labels only, nothing +gates on it. **Future:** deciding whether `SellerPermissionRole` extends, +replaces, or sits alongside `AdminRole`; wiring any guard/interceptor to +check it; deciding how a Seller/Seller Staff session authenticates at all +(same Telegram/Ed25519 mechanisms as today, §4, or something new — not +decided). + +### 11.5 Domain resolution + +``` +market.com → Marketplace (Implemented — ADR-001, live today) +nike.market.com → Marketplace → Seller (Future — no backend resolves this yet) +``` + +**Implemented today:** tenant (Marketplace) resolution is entirely +backend-side by request Host (ADR-001, §1.9). The frontend never resolves +tenant identity itself — it calls `GET /bootstrap` and renders whatever +comes back for whatever hostname it's running on. + +**Future:** a second-level Host pattern (`{seller}.{marketplace-domain}`) +resolving to a seller scope beneath that marketplace. No backend logic for +this exists. Per the frontend-side storefront audit +(`Seller-Management-Storefront-Audit.md`), the frontend's existing +discipline — nothing hardcodes hostname, canonical URLs already derive +from `location.origin` dynamically — means this pattern needs **no +frontend routing change** once a backend resolves it; the open work is +entirely backend resolution logic plus which bootstrap fields carry the +resolved seller data (see §11.6). + +### 11.6 Bootstrap additions + +All **Implemented as typed contracts, always absent/false in every real +bootstrap response today** — no backend populates any of these fields +anywhere: + +- **`modules`** — `BootstrapConfig.modules?: PlatformModulesConfig` + (`shared/models/config/platform-modules.model.ts`). Optional; absent + means every module is disabled. +- **`modules.sellerManagement`** — `{enabled: boolean}`, defaults to + `false` (`DEFAULT_PLATFORM_MODULES_CONFIG`). Read by the Phase 1 page + today; no backend ever sets it `true`. +- **`sellerScope`** — **Planned**. The frontend has a domain-level + `SellerScope` type (`core/sellers/models/seller-scope.model.ts`: + `{sellerId, marketplaceId}`) and a bootstrap-wire counterpart, + `BootstrapConfig.seller?: SellerConfig` + (`shared/models/config/seller.model.ts`) — present only when the backend + has resolved a seller-level request scope (§11.5). No backend does this + yet; the field is optional and always absent today. +- **`sellerBranding`** — **Planned**. Carried as `SellerConfig`'s branding + shape would need to be, or as `BootstrapConfig.seller?.branding` — the + exact nesting isn't finalized, since `SellerConfig` (bootstrap wire + shape) and `SellerBranding` (domain type) are currently separate types + that haven't been reconciled (see `Seller-Management-Domain-Models.md`). + Flagged as an open question here rather than guessed at. +- **`permissions`** — **Implemented** (existing, unchanged) — + `BootstrapConfig.permissions: PermissionsConfig` already exists and is + unrelated to Seller Management's future permission model; the two are + not connected today. **Future:** whether/how `SellerPermissionRole` + (§11.4) ever surfaces through this existing field or a new one — not + decided. + +### 11.7 Checkout modes + +**Future — not designed.** Two named concepts, no decision between them: + +- **Unified Order** — one customer purchase, regardless of how many + sellers' items are in the cart, produces one order record. +- **Split Orders** — one customer purchase spanning multiple sellers + produces one order record per seller. + +**Current, unrelated to sellers:** checkout today is a single inline +popup flow (`pages/cart/cart.component.ts`) producing exactly one order via +one `POST /orders`-equivalent call — there is no multi-seller cart concept +of any kind to split or unify, because every product is marketplace-owned. +This decision has real consequences (payments, refunds, reporting) that +depend on it — explicitly listed as open in +`Seller-Management.md` §6 and repeated here because it's the single most +consequential undecided item for backend design once this capability moves +past preparation. + +### 11.8 Product ownership + +**Implemented (schema only), Future (logic).** `sellerId?: string` was +added as an **optional** field to three existing frontend types: `Item` +(storefront product, `models/item.model.ts`), `AdminProduct` +(`features/admin/products/models/admin-product.model.ts`), and `AdminOrder` +(`features/admin/orders/models/admin-order.model.ts`). In every case, +absent means marketplace-owned — exactly what every existing product and +order is today. **No frontend code reads or writes this field anywhere.** +No backend column, migration, or filter exists for it either. + +**Compatibility guarantee, verified not assumed:** adding this optional +field required zero changes to any consumer of these three types — +confirmed by `tsc --noEmit` staying clean after the change +(`Seller-Management-Domain-Models.md`). The same guarantee applies to any +future backend schema change: a nullable `seller_id` column (or +equivalent) that defaults to `NULL`/absent preserves every existing +product/order exactly as-is. **Existing products remain valid** with no +migration required to backfill a value — `NULL`/absent seller ownership is +a first-class, permanent state, not a transitional one. + +--- + ## Appendix: `docs/TODO.md` items merged into this document (2026-07-26) Final Project Closeout moved every backend-shaped item out of `docs/TODO.md` into this