feat(sellers): typed domain models for future Seller Management - no logic, no API, no auth changes

Typed models only, per mission. Nothing outside the new files reads
or writes any of this yet.

New core/sellers/models/ (mirrors core/products/models,
core/auth/models convention):
- MarketplaceRef - minimal {id,slug,name} reference from a seller
  back to its marketplace, distinct from bootstrap's TenantConfig.
- SellerStatus - 'pending'|'active'|'suspended'|'disabled', no
  transition logic.
- SellerScope - {sellerId, marketplaceId}, domain-level counterpart
  to BootstrapConfig.seller (SellerConfig from the ADR-011 pass).
- SellerBranding (+SellerContact/SellerAddress/SellerThemeOverrides)
  - logo/banner/description/contacts/address/theme overrides, every
    field optional. Marketplace branding/theme remain default;
    nothing consumes this yet.
- SellerPermissionRole/SellerPermissions - marketplaceOwner/seller/
  sellerStaff/platformAdmin. Separate vocabulary from the existing
  AdminRole (core/auth/models/permission.model.ts) - not merged, not
  wired into any guard, zero auth behavior change.
- Seller - the eventual entity, composed from the above.

Changed (optional-only, verified backward compatible):
- Item (models/item.model.ts) gained sellerId?: string
- AdminProduct (features/admin/products/models/) gained
  sellerId?: string
- AdminOrder (features/admin/orders/models/) gained sellerId?: string

Absent means marketplace-owned in every case, exactly like every
existing product/order today. No consumer of any of these three
models needed updating. AdminOrderItem (per-line-item ownership) and
the existing PermissionsConfig/AdminRole system were deliberately not
touched - out of scope for this pass.

Added docs/architecture/foundation/Seller-Management-Domain-Models.md
documenting every new type, every changed field, and the explicit
non-goals list. Linked from the foundation README alongside ADR-011
and the diagrams doc.

tsc --noEmit clean, arch:check (boundaries + cycles) clean.
This commit is contained in:
sdarbinyan
2026-07-26 21:55:11 +04:00
parent 20442eb93c
commit 86091a4742
12 changed files with 199 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
# Seller Management — Domain Models (Preparation)
Companion to [ADR-011](adr/ADR-011-optional-seller-management-module.md) and
[Seller-Management-Diagrams.md](Seller-Management-Diagrams.md). This document
covers the second preparation pass: typed domain models for a future Seller
entity, and optional seller-ownership fields on existing Product/Order
models. **Typed models only — no repository, gateway, facade, CRUD, API, or
authentication/authorization change exists as a result of this work.**
## New: `core/sellers/models/`
A new domain model group, mirroring the existing `core/products/models/`,
`core/auth/models/` convention. Nothing outside this directory imports from
it yet — these types exist for future work to build against.
| Type | File | Purpose |
|---|---|---|
| `MarketplaceRef` | `marketplace-ref.model.ts` | Minimal `{id, slug, name}` reference from a seller record back to its owning marketplace. Not a replacement for `TenantConfig` (bootstrap's runtime tenant contract, ADR-001) — just enough to say which marketplace a seller belongs to. |
| `SellerStatus` | `seller-status.model.ts` | Lifecycle vocabulary: `'pending' \| 'active' \| 'suspended' \| 'disabled'`. No transition logic. |
| `SellerScope` | `seller-scope.model.ts` | `{sellerId, marketplaceId}` — the domain-level counterpart to `BootstrapConfig.seller` (`SellerConfig`). Backend-resolved only, same rule as tenant resolution (ADR-001, ADR-011). |
| `SellerBranding` (+ `SellerContact`, `SellerAddress`, `SellerThemeOverrides`) | `seller-branding.model.ts` | Logo, banner, description, contacts, address, theme overrides — **all fields optional**. Absent means marketplace branding/theme applies, unchanged (`BrandingConfig`/`ThemeConfig`). Nothing consumes this yet. |
| `SellerPermissionRole`, `SellerPermissions` | `seller-permissions.model.ts` | Four future roles: `marketplaceOwner`, `seller`, `sellerStaff`, `platformAdmin`. **A separate vocabulary from the existing `AdminRole`** (Owner/Manager/Support/ReadOnly, `core/auth/models/permission.model.ts`) — not merged, not wired into any guard, no auth behavior change. |
| `Seller` | `seller.model.ts` | The eventual entity: `id`, `marketplace: MarketplaceRef`, `name`, `slug`, `status: SellerStatus`, optional `branding: SellerBranding`, `createdAt`/`updatedAt`. |
All exported via `core/sellers/models/index.ts`.
## Changed: optional seller ownership on existing entities
Three existing entities gained one new **optional** field each. In every
case: absent = marketplace-owned (today's only reality for every existing
product/order), nothing reads the field yet, no consumer needed updating,
`tsc`/`arch:check` both verified clean after the change.
| Entity | File | Field added |
|---|---|---|
| `Item` (storefront product) | `models/item.model.ts` | `sellerId?: string` |
| `AdminProduct` (admin product editor) | `features/admin/products/models/admin-product.model.ts` | `sellerId?: string` |
| `AdminOrder` (admin order editor) | `features/admin/orders/models/admin-order.model.ts` | `sellerId?: string` |
Deliberately **not** touched: `AdminOrderItem` (per-line-item seller
ownership is a finer-grained decision than this preparation pass covers —
order-level `sellerId` is enough for now), and both existing bootstrap
`PermissionsConfig`/`AdminRole` (no authentication change, per mission).
## Non-goals (explicitly out of scope)
- No repository, gateway, facade, or API call reads or writes `sellerId`,
`Seller`, or any type in this document.
- No route, guard, or UI surfaces any of this.
- No change to `AdminRole`, `ROLE_PERMISSIONS`, or any existing
authentication/authorization code path.
- No change to marketplace branding/theme defaults or precedence — a
marketplace with no sellers, or a seller with no branding overrides,
behaves exactly as today.
## What this unblocks later
Once Seller Management is actually implemented (its own ADR/implementation
pass, per ADR-011 §"Scope of this ADR"): a `SellerRepository`/`SellerGateway`
can return `Seller` objects instead of inventing a shape; product/order
CRUD can start populating `sellerId` without a breaking schema change;
permission guards can consume `SellerPermissionRole` once a real role system
decision is made; branding resolution can check `Seller.branding` before
falling back to marketplace `BrandingConfig`/`ThemeConfig`.