docs: backend contracts for Phases 8-10 (identity/messaging, tenant registry, content modules)

- Phase 8: Customer/ExternalIdentity/ContactChannel, VK ID OAuth 2.1/PKCE
  built first per Sprint 0.1 ("do all after vk"), then OTP, then MAX/
  Telegram bot linking, then the Notification Orchestrator + Delivery
  Conversation State Machine. Hard rule carried through: bots never touch
  financial statuses, only delivery fields via a dedicated Delivery Service.
- Phase 9: Marketplace/MarketplaceDomain/MarketplaceFeatureSet/
  MarketplaceRevision, full Hostinger DNS automation sequence (snapshot
  before change, never touch MX/SPF/DKIM/DMARC/CAA), lifecycle state
  machine that must expose its own blocker on every transition, publish
  model with orders/payments/inventory explicitly excluded from revisions.
- Phase 10: Gorbushka-class content entities (Shop/Service/Floor/
  SchemePin/RentListing/News/Lead/MallSettings), explicitly lowest
  priority and gated on Commerce Core being real first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-08-17 23:05:39 +04:00
parent 707db6d43c
commit ec6760ac65
3 changed files with 399 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
# Phase 9 Backend Contract — Tenant Registry, Domain Automation, Publish Model
Companion to [PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md](../PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md) Phase 9 (Sprints 9.19.3). Covers plan §4.3, §8.
**Status: ready to build.** Zero `hostinger` references exist in the codebase today.
---
## 1. Entities
```ts
interface Marketplace {
id: string;
name: string;
code: string;
type: 'commerce' | 'mall_directory' | 'hybrid' | 'single_brand';
ownerId: string;
countries: string[];
locales: string[];
currencies: string[];
timezone: string;
lifecycleState: MarketplaceLifecycleState;
}
type MarketplaceLifecycleState =
| 'draft' | 'configured' | 'content_ready' | 'domains_planned'
| 'staging_live' | 'qa_passed' | 'production_ready' | 'live' | 'paused' | 'archived';
interface MarketplaceDomain {
marketplaceId: string;
domain: string;
type: 'production' | 'www' | 'staging' | 'preview' | 'api' | 'seller';
status: 'planned' | 'dns_pending' | 'ssl_pending' | 'active' | 'failed';
}
interface MarketplaceFeatureSet {
marketplaceId: string;
features: Record<string, boolean>; // e.g. { catalog: true, sellers: true, cart: true, checkout: true, payments: true, orders: true, refunds: true, directory: false, ... }
}
interface MarketplaceRevision {
id: string;
marketplaceId: string;
status: 'draft' | 'validated' | 'preview' | 'published';
publishedAt?: string;
supersedesRevisionId?: string; // rollback creates a NEW revision, never mutates the old one
}
```
**Hard invariant:** `Order`, `Payment`, `InventoryRecord`, and every financial ledger row are **not part of a `MarketplaceRevision`**. Rolling back a storefront design revision must never touch commerce data.
## 2. Lifecycle state machine
```
draft -> configured -> content_ready -> domains_planned -> staging_live -> qa_passed -> production_ready -> live -> paused/archived
```
Every state transition endpoint must return the specific blocker preventing the next transition — not just "not ready."
```
GET /api/admin/v2/marketplaces/{id}/lifecycle -> { currentState, nextState, blockers: string[] }
POST /api/admin/v2/marketplaces/{id}/lifecycle/advance
```
## 3. Onboarding wizard (8 steps, plan §4.3)
```
POST /api/admin/v2/marketplaces -- step 1: name/code/type/owner/countries/locales/currencies/timezone
PATCH /api/admin/v2/marketplaces/{id}/feature-set -- step 2
POST /api/admin/v2/marketplaces/{id}/domains -- step 3
PATCH /api/admin/v2/marketplaces/{id}/design -- step 4
POST /api/admin/v2/marketplaces/{id}/roles -- step 5
PATCH /api/admin/v2/marketplaces/{id}/integrations -- step 6
POST /api/admin/v2/marketplaces/{id}/staging-launch -- step 7, runs smoke tests
POST /api/admin/v2/marketplaces/{id}/production-launch -- step 8, requires all P0 blockers closed + explicit approval
```
## 4. Domain automation (Hostinger API, per plan §8.2)
```
GET /api/dns/v1/zones/{domain}
POST /api/dns/v1/zones/{domain}/validate
PUT /api/dns/v1/zones/{domain}
DELETE /api/dns/v1/zones/{domain}
GET /api/dns/v1/snapshots/{domain}
GET /api/dns/v1/snapshots/{domain}/{snapshotId}
POST /api/dns/v1/snapshots/{domain}/{snapshotId}/restore
```
Process, strictly in this order:
```
1. Read current DNS zone.
2. Save a snapshot (rollback payload) BEFORE any change.
3. Build and validate a DNS plan.
4. NEVER touch MX/SPF/DKIM/DMARC/CAA records without a separate, explicitly scoped task.
5. Apply records only after production approval.
6. Verify propagation, SSL issuance, and health checks.
7. Mark the domain 'active' only after all checks in step 6 pass.
```
## 5. Publish model
```
draft -> validation -> preview -> publish
```
```
POST /api/admin/v2/marketplaces/{id}/revisions -- create draft
POST /api/admin/v2/marketplaces/{id}/revisions/{revId}/validate
POST /api/admin/v2/marketplaces/{id}/revisions/{revId}/publish -- becomes immutable
POST /api/admin/v2/marketplaces/{id}/revisions/{revId}/rollback -- creates a NEW revision pointing at the prior published content
```
Replaces the current builder's `localStorage`-only draft persistence and the empty `apiEndpoints.builder: {}` placeholder in bootstrap. CMS/static-page content (currently in-memory bootstrap only) gets a real write path through this same revision model.
## 6. Tenant resolution hardening
```
GET /api/v2/storefront/bootstrap -- resolved server-side from verified Host header
```
- Host is normalized and matched against `MarketplaceDomain` server-side — the marketplace ID from the browser is never a trust boundary.
- Unknown Host → `404`, with **no fallback to any other tenant**.
## 7. What the frontend will start doing once this ships
- Build the backoffice **Marketplaces** section (missing from admin nav today): registry, type, status, domains, currencies, feature set, responsible manager.
- Build the **Domains & Releases** section: DNS/SSL status, staging/production, health checks, rollback.
- Wire the project editor/builder to real revision persistence instead of `localStorage`.
- Marketplace dashboard: GMV, paid orders, conversion, payment failure rate, moderation queue, low stock, unmatched events, integration health, domain/SSL/release status (plan §4.2).