docs(backend): add Seller Management section to BACKEND.md
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.
This commit is contained in:
213
docs/BACKEND.md
213
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
|
||||
|
||||
Reference in New Issue
Block a user