Files
marketplaces/docs/PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md
sdarbinyan 3c72c37e31 docs: v3.1 gap analysis + delivery plan; add DI seams to 9 admin gateways
Adds InjectionToken + factory for Orders, Products, Users, Transactions,
Monitoring, Moderation (mirrors existing Categories/Dashboard pattern) and
repoints their facades plus the derived Analytics/Customers facades and
admin-order-watcher off the mock LocalGateway class directly. No behavior
change today - still resolves to the mock - but a real backend can now be
bound per domain with zero facade edits.

Docs: full gap analysis of Product Plan v3.1 against current repo state,
and a phased delivery plan (10 phases, 34 sprints, 5 tracks) breaking every
identified gap into scoped, sequenced work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 21:24:57 +04:00

33 KiB
Raw Blame History

Product Plan v3.1 — Delivery Plan (Phases → Sprints → Todos)

Companion to PRODUCT-PLAN-v3.1-GAP-ANALYSIS.md. Every gap identified there is assigned here exactly once.

No calendar dates. The plan itself (§12) refuses invented dates and fixes sequence + exit criteria instead. This document does the same. Sprints are ordered units of work, not two-week promises. Sizes are relative: S / M / L / XL.

Ownership tags: [FE] this repo · [BE] backend/platform service · [BOTH] coordinated contract change · [DEC] decision, no code.

Deviation from the plan's own order, and why: the plan sequences P0-C (external ingestion) before P0-D (catalog integrity). We swap them. External order ingestion maps externalSKU → internal offer (§5.1), and Offer does not exist yet — ingestion has nothing to map onto until the Product/Offer split ships. Everything else follows the plan's ordering.


Phase map

Phase Name Plan ref Gate
0 Unblock & seams Decisions answered; every admin domain swappable
1 Money & payment truth P0-A, §2.3 §3.3 §3.8 §7 An order total is explainable from data
2 Orders canonical + notifications P0-B, §2.8 §2.10 §3.5 Paid order appears and notifies without refresh
3 Catalog integrity + fulfillment P0-D, §2.1 §2.4 §3.6 Any published offer is genuinely buyable and fulfillable
4 External order ingestion P0-C, §5 §3.7 External purchase lands in Orders, no duplicates
🚦 PRODUCTION LAUNCH GATE §3 LAUNCH BLOCKERS, §13.2 All P0 closed and evidenced
5 Seller Portal P1-A, §2.2 Seller runs own offers and orders in scoped UI
6 Server cart + checkout session P1-B, §2.5 §2.6 Client price never trusted; repeat-safe
7 Payments hardening + reconciliation P1-C, §2.7 §7.3 Internal vs provider matched, mismatches visible
8 Identity & messaging §2.9 §3.4 §14 VK/MAX/Telegram linked; bot collects delivery
9 Tenant registry, domains, releases P2-A, §4.3 §8 New marketplace launched with no hardcode
10 Tenant content modules (Gorbushka) P2-B, §11 Content tenant on same runtime/backoffice

Parallel tracks (start early, run across phases): A Analytics pipeline · S Security/RBAC/audit · Q QA & E2E · N API namespace migration · Z Pre-existing repo debt.


Phase 0 — Unblock & seams

Nothing downstream can be honestly estimated until this closes. Two sprints: one is other people answering questions, one is work we can do today with no answers.

Sprint 0.1 — Decisions [DEC]

Blocking. Escalate as a single list, not one at a time.

  • Backend ownership. Platform API, Workers, Integration Hub, Domain Automation — our team or a service team? Everything [BE] below is unassigned until answered.
  • Unfreeze the payment chain. BACKEND-API-REFERENCE.md §7 marks it do-not-modify. Phases 1, 6 and 7 are unbuildable otherwise.
  • Name the external marketplaces for §5 connectors (Ozon / Wildberries / Yandex Market / Avito / other). Each is a separate connector; Phase 4 cannot be sized without the list.
  • FX rate source — which provider, and does the backend return converted prices or serve rates? Plan §2.3 implies backend-converted.
  • §14 vs. approved email/phone OTP spec — VK ID first, or finish OTP first?
  • Multi-seller orders: unified or split? Open in three of our own documents. Blocks Phase 3 and Phase 5 data model.
  • Reproduce or retract the "fixed 5-second payment" claim (§3.2). Not present in this codebase.
  • API namespace migration (§9.3) — migrate before new endpoints, or accept two conventions? Cost rises every phase this is deferred.
  • Document version — file says v3.1, version block says 3.0. Which is canonical?

