Files
marketplaces/docs/architecture/foundation/Seller-Management-Backend-Migration-Plan.md

568 lines
30 KiB
Markdown
Raw Normal View History

docs: Backend Migration Plan for Seller Management Documentation only, no code. Synthesizes the 3 prior audits (Seller-Management.md, the Backoffice readiness audit, the Storefront audit) plus BACKEND.md SS11 into one migration plan covering all 17 requested modules: Authentication, Authorization, Bootstrap, Products, Categories, Orders, Payments, Transactions, Reviews, Analytics, Media, Search, CMS, Builder, Settings, Notifications, Emails, Audit Logs. Per module: current behavior, future behavior, migration strategy, backward compatibility, risk, effort, and an endpoint classification (No change / Minor change / Major change / New endpoint) grounded in facts already established in the prior audits - no new exploration, no invented specifics. Headline finding: Orders (the Unified-vs-Split-Orders decision) is the single highest-risk, most consequential item in the whole plan - payments/refunds/reporting all depend on it, and it can't be resolved by an additive field the way every other domain's seller-scoping can. Payments stays untouched (ADR-010, frozen) under the Unified path; only Split Orders would ever touch the payment flow, and only then with the same scrutiny the original frozen implementation got. Cross-cutting sections included per mission: Database changes (one nullable seller_id column touches existing tables, everything else is new tables - no NOT NULL migration ever required), Permission changes, Caching (bootstrap cache key must include resolved seller identity), Indexes, Security (seller-to-seller isolation treated with tenant-isolation rigor), Performance, API Versioning (ties to the already-open BACKEND.md SS2.10 decision), Migration order (14 numbered dependency steps), and 6 recommended implementation phases (A: Foundation through F: Operational polish). Every phase explicitly re-asserts the non-negotiable constraint: modules.sellerManagement.enabled=false must show zero behavioral difference before/after each phase ships. Linked from docs/architecture/foundation/README.md alongside the other Seller Management docs.
2026-07-26 22:49:07 +04:00
# Seller Management — Backend Migration Plan
Documentation only. No code, no implementation. This plan synthesizes the
three prior audits — do not re-derive facts already established there,
read them for detail:
- [Seller-Management.md](Seller-Management.md) — capability overview,
Implemented/Planned/Future legend
- [Seller-Management-Backoffice-Readiness-Audit.md](Seller-Management-Backoffice-Readiness-Audit.md)
— per-admin-module scoping facts
- [Seller-Management-Storefront-Audit.md](Seller-Management-Storefront-Audit.md)
— storefront/subdomain facts
- `BACKEND.md` §11 — the backend documentation this plan assumes as its
starting contract
**Non-negotiable constraint repeated from the mission, and load-bearing for
every classification below:** existing marketplaces without sellers must
continue working exactly as today. Seller Management stays optional
forever, not just at launch. No endpoint may require seller support unless
`modules.sellerManagement.enabled` is true. Every classification and every
migration strategy in this document is written to satisfy that constraint
first — where a module can't satisfy it without a structural rework, that's
called out explicitly, not glossed over.
## Endpoint classification legend
- **No change** — endpoint's request/response/behavior is untouched.
- **Minor change** — an optional field/parameter added (e.g. `sellerId?` in
a filters object or DTO); absent value behaves identically to today.
- **Major change** — data model or endpoint semantics change beyond an
optional field (e.g. a new join, a new required decision like split
orders, a new aggregation dimension).
- **New endpoint** — doesn't exist today, net-new surface.
## Module-by-module
### Authentication
- **Current:** Two live mechanisms (`BACKEND.md` §4) — Telegram/QR
customer session login (live), Ed25519 admin challenge/response (built
client-side, not wired live). No seller concept in either.
- **Future:** `SellerPermissionRole` (`marketplaceOwner`/`seller`/
`sellerStaff`/`platformAdmin`) as a role a session can carry, and a
decision on whether Seller/Seller Staff authenticate via a third
mechanism or reuse Telegram/Ed25519 with a different claim.
- **Migration strategy:** additive only — a new optional claim/role field
on the existing JWT structure (§4 §3), never a new auth mechanism forced
onto existing flows. Existing customer and admin login must not gain any
new required step.
- **Backward compatibility:** total, if done as an additive claim. A
session with no seller claim today is indistinguishable from a session
before this work existed.
- **Risk:** **Medium** — auth is the most consequence-sensitive surface in
the app (ADR-010 froze it once already); any change here needs
security review, not just a schema add.
- **Effort:** Medium (claim/role addition) once the role-vs-`AdminRole`
reconciliation decision (§11.4) is made; that decision itself is the
bigger unknown, not the wiring.
- **Endpoint classification:** existing login/verify/refresh/logout —
**Minor change** (optional claim), contingent on the role decision above.
New seller-specific login/enrollment flow (if Seller/Seller Staff need
one) — **New endpoint**, Future, not designed.
### Authorization
- **Current:** Coarse `AdminRole` (Owner/Manager/Support/ReadOnly) mapped
to `backoffice.read`/`backoffice.write`/`builder.read`/`builder.write`/
`settings.manage` (§4 §9.1). No route currently enforces even this — the
admin role model exists but nothing gates on it yet (confirmed by the
Backoffice audit: "no admin module anywhere does role-based hiding of
buttons or data today").
- **Future:** `SellerPermissionRole` layered in, deciding whether it
extends or sits alongside `AdminRole`.
- **Migration strategy:** since authorization enforcement doesn't exist yet
even for the current roles, there is no existing enforcement to break —
this is genuinely additive design space, not a migration of live
behavior.
- **Backward compatibility:** trivial today (nothing to preserve because
nothing enforces roles yet) but becomes a real compatibility question the
moment `AdminRole` enforcement is eventually added — sequence matters:
whichever role model ships first should be designed with the other in
mind, or the second one becomes a breaking migration of the first.
- **Risk:** **Low today, Medium if sequenced wrong** — the risk is entirely
about doing `AdminRole` enforcement and `SellerPermissionRole` design in
the wrong order, not about either individually.
- **Effort:** Low to design (no live behavior to preserve); Medium to
implement once both role systems' relationship is decided.
- **Endpoint classification:** all admin endpoints — **No change** today
(no enforcement exists to change); **Major change** whenever
role-enforcement is added generally, seller-aware or not.
### Bootstrap
- **Current:** `GET /bootstrap`, backend resolves tenant by Host (ADR-001,
§1). `BootstrapConfig` already has optional `modules?`/`seller?` fields
(§11.6), always absent/false — no backend populates them.
- **Future:** backend resolving `{seller}.{marketplace-domain}` (§11.5) and
populating `modules.sellerManagement.enabled` + `seller` for a real
seller-scoped request.
- **Migration strategy:** the fields already exist and are optional — the
only backend work is *populating* them correctly for a resolved seller
scope, not adding new frontend-facing shape. Existing marketplaces'
bootstrap responses need zero changes; they simply never populate the
new fields.
- **Backward compatibility:** already verified — these are optional fields
added to a live contract with zero consumer changes required (confirmed
`tsc --noEmit` clean at the time they were added).
- **Risk:** **Low** — this is the best-prepared module in the whole
migration, precisely because the frontend contract was already extended
in advance without needing backend cooperation.
- **Effort:** Medium — the resolution logic (subdomain → seller lookup) is
new backend work, but the response shape is already spoken for.
- **Endpoint classification:** `GET /bootstrap`**Minor change** (two new
optional response fields to populate, conditionally).
### Products
- **Current:** No real backend yet (§8) — mock gateway. `AdminProductListFilters`
already has `search/categoryId/visibility/stock/includeArchived/sort/page/pageSize`.
`Item`/`AdminProduct` already carry optional `sellerId?` (§11.8),
read/written by nobody today.
- **Future:** `sellerId` filter on list endpoints; ownership enforcement on
create/update/delete once a real seller session exists.
- **Migration strategy:** add `sellerId` as one more optional field to the
existing filters object and DTOs — the field already exists in the
frontend type, so there's no frontend change required at all, only
backend query logic (`WHERE seller_id = ? OR seller_id IS NULL` pattern
or equivalent) gated behind the feature flag.
- **Backward compatibility:** guaranteed at the frontend type level
already; backend guarantee depends on making the new column/filter
nullable and defaulting existing rows to `NULL` (marketplace-owned) —
see Database changes below.
- **Risk:** **Low** for the filter addition; **Medium** for ownership
*enforcement* (a bug here could hide a marketplace owner's own products
from themselves, or leak a seller's products to another seller).
- **Effort:** Small (list/filter) once the DI-token seam this domain
currently lacks (per Backoffice audit) is added — that seam is
independent prerequisite work, not seller-specific.
- **Endpoint classification:** list/get — **Minor change**. Create/update
(ownership assignment) — **Minor change** if `sellerId` is just an
optional write field; **Major change** if ownership transfer or
seller-side write restrictions are added.
### Categories
- **Current:** The most backend-mature domain — real HTTP already
(`AdminCategoriesApiGateway`, DI-token-bound, §3.2). Facade currently
hardcodes a full unfiltered fetch and does all real filtering
client-side to preserve tree parent/child chains (Backoffice audit
finding).
- **Future:** categories are conceptually marketplace-wide (shared
taxonomy) — the real future question is scoping *products within* a
category by seller, not scoping categories themselves.
- **Migration strategy:** likely **no backend change at all** for
Categories proper; ownership scoping happens one level down, at Products.
- **Backward compatibility:** trivial — no change anticipated.
- **Risk:** **Low.**
- **Effort:** Low (frontend-only fix: the facade's hardcoded full-fetch
pattern, unrelated to backend).
- **Endpoint classification:** **No change** anticipated.
### Orders
- **Current:** `AdminOrderListFilters` has `search/status/page/pageSize`;
`AdminOrder` has optional `sellerId?` (§11.8) at the order level.
`AdminOrderItem` (per-line-item) has **no seller attribution field at
all** — the concrete gap behind Checkout Modes (§11.7).
- **Future:** per-item seller attribution, plus the Unified-vs-Split-Orders
decision (§11.7) — the single most consequential undecided item in this
entire plan.
- **Migration strategy:** cannot be resolved by an additive field alone.
**Unified Order** path: add optional `sellerId` to each order-item row
(minor, additive). **Split Orders** path: checkout must decide, at
creation time, whether to write N order records instead of one for a
multi-seller cart — that changes `POST /orders`' semantics for any cart
containing mixed-seller items, which is a **major** change regardless of
how carefully it's gated, because "how many order records does this
checkout produce" is not optional-field-shaped.
- **Backward compatibility:** guaranteed for any cart containing only
marketplace-owned items (the only kind that exists today) under either
path. The compatibility risk is entirely about *new* multi-seller carts,
which cannot exist until Products have real seller ownership — so there
is a natural sequencing safety net here, not just a promise.
- **Risk:** **High** — this is the highest-risk item in the whole plan.
Payments, refunds, and financial reporting all depend on the
Unified-vs-Split decision; getting it wrong after sellers exist means a
breaking change to live financial data, not a code refactor.
- **Effort:** Large — this decision should be made and locked before any
seller onboarding is possible, not discovered mid-rollout.
- **Endpoint classification:** `GET /orders` (list/filter) — **Minor
change**. `POST /orders` (create) — **Major change** (semantics change
based on the Unified/Split decision). `PATCH` status transitions — likely
**Minor change** if orders stay 1:1 with a single seller scope (Split
path) or **Major change** if partial per-seller status exists within one
unified order.
### Payments
- **Current:** **Frozen** (ADR-010) — Telegram QR/card payment flow,
`POST /cart` (`CartPaymentRequest``QrCreateResponse`), status polling.
Explicitly preserved unchanged through every prior platform-refactoring
pass in this codebase's history.
- **Future:** if Split Orders is chosen (§ Orders above), a single checkout
may need to create multiple payment records or split a captured payment
across sellers — a genuinely new payment-flow shape, not a parameter
addition.
- **Migration strategy:** **do not touch the frozen flow for the Unified
Order path** — a unified order with mixed-seller items can still use
today's exact single-payment flow, only the *order* record differs
internally. Only the Split Orders path forces any payment-flow change,
and even then, the existing flow should remain the path for
seller-disabled marketplaces with zero exceptions.
- **Backward compatibility:** absolute requirement, restated from ADR-010 —
this is the one area of the whole codebase with an explicit prior
"freeze, do not redesign" decision, and Seller Management does not
override it.
- **Risk:** **High** if Split Orders is chosen — payment/financial flows
are the least forgiving place for a design misstep in this entire system.
- **Effort:** Large, only if Split Orders is chosen; **zero** for Unified
Order.
- **Endpoint classification:** **No change** under Unified Order. **Major
change or New endpoint** under Split Orders (undecided, Future).
### Transactions
- **Current:** Derived entirely from the same unscoped Orders list
(`AdminTransactionsLocalGateway` mirrors `AdminOrdersLocalGateway`'s
pattern, Backoffice audit finding). `AdminTransactionListFilters` has
`search/status/type/page/pageSize`.
- **Future:** per-seller transaction filtering/reporting.
- **Migration strategy:** inherits whatever Orders decides — Transactions
cannot be scoped correctly until Orders resolves per-item seller
attribution (§ Orders above). Adding a `sellerId` filter here today would
be cosmetic without that prerequisite.
- **Backward compatibility:** same guarantee as Orders — blocked on the
same prerequisite, not an independent risk.
- **Risk:** **Medium** — inherits Orders' risk one level removed (financial
reporting, not the payment flow itself).
- **Effort:** Small once Orders is resolved; not independently schedulable
before that.
- **Endpoint classification:** **Minor change** (filter field), contingent
on Orders' Major change landing first.
### Reviews
- **Current:** Storefront submission is live; admin moderation
(`AdminModerationGateway`) is mock-only. `AdminReviewListFilters` has
`search/status/rating/page/pageSize`. Reviews carry `productId` — no
direct seller field.
- **Future:** a seller sees reviews on their own products, via a join
through Products' `sellerId`, not a new field on the review itself.
- **Migration strategy:** add `sellerId` as a filter that internally joins
through the product's ownership — additive at the API surface, but
implemented as a join, not a stored column on reviews.
- **Backward compatibility:** total — the filter is purely additive and
optional.
- **Risk:** **Low.**
- **Effort:** Small, contingent on Products having real `sellerId` data to
join against.
- **Endpoint classification:** review list/detail — **Minor change**.
Reports (`loadReports()`, currently bare no-arg, no filters object at
all) — **Minor change** too, but requires adding a filters parameter
that doesn't exist on the endpoint today, so slightly more surface than
the reviews list.
### Analytics
- **Current:** No aggregation endpoint exists at all (§3.20) — every
number (revenue, top products, health, recommendations) is computed
client-side by summing the *entire* orders/products/categories/reviews
corpus. This gap exists independent of Seller Management.
- **Future:** per-seller analytics, requiring the underlying domains
(Orders, Products, Reviews) to be seller-scoped first, then a real
aggregation endpoint partitioned by seller.
- **Migration strategy:** do not attempt to seller-scope analytics before
a real aggregation endpoint exists for the marketplace as a whole — that
is a prerequisite gap, not a Seller Management task. Once it exists,
seller-partitioning is an additional dimension on the same aggregation
query, not a new endpoint family.
- **Backward compatibility:** unaffected — a marketplace with no sellers
gets marketplace-wide aggregates exactly as it always has, whenever the
real aggregation endpoint is eventually built.
- **Risk:** **Medium** — mostly the risk of building the wrong aggregation
shape before seller-partitioning is even a consideration, and having to
redo it.
- **Effort:** Large — this is explicitly the last domain recommended for
real backend work in `BACKEND.md` §9, and Seller Management adds a
further dimension on top of an already-large lift.
- **Endpoint classification:** **New endpoint** (the aggregation endpoint
itself doesn't exist yet, seller-aware or not).
### Media
- **Current:** `MediaRepository` abstract class, DI-token-bound already
(mock live, `ApiMediaRepository` not yet written). `MediaListParams`
already accepts `page/pageSize/search/folder/kind/sort`. `MediaAsset` has
no owner/uploader field at all.
- **Future:** `sellerId` filter, requiring an owner field added to
`MediaAsset` first.
- **Migration strategy:** two small additive changes — a new optional
`sellerId`/`ownerId` field on the asset model, and a matching optional
filter field on `MediaListParams`. This module and Categories are the
two best-positioned in the entire audit for a low-risk addition.
- **Backward compatibility:** total — both changes are optional-field
additions to an already-flexible params object.
- **Risk:** **Low.**
- **Effort:** Small.
- **Endpoint classification:** list — **Minor change**. Upload/update
(§7) — **Minor change** (one new optional field in the request body).
### Search
- **Current:** Standard search contract exists (§2.5) as a framework
convention (keyword, no dedicated backend endpoint beyond catalog list
filtering — `/search` reuses the same catalog container/endpoint as
`/catalog` per the Storefront audit). No autocomplete/trending endpoint
exists; explicitly flagged as its own open "Requires backend decision"
in §2.12.
- **Future:** filtering search results by seller scope, same mechanism as
Products (search is not architecturally distinct from catalog browsing
today).
- **Migration strategy:** inherits Products' migration entirely — no
separate search-specific backend work anticipated beyond what Products
already needs.
- **Backward compatibility:** total, same guarantee as Products.
- **Risk:** **Low.**
- **Effort:** None beyond Products — not independently schedulable.
- **Endpoint classification:** **Minor change**, identical to Products'
classification (same underlying endpoint).
### CMS (Static Pages)
- **Current:** No backend call at all — reads/writes
`BootstrapConfig.staticPages` in-memory (§1, §3.8). Marketplace-wide
content (legal, about) by nature.
- **Future:** **conceptually does not apply** — no per-seller static page
concept exists in this document or in product intent. If sellers ever
need their own content pages, that is new product surface, not an
extension of this module.
- **Migration strategy:** none anticipated. Flag if product strategy later
decides otherwise — treat as a new capability, not a CMS migration.
- **Backward compatibility:** unaffected — no change proposed.
- **Risk:** **None.**
- **Effort:** **None.**
- **Endpoint classification:** **No change.**
### Builder
- **Current:** No backend write path at all (§1.10, §8) — draft/publish is
`localStorage`-only, editing one global `BootstrapConfig` document per
marketplace. The single strongest one-owner assumption in the codebase
(Backoffice audit finding).
- **Future:** a seller-scoped builder (per-seller storefront layout/
branding) would be an entirely new product surface built on a different
premise than "one config document per marketplace" — not an extension of
the existing builder.
- **Migration strategy:** none proposed for the existing Builder. If a
seller-facing builder is ever wanted, it should be scoped as its own ADR
and its own backend surface, not bolted onto the marketplace Builder's
existing draft/publish contract.
- **Backward compatibility:** unaffected — no change proposed to the
existing module.
- **Risk:** **None** for the existing module; **High** if a future team
attempts to retrofit seller-awareness into the existing single-document
model rather than building fresh — flagged explicitly as an
anti-pattern to avoid.
- **Effort:** **None** now; a seller-facing builder, if ever built, is a
large, independent effort, not a migration of this one.
- **Endpoint classification:** **No change** to the existing (still
nonexistent) builder write path. Any future seller-builder surface is
**New endpoint**, Future, not designed.
### Settings
- **Current:** No route exists — `comingSoon: true` in the admin nav, no
component backs it (confirmed, Backoffice audit).
- **Future:** if Settings is ever built, it's the natural home for
marketplace-level Seller Management configuration (e.g. enabling the
module, default seller policies) — speculative, not designed.
- **Migration strategy:** none — there's nothing to migrate.
- **Backward compatibility:** not applicable.
- **Risk:** **None.**
- **Effort:** **None** attributable to Seller Management specifically.
- **Endpoint classification:** **No change** — no endpoint exists.
### Notifications
- **Current:** A marketplace-facing feature flag exists
(`FeatureFlagsConfig.notifications: boolean`) but this gates a storefront
UI feature, not a backend notification/email service — no such service
exists in this codebase for anyone today.
- **Future:** seller onboarding (invitation accepted, application
approved/rejected) would need real notification delivery — entirely
net-new, not an extension of the existing flag.
- **Migration strategy:** none — nothing exists to migrate.
- **Backward compatibility:** not applicable.
- **Risk:** **Low** (net-new work carries normal build risk, not migration
risk).
- **Effort:** Medium, whenever built — but zero today and not a
prerequisite for anything else in this plan.
- **Endpoint classification:** **New endpoint**, Future, not designed.
### Emails
- **Current:** No email-sending capability exists anywhere in this
codebase.
- **Future:** the mocked "Request Access" form on the Phase 1 UI
(`admin-seller-management-page.component.ts`) implies a real email would
eventually be sent on submission — today it's a `setTimeout`-mocked
success dialog with zero delivery.
- **Migration strategy:** none — nothing exists to migrate.
- **Backward compatibility:** not applicable.
- **Risk:** **Low** (net-new, not migration).
- **Effort:** Small to Medium, whenever built (transactional email for one
form submission is a contained scope).
- **Endpoint classification:** **New endpoint**, Future, not designed.
### Audit Logs
- **Current:** Documented in `BACKEND.md` §5.14 as a proposed convention
(structured audit-log entries with actor/action/target/timestamp) — no
backend implementation confirmed to exist; this is itself already
Planned/Future in the base backend doc, independent of Seller
Management.
- **Future:** any seller-specific action (seller created, activated,
suspended, branding changed) should flow through the same audit-log
convention once it exists, with an added seller-scope dimension on the
log entry — not a parallel logging system.
- **Migration strategy:** none specific to Seller Management beyond
ensuring, whenever audit logging is built, that its schema includes an
optional seller-scope field from day one rather than retrofitting it
later.
- **Backward compatibility:** not applicable — nothing exists yet to
preserve.
- **Risk:** **Low.**
- **Effort:** None additional if sequenced correctly (add the field when
audit logging is first built); Medium if audit logging ships first
without it and needs a schema migration later.
- **Endpoint classification:** **New endpoint** (audit log query surface,
if one is ever exposed to admins) — Future, not designed.
## Database changes
No schema exists yet for any of this (§8 — no backend implemented at all).
Recommendations, not decisions:
- A `sellers` table (id, marketplace_id, name, slug, status, branding
JSON/columns, timestamps) — new table, no impact on existing schema.
- A nullable `seller_id` foreign key on `products`/`items` and `orders` (or
order-items, pending the Unified/Split decision) — nullable by
design, defaulting existing rows to `NULL` (marketplace-owned). This is
the one schema change that touches existing tables; every other addition
is a new table.
- A nullable `seller_id`/`owner_id` on the media-assets table, if Media
ownership scoping is pursued.
- No column should ever be added as `NOT NULL` without a default — that
would force a backfill migration on existing data, which this plan's
constraint explicitly rules out.
## Permission changes
- New `sellers` and `seller_users` (or equivalent) authorization checks —
entirely new policy, not a modification of existing `AdminRole` checks
(which, per the Backoffice audit, don't enforce anything yet regardless).
- Existing admin/customer authorization paths: **no change** required for
marketplaces with `modules.sellerManagement.enabled = false`.
- Recommendation: implement seller-scoped authorization as an additional
policy layer evaluated only when a request resolves to a seller scope
(§11.5) — never as a modification of the existing marketplace-level
policy evaluation path.
## Caching
- Bootstrap responses are already cached client-side per tenant (§1.7); a
seller-scoped bootstrap response should be cached under a cache key that
includes the resolved seller identity (e.g. keyed by full resolved Host,
which it already effectively is), not the marketplace alone — otherwise
a seller subdomain risks serving a cached marketplace-level response or
vice versa.
- No existing cache invalidation logic needs to change for marketplaces
without sellers.
## Indexes
- `sellers(marketplace_id)` — every seller lookup is scoped by marketplace.
- `products(seller_id)` / `orders(seller_id)` (or order-items equivalent)
— nullable-column indexes; most databases index `NULL` efficiently, but
this should be verified against the chosen database engine before
assuming query performance is unaffected for the common (`NULL`) case.
- No index changes required on any table for marketplaces that never
populate `seller_id`.
## Security
- Seller-scoped data access is a new cross-tenant-adjacent boundary (a
seller must never see another seller's data within the same
marketplace) — recommend treating this with the same rigor as tenant
isolation (§5.10/§4 §10), not as a lesser internal boundary.
- The existing frozen payment flow (ADR-010) must not be reopened for the
Unified Order path — only the Split Orders path (if chosen) touches
payment security surface at all, and that touch should get the same
security review rigor as the original payment implementation.
## Performance
- Analytics is already the heaviest computation path in the app (full
client-side aggregation over the entire corpus, §3.20) — building the
real aggregation endpoint this plan's Analytics section calls for should
happen with seller-partitioning in mind from the start, to avoid a
second heavy migration shortly after the first.
- No performance regression is anticipated for marketplaces without
sellers — every proposed change is either a new table/endpoint (zero
cost when unused) or a nullable-field filter (negligible cost when the
filter is never applied).
## API Versioning
Already documented as an open, undecided item in `BACKEND.md` §2.10 (no
path/header versioning scheme exists today). Recommendation specific to
this migration: whichever versioning decision is made generally should
land **before** any Seller Management endpoint ships, so new endpoints
(Seller CRUD, Activation, Invitations, Branding, Analytics, Dashboard) are
versioned consistently with the rest of the API from their first day,
rather than being retrofitted later as the one inconsistent set.
## Migration order
Strict dependency order, not a preference:
1. **Bootstrap** (already prepared, lowest risk) — backend starts
populating `modules`/`seller` fields for a resolved seller scope.
2. **Products**`seller_id` column + filter, the foundation every
downstream domain depends on.
3. **Categories** — confirm no change needed (likely true, low effort to
verify).
4. **Media** — independent, can happen in parallel with Products.
5. **Reviews** — depends on Products (join through product ownership).
6. **Orders** — the Unified-vs-Split-Orders decision must be made here,
informed by Products already existing. This is the hard gate — nothing
past this point should start before it's resolved.
7. **Payments** — only touched if Split Orders is chosen; otherwise
untouched, in parallel with everything above.
8. **Transactions** — depends on Orders.
9. **Analytics** — depends on Orders, Products, Reviews all being scoped;
also depends on the pre-existing (non-seller-specific) real aggregation
endpoint being built first.
10. **Authentication/Authorization** — the `SellerPermissionRole` design
and its relationship to `AdminRole` should be settled in parallel with
steps 2-6, not deferred to the end, since Seller Activation and any
real seller-facing endpoint depend on it.
11. **Seller CRUD/Activation/Invitations/Branding** — depends on
Authentication/Authorization being settled.
12. **Seller Dashboard/Analytics endpoints** — last, depends on Analytics'
real aggregation endpoint existing.
13. **Notifications/Emails/Audit Logs** — can start any time after step 11
(Seller Invitations existing gives them something to notify about);
not blocking anything else.
14. **CMS, Builder, Settings** — no migration anticipated; revisit only if
product strategy changes.
## Recommended implementation phases
- **Phase A — Foundation** (steps 1-4, 10 above): bootstrap population,
Products/Categories/Media scoping, and the permission-role design done
in parallel. Nothing customer-visible yet. Lowest risk, unblocks
everything else.
- **Phase B — The hard decision** (step 6, Orders): Unified-vs-Split-Orders
locked before any real seller can transact. This phase is a design
decision plus its implementation, not a feature — treat it as a gate,
not a sprint item.
- **Phase C — Dependent domains** (steps 5, 7, 8): Reviews, Payments (if
Split chosen), Transactions — mechanical once Phase B lands.
- **Phase D — Seller-facing surface** (step 11): Seller CRUD, Activation,
Invitations, Branding — the first point where a seller account can
actually exist and do something.
- **Phase E — Analytics & reporting** (steps 9, 12): the largest single
remaining lift, deliberately last since it depends on everything above.
- **Phase F — Operational polish** (step 13): Notifications, Emails, Audit
Logs — improves the experience of Phase D/E but blocks nothing.
At every phase boundary: re-verify the non-negotiable constraint. A
marketplace with `modules.sellerManagement.enabled = false` must show zero
behavioral difference before and after each phase ships. If a phase can't
satisfy that, it isn't ready to ship — regardless of how much of it is
"done."