Exit: all nine answered in writing.

Sprint 0.2 — Seams and type reconciliation [FE] — runs regardless of answers

  • Add DI tokens to the 9 admin domains that have none: Orders, Products, Users, Transactions, Monitoring, Moderation (+ derived Customers, Analytics). M — hard prerequisite for every [BE] swap in Phases 17.
  • Reconcile AdminRole — defined twice with unrelated shapes (auth string-union vs. Users-page display interface). S
  • Reconcile the two Category types, both fed by the same /category response, both in use. S
  • Resolve SellerConfig (bootstrap) vs. Seller/SellerBranding (domain) — pick one or document the mapping. Blocks Phase 5. S
  • Build the feature-flag / capability-guard service an existing ADR already promises; migrate the hand-rolled sellerManagement.enabled check onto it. S
  • Build the centralized error-handling layer (core/error-handling/, core/interceptors/ are .gitkeep-only today): error-envelope interceptor + 429 handling. M [BOTH] — envelope shape needs backend agreement.
  • Fix toAuthErrorShape() to read a body-level code, not HTTP status alone — the built "session expired" / "invalid signature" screens are currently dead UI. S
  • Bind mock implementations to PRODUCT_DATA_PROVIDER and CATEGORY_REPOSITORY, or delete the dead mock branch. Today both silently ignore useMockData. S

Exit: any admin domain can be pointed at a real backend by swapping one provider.


Phase 1 — Money & payment truth (P0-A)

Closes §3.3 and §3.8, and half of the §13.1 acceptance table. The single highest-value phase: it is what makes totals explainable to a bank.

Sprint 1.1 — Money model [BOTH]

  • Money = { amountMinor: int, currency } end to end. Kill float arithmetic in CurrencyRatesService.convert(). L
  • Currency minor-units + rounding rules table (RUB/USD/EUR/AMD at minimum). M
  • Delete browser-owned rates: remove currencyRates.v1 from localStorage and the hardcoded DEFAULT_RATES fallbacks (USD: 0.011, AMD: 4.3). S
  • Remove the admin-typed rate editor from Admin Settings once a real source exists. S

Sprint 1.2 — FX quote + rate source [BE] + [FE]

  • FxQuote { base, quote, rate, source, observedAt, expiresAt, quoteId } entity + endpoint. M
  • Rate-source adapter behind an interface; concrete provider pluggable (§7.1). M
  • Stale/outlier quote rules; checkout blocks or uses an explicitly configured fallback. M
  • PriceBook: offer base currency + allowed display/checkout currencies per tenant. M

Sprint 1.3 — Price snapshot + server-authoritative amount [BOTH] — needs the freeze lifted

  • PriceSnapshot { offerId, amount, currency, fxQuoteId, capturedAt }, immutable. L
  • Server computes and validates the charged amount. Stop trusting CartPaymentRequest.amount and the per-item price[] array from the browser. L — the plan's §2.5 headline requirement.
  • Old orders never recalculated when a rate updates. S
  • Backoffice "total formula" panel: lines × qty discounts + delivery + fees, plus the FX quote used (§7.2). M
  • PriceHistory on offer price and stock, with author/source (§2.1). M

Sprint 1.4 — Payment timeline [BE] + [FE]

  • Explicit state machines: PaymentIntent (created→pending→authorized/paid→failed/cancelled), Payment (received→confirmed→captured/settled→refunded), Order (pending_payment→paid→processing→fulfilled). L
  • Persist provider event id, provider timestamp, receivedAt, processedAt per transition. M
  • Webhook entrypoint with signature verification + idempotency (§2.7). L
  • Idempotency keys on checkout, payment and order creation. Zero idempot* exists today. M
  • Replace client-polled status signals with server truth; keep polling only as a UI fallback. M
  • Keep the current honest behaviour: no artificial delay. Already compliant — protect it with a test. S

Exit criteria (plan's own): currency converts correctly; payment timeline reconstructable from provider events; every total explainable from SKU/qty/delivery/discount/FX.


Phase 2 — Orders canonical + notifications (P0-B)

Sprint 2.1 — Canonical order model [BOTH]

  • Order header: marketplaceId, source, customer, currency, subtotal, discounts, delivery, total, paymentStatus, orderStatus. L
  • OrderLine with offerId, sellerId, skuSnapshot, titleSnapshot, qty, unitPriceMinor, lineTotalMinor, priceSnapshotId. M
  • OrderEvent timeline: created, paid, seller notified, accepted, fulfilled, cancelled, refunded (§2.8). Closes our own "Real order audit trail" TODO. M
  • Real AdminOrdersApiGateway replacing the 24-row static seed with no create path. L [BE]
  • Admin order actions: assign, resend notification, replay sync, cancel/refund by permission, comment, export. M
  • OrderContactSnapshot — name/contacts frozen at order time, immune to later profile edits (§2.9). S

Sprint 2.2 — Event bus + Notification Center [BE] + [FE]

  • Platform event bus emitting order.created, order.paid, payment.failed, webhook.error, stock.low, oversell, refund.requested/completed, external_order.imported. L
  • Notification entity: unread/read, severity, marketplaceId, entity type/id, deep link. M
  • DeliveryAttempt log per external channel — a Telegram/email failure must never lose the internal notification (§2.10). M
  • Backoffice Notifications section: unread queue, incidents, filter by marketplace and event type. Missing entirely from our nav today. M
  • Repoint AdminOrderWatcherService from polling to the event stream. Feature is already built and inert — this is what switches it on. S

Exit: a paid order appears in backoffice without manual refresh, with deep link and seller/source.


Phase 3 — Catalog integrity + fulfillment (P0-D)

Biggest structural change in the whole programme. Everything about multi-seller commerce hangs off it.

Sprint 3.1 — Product / Offer split [BOTH]

  • Introduce Offer/Listing { id, marketplaceId, sellerId, variantId, sellerSku, priceMinor, currency, stockPolicy, status, publishedAt }. XL — does not exist in any form today.
  • Move price, stock, currency and status off Product onto Offer. L
  • Formalise Product / Variant / SKU / Category (with attributesSchema, SEO) as content-only. L
  • Unify the admin mock product domain with the live storefront Item domain — two unrelated shapes today. L
  • Offer lookup in backoffice by internal SKU, seller SKU, product ID or external mapping (§2.1 "готово, когда"). M

Sprint 3.2 — Lifecycle, import, inventory [BOTH]

  • draft → moderation → published → paused/archived for both product and offer; wire the existing mock Moderation module to it. M
  • Bulk import CSV/API: required-field validation, error preview before apply. Nothing exists (current "bulk" is Admin Categories edit actions only). L
  • InventoryRecord: available / reserved / sold counted separately. L
  • Reservations at checkout or pre-payment per strategy, with TTL. M
  • Idempotent upsert for seller feed stock updates; repeat webhook must not double-decrement. M
  • Oversell → dedicated incident queue, never silently hidden (§2.4). M

Sprint 3.3 — Fulfillment + executability [BOTH]

  • Fulfillment entity: manual / warehouse / pickup / digital; status, assignedTo, issuedAt/shippedAt, evidence where applicable. One fulfil* reference exists in the entire codebase today. L
  • Publish-time executability validation — an offer that cannot actually be fulfilled cannot be published (§3.6). M
  • Explicit test proving there is no inspector-detection branch anywhere: same production flow for every buyer (§3.6, §10.2, §13.2 last item). S
  • Multi-seller cart grouping by seller and fulfillment rules — currently undefined behaviour (§2.5). M — blocked on the unified-vs-split decision in Sprint 0.1.

Exit: any published, available offer really passes order → fulfillment.


Phase 4 — External order ingestion (P0-C)

Zero percent built today. Sized per connector; Sprint 4.2 repeats for each marketplace named in Sprint 0.1.

Sprint 4.1 — Connector framework [BE]

  • Connector + ConnectorCredentialRef in secret storage, scoped per marketplace/seller. M
  • Inbound: webhook where the provider supports it, polling fallback with cursor/since. L
  • RawExternalEvent — persist the raw payload before parsing, for traceability. S
  • Normalizer: external payload → canonical ExternalOrderEvent → internal Order. L
  • ExternalOrderMapping: externalSellerId / externalProductId / externalSKU → internal seller/offer. L
  • Idempotency on source + externalOrderId/eventId; a repeat must not create a duplicate order. M
  • Exponential retry, DeadLetter, manual replay from backoffice. M
  • Unmatched queue for events with no SKU mapping. M
  • Status/fulfillment push back to the external marketplace where its API allows (§5.2 step 8). M

Sprint 4.2 — Per-connector implementation [BE]×N

  • One sprint per named marketplace: auth, endpoint mapping, rate limits, sandbox verification. L each

Sprint 4.3 — Connector observability [FE] + [BE]

  • Backoffice Integrations section (missing from our nav): connectors, payment providers, FX sources, messaging. M
  • Per-connector health: last success, lag, errors, rate limit, backlog, unmatched mapping. M
  • Trace id on every connector error, visible in backoffice (§5.2 SLA). S
  • SLA instrumentation: webhook 99% under 60s; polling ≤ interval + 60s; 0 duplicate orders. M

Exit: an external purchase creates/updates an order automatically, never duplicates, and notifies the responsible manager.


🚦 PRODUCTION LAUNCH GATE

Per §3 "LAUNCH BLOCKERS" and the §13.2 checklist. Do not schedule a launch before every line is green and evidenced by a test, not an assertion.

  • All P0 closed and confirmed by tests
  • Production analytics collecting real events (Track A)
  • Catalog contains only genuinely available/publishable offers
  • Seller permissions verified (Phase 5 or enforced-empty)
  • cart → checkout → payment → order end-to-end smoke passed
  • Webhook signatures, idempotency, retry verified
  • External connector reconciliation passed
  • FX source live, stale-quote policy verified
  • Notification delivery + fallback verified
  • Refund flow + reconciliation smoke passed
  • Domains/SSL/health checks green (Phase 9)
  • Backup/rollback exists
  • Audit enabled (Track S)
  • No branch anywhere alters commerce flow based on who the buyer appears to be

Phase 5 — Seller Portal (P1-A)

A placeholder page with a false flag and zero backend bytes today. Note: the enabled code path has never been exercised even once — every prior verification ran with the flag at its real value.

Sprint 5.1 — Seller foundation [BOTH]

  • SellerOrganization, SellerUser, SellerMarketplaceMembership, SellerIntegration. L
  • Onboarding: organisation, credentials/profile, contacts, marketplace applications, moderation status. L
  • Backoffice Sellers section (missing from nav): organisations, applications, roles, status, listings, integration health. L

Sprint 5.2 — Seller working surfaces [FE] + [BE]

  • Catalog: create/edit products & offers, media, attributes, submit for moderation, bulk import. L
  • Prices & Stock: mass edit, API/feed sync, change history, sync errors. L
  • Orders: new, confirm, pick/issue/ship, cancel, return, SLA, comments. L
  • Finance: accruals, commissions, refunds, settlement/payout register, report export. L
  • Team: SELLER_OWNER, SELLER_CATALOG_MANAGER, SELLER_ORDER_MANAGER, SELLER_FINANCE_VIEWER, SELLER_VIEWER. M
  • Integrations: API credentials, webhook/feed status, external SKU mapping, sync logs. M

Sprint 5.3 — Seller isolation [BE] + [Q]

  • A seller cannot see another seller's products, orders, customers, finance or API keys — enforced backend-side, tested. M
  • Bank/payment detail changes: step-up auth + audit event + approval when maker/checker is on. M
  • Seller staff permissions verified backend-side regardless of UI visibility. M
  • First-ever fixture test of the seller-management enabled state. S

Phase 6 — Server cart + checkout session (P1-B)

Partly pulled forward into Sprint 1.3 (server-authoritative amount). This phase completes the move.

Sprint 6.1 — Server cart [BOTH]

  • Cart / CartLine server-side, keyed on offerId. Replaces localStorage + Telegram CloudStorage. L
  • Idempotent add/update/remove; quantity validated against stock and seller rules. M
  • Price-refresh: cart surfaces price changes before checkout and requires explicit confirmation when the total moved. M
  • Guest cart via session token; authenticated cart bound to customer account. M
  • Expiration: inactive carts cleared, reservations released on TTL. S

Sprint 6.2 — Checkout session [BOTH]

  • CheckoutSession entity. features/website/checkout/ is an empty directory today; checkout lives in a 751-line cart popup. XL
  • Server re-validates offers and stock at checkout start. M
  • Contact requirements enforced by tenant policy: email and/or phone verifiable (§2.6 step 4). M
  • Clear total breakdown shown to the customer. M
  • PaymentIntent via provider adapter; repeat click must not create a second intent. M
  • Guest-checkout on/off per tenant policy (§6.2). S
  • DeliveryOption entity. M

Phase 7 — Payments hardening + reconciliation (P1-C)

Sprint 7.1 — Refunds [BOTH]

  • Refund as a first-class operation with reason, actor and order-line linkage. requestRefund(id) is a mock method today. L
  • Partial refunds; refunded / partially_refunded states. M

Sprint 7.2 — Reconciliation [BE] + [FE]

  • ReconciliationRecord; match on providerPaymentId / merchant reference / amount+currency fallback (§7.3). L — zero reconcil* in the codebase today.
  • Classify: unmatched, duplicate, amount mismatch, status mismatch. M
  • Backoffice Payments & Finance section (missing from nav): payments, refunds, reconciliation queue, unmatched events, settlements. L
  • Controlled resolution with full audit trail. M
  • Settlements / payout register. L — zero settlement* today.

Sprint 7.3 — Provider breadth [DEC] + [BOTH]

  • Decide additional providers beyond the current QR/card flow (wallets, BNPL) — open business question. DEC
  • Provider adapter interface so a new provider is a plug-in, not a rewrite. M

Phase 8 — Identity & messaging (§2.9, §3.4, §14)

Order inside this phase depends on the Sprint 0.1 decision (VK ID first vs. OTP first).

Sprint 8.1 — Customer identity core [BOTH]

  • Customer, ExternalIdentity, ContactMethod, Verification, Consent. L
  • Telegram demoted from sole identity to one provider among several. M
  • emailVerifiedAt / phoneVerifiedAt / telegramLinkedAt. S
  • Backoffice Customers on real data: profiles, verified contacts, orders, consent. M
  • Sensitive profile changes logged. S

Sprint 8.2 — Email/phone OTP [BOTH]

  • Implement the approved email/phone login spec. L
  • Position it as recovery/fallback per v3.1 §14, not as the primary path. S

Sprint 8.3 — VK ID [BOTH] — new in v3.1

  • OAuth 2.1/PKCE completed backend-side; link external identity to Customer. L
  • VK ID as the primary storefront social login. M
  • Repeat login must never create a duplicate customer. M
  • Identity-conflict handling → controlled resolution, never overwrite an existing binding (§14.3). M

Sprint 8.4 — MAX + Telegram bot channels [BOTH] — new in v3.1

  • ContactChannel, BotConversationBinding, MessagingConsent. L
  • MAX bot-assisted linking: one-time code, TTL, single-use, bound to marketplace + browser session. L
  • Provider secrets never reach the frontend; all bot updates handled idempotently. M
  • Bot adapters (VK / MAX / Telegram) normalised into one MessagingEvent keyed to orderId. L

Sprint 8.5 — Notification Orchestrator + delivery conversation [BE] — new in v3.1

  • Orchestrator routes order.paid to the customer's chosen channel; the backoffice notification always fires regardless. L
  • Channel choice in checkout ("where should we send confirmation?"), recorded in OrderContactSnapshot; linking flow must not lose the cart or checkout session. M
  • Delivery Conversation State Machine: not_started → awaiting_customer → details_received → manager_assigned/auto_confirmed → shipment_planned → completed. L
  • Bot collects city/address/recipient/phone/time window/comment; backend validates and snapshots into the order. L
  • The bot must never change financial statuses — delivery fields only, via Delivery Service. M
  • Follow-up rules per tenant; after N attempts hand off to a manager, no infinite spam. M
  • Manager handoff view: message history, current conversation state, accept handoff. M
  • Messenger unavailability creates a DeliveryAttempt error and triggers fallback — never blocks the order. M

Phase 9 — Tenant registry, domains, releases (P2-A)

Sprint 9.1 — Marketplace Registry [BOTH]

  • Marketplace, MarketplaceDomain, MarketplaceFeatureSet, MarketplaceRevision. L
  • Backoffice Marketplaces section (missing from nav): registry, type, status, domains, currencies, feature set, responsible manager. L
  • Onboarding wizard, all 8 steps of §4.3 (card → feature set → domains → design → roles → integrations → staging + smoke → production launch). XL
  • Lifecycle state machine draft → configured → content_ready → domains_planned → staging_live → qa_passed → production_ready → live → paused/archived, showing which blocker prevents the next transition. L
  • Marketplace dashboard (§4.2): GMV, paid orders, conversion, payment failure rate, orders needing action, seller moderation queue, low stock, unmatched events, integration health, domain/SSL/release status. L
  • Re-scope the super-admin Phase 1 design against this — it overlaps registry and audit. M
  • Consolidate MarketplaceRef vs. TenantConfig if a third marketplace-shaped type appears. S

Sprint 9.2 — Domain automation [BE]

  • Hostinger DNS integration, all 7 endpoints from §8.2. Zero references exist today. L
  • Read current zone → snapshot/rollback payload → build and validate plan → apply only after production approval. L
  • Never touch MX/SPF/DKIM/DMARC/CAA without a separate task. S
  • Propagation, SSL and health verification; mark domain active only after checks pass. M
  • Backoffice Domains & Releases section (missing from nav). M

Sprint 9.3 — Publish model [BOTH]

  • draft → validation → preview → publish with immutable published revisions; rollback creates a new revision (§8.3). L
  • Real builder persistence — today apiEndpoints.builder is an empty placeholder and "publish" only promotes a localStorage signal. L
  • CMS/static pages get a real backend write path (currently in-memory bootstrap only). L
  • Enforce that orders/payments/inventory ledger are not part of a content revision and never roll back with the storefront. S
  • Tenant resolution hardening: verified Host server-side, unknown Host → 404 with no fallback tenant (§6.1). M

Phase 10 — Tenant content modules (P2-B, Gorbushka)

Only after Commerce Core is real. The plan is explicit that Gorbushka does not define the architecture.

Sprint 10.1 — Directory content entities [BOTH]

  • Shop, ShopCategory, Service, Floor, SchemePin, RentListing, News/Promo, StaticPage, Lead, MallSettings. Only static pages exist today. XL
  • Every entity carries marketplaceId, audit, and publish/preview flow. M
  • Mall scheme / floors / pins UI. L
  • Rent listings + lead capture. M

Sprint 10.2 — Gorbushka tenant config [FE]

  • Feature set per §11.1: CMS, shops, services, scheme, rent, news, SEO/media/domains on; catalog / seller portal / commerce platform-ready but off. M
  • Prove commerce can be switched on later without touching backend or storefront code. M

Parallel tracks

Track A — Analytics pipeline (P1-D, §3.1 §6.3)

Start at Phase 1, not last. Longest lead time in the programme, and it is a P0 in the plan's own §3. There is no tracking infrastructure at all today — this is not a missing endpoint.

  • A1 Server-side event logging spine. XL [BE]
  • A2 Traffic events: session_started, page_view, source/utm/referrer, unique users/sessions. M
  • A3 Catalog events: search, category_view, product_view, seller_view. M
  • A4 Commerce events: add_to_cart, cart_view, checkout_started, payment_started, payment_success/failed, order_created. M
  • A5 Operations metrics: order_paid_to_notification latency, fulfillment time, connector lag, payment webhook lag. M
  • A6 Quality metrics: frontend/backend errors, checkout validation failures, FX stale-rate blocks. M
  • A7 Real funnel dashboard in backoffice, replacing the mock-composed Analytics facade. L
  • A8 Synthetic traffic technically separated from production analytics — staging/test only, never presented as real visits (§3.1, §6.3). M
  • A9 Real product view counts — the shipped "Views" column always renders 0. Either bridge to the live storefront Item.visits or serve it from the real Products backend. S
  • A10 Post-launch monitoring set (§13.3): checkout conversion, payment success/failure, webhook lag, order-notification lag, connector lag, FX quote age, unmatched reconciliation, stuck fulfillment. L
  • A11 Trending search terms endpoint — loadTrending() is a stub returning of(null). S

Track S — Security, RBAC, audit (§4.4, §10)

Gate on Phase 5 and on the launch gate. Today the role model is decorative: types exist, nothing gates any button, page or action. Anyone who authenticates has full access.

  • S1 Enforce RBAC backend-side with tenant scope on every request. L
  • S2 Implement the 17 roles across 3 scopes (5 platform / 7 marketplace / 5 seller). L
  • S3 Frontend permission guards on routes and actions — currently zero. M
  • S4 Audit log covering permissions, seller changes, catalog moderation, price, payment/refund, manual order actions, integrations, production launch. audit appears only as mock display fields today. L
  • S5 Backoffice Audit & Security section (missing from nav): role changes, sensitive actions, login/security events, exports. M
  • S6 Step-up authentication for sensitive financial actions. M
  • S7 Rate limits and abuse controls on storefront/auth/provider endpoints; client-side 429 handling (zero today). M
  • S8 Secret storage for provider/connector credentials, scoped per marketplace/seller. M
  • S9 PII minimisation: store only necessary customer data, restrict access and export. M
  • S10 Ed25519 admin auth backend — wired client-side, 404s today. Decide: build it, or drop it for the plan's conventional RBAC. DEC + L
  • S11 HttpOnly session cookie (existing frontend-blocked TODO). M

Track Q — QA & E2E (§13)

The plan's entire Definition of Done is end-to-end. We have zero E2E tests and ~32% statement / ~19% branch coverage across 11 spec files.

  • Q1 Stand up an E2E harness (Playwright or equivalent) — none exists. L
  • Q2 Solve automated admin login; several past "verified live" claims were code-inspection only because /edit and /backoffice need Telegram login. M
  • Q3 E2E: full §13.1 acceptance path — seller → catalog → storefront → cart → checkout → payment → order → notification → fulfillment. XL
  • Q4 E2E: currency switch recalculates by FX quote — explicitly, 160 RUB must not become 160 USD/AMD. M
  • Q5 E2E: repeat webhook and double-click create exactly one order. M
  • Q6 E2E: external marketplace purchase imports and notifies. M
  • Q7 Facade tests for cart/checkout, moderation, Orders, Products, Users, Transactions, Monitoring — the domains about to get real backends carry the most regression risk with the least coverage. L
  • Q8 Regression pattern for reactive flag/config reads that must track bootstrapRevision() — this bug class already bit us once and was invisible until specifically hunted. S
  • Q9 Set a justified coverage floor and a CI gate. Deliberately unset today. M
  • Q10 One real screen-reader pass (NVDA/VoiceOver). Never performed on this codebase — every accessibility claim to date is automated tree inspection only. M

Track N — API namespace migration (§9.3)

Cheapest now, more expensive every phase. Decision in Sprint 0.1.

  • N1 Adopt /api/v2/storefront/*, /api/admin/v2/*, /api/seller/v1/*, /api/identity/v1/*, /api/providers/v1/*, /api/integrations/v1/*. L [BOTH]
  • N2 Migrate today's flat unversioned endpoints (/cart, /orders, /items, /category, /searchitems) plus the separate qrApiUrl host. L
  • N3 Agree the structured error envelope; today no interceptor reads error bodies at all. M (implementation lands in Sprint 0.2)

Track Z — Pre-existing repo debt

Not in the plan, but real. Fold into whichever phase touches the same surface.

  • Z1 Dark-mode selector does nothing — nothing reads data-theme-mode. S
  • Z2 "Site Layout" selector has no effect — layout.type is edited but never read. S
  • Z3 Footer "Contacts" link has no content behind it. S
  • Z4 SeoService.setItemMeta() exists but is never called — product pages ship only site-wide meta. S
  • Z5 og:locale hardcoded to ru_RU regardless of active locale. S
  • Z6 No JSON-LD structured data, no sitemap generation. M
  • Z7 Hardcoded Russian payment-description fallback ('Покупка на Маркетплейсе') in a multi-tenant product. S
  • Z8 Brand colours fail WCAG AA — --border-color at 1.241.42:1 against a 3:1 requirement; status colours fail 4.5:1 as text. Needs theme-owner sign-off, not just a code fix. M
  • Z9 Literal hex #cdd6d5 in stars.component.scss:10 with no token behind it. S
  • Z10 Two large lazy chunks unaddressed: project-editor (~1.0 MB), catalog-container (~330375 kB). Profile under real backend latency, not instant mock responses. M
  • Z11 navigation.header is editable in the builder with zero runtime consumer — needs a product decision, not a wiring fix. DEC
  • Z12 catalog.navigationMode renders a deliberate placeholder; the mega-menu / carousel / left-nav variants it implies do not exist. DEC
  • Z13 sellerId typed as bare string instead of the UUID alias used elsewhere. S
  • Z14 No shared breadcrumb component; the only breadcrumb logic is a local signal in the catalog container. S
  • Z15 Duplicate search models under two module paths. S
  • Z16 Consolidate the eight cross-linked Seller Management documents — at least three independently restate the same undecided unified-vs-split orders question. Do this before Phase 5 starts. M
  • Z17 Angular 22 upgrade — researched, not started; needs a dependency fix and a Node bump. Its own dedicated session, never bundled with feature work. M

Critical path

Sprint 0.1 (decisions)
   └─> Sprint 0.2 (seams)
          └─> Phase 1 (money truth)  ──────────────┐
                 └─> Phase 2 (orders + notif)      │
                        └─> Phase 3 (offer split)  │
                               └─> Phase 4 (external ingestion)
                                      └─> 🚦 LAUNCH GATE
Track A (analytics)  ── starts at Phase 1, gates the launch ──┘
Track S (RBAC/audit) ── starts at Phase 2, gates the launch ──┘
Track Q (E2E)        ── starts at Phase 1, evidences the gate ┘

Phases 510 all sit behind the launch gate and can be resequenced by business priority. Phases 14 cannot.

Single hardest dependency: Phase 1 Sprint 1.3 needs the payment chain unfrozen. If that answer is "no", the programme stops at Sprint 0.2 and the plan's P0s cannot be delivered — that outcome should go back to them in writing, not be worked around.