# Backend Surface Audit Machine-oriented, exhaustive audit of every backend touch-point the Angular frontend expects — derived from the current source tree on branch `B2B`, not copied from prior docs. Purpose: single input for downstream backend-integration documentation tasks. Legend for maturity (mirrors `docs/BACKEND_API.md`'s tagging so the two stay reconcilable): - **LIVE** — real `HttpClient` call exists in code today (file cited). - **MOCK-SWAPPABLE** — interface + mock implementation exist, wired through an Angular DI token so a real `*Api*` class can be dropped in without touching UI. A real impl may or may not exist yet. - **MOCK-ONLY (no seam)** — mock/local implementation exists but the facade injects the concrete local class **directly** (no DI token). Adding a backend here first requires introducing a token seam. This is the single most important structural finding below. - **LOCAL-ONLY** — never talks to a backend by design (localStorage / in-memory / derived from already-loaded bootstrap). Listed for completeness. ## Table of contents 1. [Executive summary & key findings](#1-executive-summary--key-findings) 2. [Runtime provider strategy & environment](#2-runtime-provider-strategy--environment) 3. [HTTP interceptor pipeline](#3-http-interceptor-pipeline) 4. [Live HTTP endpoints (verified in code)](#4-live-http-endpoints-verified-in-code) 5. [Domain: Auth (customer + admin)](#5-domain-auth-customer--admin) 6. [Domain: Bootstrap / config / tenant](#6-domain-bootstrap--config--tenant) 7. [Domain: Products & catalog](#7-domain-products--catalog) 8. [Domain: Categories](#8-domain-categories) 9. [Domain: Backoffice storefront data](#9-domain-backoffice-storefront-data) 10. [Domain: Cart / orders / payments](#10-domain-cart--orders--payments) 11. [Domain: Reviews & questions (engagement)](#11-domain-reviews--questions-engagement) 12. [Domain: Location / regions](#12-domain-location--regions) 13. [Domain: Widgets / dynamic renderer](#13-domain-widgets--dynamic-renderer) 14. [Admin gateways (feature area)](#14-admin-gateways-feature-area) 15. [Domain: Media library](#15-domain-media-library) 16. [Domain: Content management / static pages](#16-domain-content-management--static-pages) 17. [Domain: Project editor / builder](#17-domain-project-editor--builder) 18. [Domain: Search](#18-domain-search) 19. [Domain: User experience (wishlist/compare/etc.)](#19-domain-user-experience-wishlistcomparetc) 20. [Domain: Diagnostics](#20-domain-diagnostics) 21. [Facade catalog](#21-facade-catalog) 22. [Gateway / provider master table](#22-gateway--provider-master-table) 23. [Model / DTO catalog](#23-model--dto-catalog) 24. [Endpoint URL literals found in code](#24-endpoint-url-literals-found-in-code) 25. [Cross-check against existing docs](#25-cross-check-against-existing-docs) --- ## 1. Executive summary & key findings - **~9 real HTTP-speaking domains** exist today: product/catalog, categories, cart/orders/ payments, reviews/questions, telegram session auth, bootstrap, backoffice storefront data, widget manifest, location/regions. Plus **Ed25519 admin auth** — wired to real `HttpClient` but the endpoints are not implemented server-side yet (calls 404 today, by design). - **Two provider seams are token-bound and API-ready today**: `PRODUCT_DATA_PROVIDER` (→ `ApiProductDataProvider`, LIVE) and `CATEGORY_REPOSITORY` (→ `ApiCategoryRepository`, LIVE), plus `CONFIG_PROVIDER` and `BACKOFFICE_DATA_PROVIDER` which switch mock↔api by strategy. - **KEY STRUCTURAL FINDING — most admin CRUD domains have no swap seam.** Of the 11 admin gateway domains, only **categories** (`ADMIN_CATEGORIES_GATEWAY`) and **dashboard-metrics** (`ADMIN_DASHBOARD_METRICS_GATEWAY`) are injected via DI token. The other 9 (orders, products, users, transactions, monitoring, moderation, customers, analytics, and the products/orders gateways reused by analytics/customers) have their facades inject the concrete `Admin*LocalGateway` **class directly**. A backend engineer cannot "just rebind a token" for those — a token must be introduced first. This partially contradicts the blanket "PLANNED / rebind the token" framing in `docs/BACKEND_API.md`. - **Only one real `*Api*Gateway` exists in the admin area**: `AdminCategoriesApiGateway` (`src/app/features/admin/categories/services/admin-categories-api.gateway.ts`). Every other admin domain is local-mock only. - **Media** is bound by class token (`MediaRepository` abstract class → `MockMediaRepository` via `app.config.ts`), so it is MOCK-SWAPPABLE but no real impl exists. - **Content-management and project-editor never hit a dedicated backend** — they read/mutate the in-memory `BootstrapConfig` (loaded once from `GET /bootstrap`) and persist drafts to localStorage. Publishing a marketplace = writing bootstrap back, for which no client write call exists yet (LOCAL-ONLY today; a builder publish endpoint is FUTURE). - **Two API base URLs are in play**: the tenant marketplace API (`ApiConfigService.getBaseUrl()`, default `https://api.dexarmarket.ru:445`, `/api` on localhost) and a separate payment/QR API (`environment.qrApiUrl` = `https://qr.vitanova.network/api`). Auth session API uses `environment.authApiUrl` (= `https://api.dexarmarket.ru:445`). --- ## 2. Runtime provider strategy & environment `src/app/core/providers/runtime-provider-strategy.service.ts` — `RuntimeProviderStrategyService` decides mock vs api per domain. Modes: `'mock' | 'api' | 'remote-config'`. | Method | Returns `mock` when | Else | |---|---|---| | `getBootstrapProviderMode()` | `useMockData` true, OR `useMockBootstrapOnLocal && isLocalhost()` | `api` | | `getBackofficeProviderMode()` | `useMockData` true | `api` | | `getProductProviderMode()` | `useMockData` true | `api` (mock/remote-config fall through to api in token factory) | | `getCategoryProviderMode()` | `useMockData` true, OR `useMockBootstrapOnLocal && isLocalhost()` | `api` | Note: `PRODUCT_DATA_PROVIDER` and `CATEGORY_REPOSITORY` token factories currently return the **Api** provider for every mode (the `case 'mock'` falls through) — there is no mock product/ category provider class bound. `getCategoryProviderMode()` returning `mock` only matters for `ADMIN_CATEGORIES_GATEWAY` (which does honor it → `AdminCategoriesLocalGateway`). `src/environments/environment.ts` relevant keys: ``` useMockData: false useMockBootstrapOnLocal: true allowBootstrapApiOverride: false localhostApiUrl: '/api' tenantApiTemplate: 'https://{tenant}.api.dexarmarket.ru:445' tenantApiBaseUrls: { default: 'https://api.dexarmarket.ru:445', dexarmarket: 'https://api.dexarmarket.ru:445' } apiUrl: '/api' authApiUrl: 'https://api.dexarmarket.ru:445' qrApiUrl: 'https://qr.vitanova.network/api' telegramBot: 'myAMLKYCBOT' (fallback in code: 'DexarSupport_bot') ``` `src/app/core/config/api-config.service.ts` — `ApiConfigService.getBaseUrl()` resolves the tenant marketplace API base: localhost → `localhostApiUrl`; else `tenantApiBaseUrls[tenantKey]`; else `tenantApiTemplate` with `{tenant}` substituted; else optional bootstrap override (gated by `allowBootstrapApiOverride`, reads `bootstrap.apiEndpoints.website.baseUrl` / `bootstrap.tenant.apiBaseUrl`). `isApiRequest(url)` = starts with `/api` or the base URL. `toApiUrl(url)` rewrites a `/api`-prefixed relative URL onto the resolved base. Tenant key comes from `TenantResolverService` (`src/app/core/config/tenant-resolver.service.ts`). --- ## 3. HTTP interceptor pipeline Registered in `src/app/app.config.ts` in this order: ``` withInterceptors([mockDataInterceptor, apiBaseUrlInterceptor, apiHeadersInterceptor, adminAuthHeadersInterceptor, cacheInterceptor]) ``` | Interceptor | File | Responsibility | |---|---|---| | `mockDataInterceptor` | `src/app/interceptors/mock-data.interceptor.ts` | When `environment.useMockData`, short-circuits marketplace endpoints with in-memory fixtures (categories, items, search, cart, qr, callback, purchase-email, sessions). Matches URL patterns — see §24. | | `apiBaseUrlInterceptor` | `src/app/interceptors/api-base-url.interceptor.ts` | Rewrites `/api/*` relative URLs to `ApiConfigService.toApiUrl()`. | | `apiHeadersInterceptor` | `src/app/interceptors/api-headers.interceptor.ts` | For marketplace API requests, sets headers: `X-Region`, `X-Language` (RU/EN/AM), `Currency` (default RUB), `WebSessionID` (auth session id or persisted anonymous 32-hex id in localStorage key `web_session_id`). | | `adminAuthHeadersInterceptor` | `src/app/core/admin-auth/admin-auth-headers.interceptor.ts` | For requests whose URL contains `/admin/`, `/backoffice/`, `/builder/`, `/media/`, sets `AdminWebSessionID` header (from `AdminAuthService.session()`) and `Authorization: Bearer ` if an admin token is stored. | | `cacheInterceptor` | `src/app/interceptors/cache.interceptor.ts` | Client-side GET response caching. | Header value maps (from `apiHeadersInterceptor`): language `ru→RU, en→EN, hy→AM`; region `moscow→Moscow, spb→ST. Petersburg, yerevan→Yerevan`. --- ## 4. Live HTTP endpoints (verified in code) All paths relative to `ApiConfigService.getBaseUrl()` unless a full origin is shown. Payment endpoints use `environment.qrApiUrl`; session endpoints use `environment.authApiUrl`. ### Marketplace API — `src/app/services/api.service.ts` (`ApiService`) | Method | HTTP | Path | Notes | |---|---|---|---| | `ping()` | GET | `/ping` | `{ message }` | | `getCategories()` | GET | `/category` | normalized to `Category[]` | | `getCategoryItems(id,count,skip)` | GET | `/category/{categoryID}?count&skip` | `Item[]` | | `getItem(id)` | GET | `/items/{itemID}` | single `Item` | | `searchItems(search,count,skip,opts)` | GET | `/searchitems?search&count&skip[&categoryIDs&minPrice&maxPrice&tag&sort]` | `{ items, total }` | | `getRandomItems(count,categoryID?)` | GET | `/items/randomitems?count[&category]` | `Item[]` (featured) | | `addToCart(sessionId,items)` | POST | `/websession/{sessionId}` | body = item array | | `submitReview(data)` | POST | `/items/{itemID}/callback` | body: rating, comment, sessionID, timestamp | | `submitQuestion(data)` | POST | `/items/{itemID}/questiion` | **NOTE: literal typo `questiion`** matches backend spec | | `createCartPayment(payload)` | POST | `/cart` | `CartPaymentRequest` → `QrCreateResponse` | | `createOrder(payload)` | POST | `/orders` | `CreateOrderRequest` → `CreateOrderResponse`; fire-and-forget after payment | | `submitPurchaseEmail(data)` | POST | `/purchase-email` | email receipt | | `createPayment(payload,headers)` | POST | `{qrApiUrl}/qr` | headers `authorization-key`, `userid-value` | | `checkCartPaymentStatus(qrId)` | GET | `{qrApiUrl}/qr/dynamic/{partnerId}/{qrId}` | partnerId const `web-97ec-9c57-4dde-9037-3a68f7f83750` | | `checkCartCardPaymentStatus(orderId)` | GET | `{qrApiUrl}/card/{partnerId}/{orderId}` | | | `checkPaymentStatus(partnerQrId,qrId)` | GET | `{qrApiUrl}/qr/dynamic/{partnerQrId}/{qrId}` | | Also builds an external QR image URL (`https://api.qrserver.com/v1/create-qr-code/...`) — not a backend of this platform. ### Other live callers | Caller (file) | HTTP | Path | Base | |---|---|---|---| | `ApiHealthService` (`src/app/services/api-health.service.ts`) | GET | `/ping` | marketplace base | | `ApiCategoryRepository` (`src/app/core/categories/repositories/api-category.repository.ts`) | GET | `/category` | marketplace base; retry x2 | | `ApiBootstrapProvider` (`src/app/core/bootstrap/providers/api-bootstrap.provider.ts`) | GET | `/bootstrap` | relative | | `MockBootstrapProvider` | GET | `/assets/mock/bootstrap/bootstrap.json` | static asset | | `ApiBackofficeDataProvider` (`src/app/core/backoffice/providers/api-backoffice-data.provider.ts`) | GET | `/api/backoffice/products`, `/api/backoffice/categories` | | | `WidgetManifestService` (`src/app/widgets/registry/widget-manifest.service.ts`) | GET | `bootstrap.widgetRegistry.manifestUrl` or `/assets/mock/bootstrap/widget-manifest.json` | | | `LocationService` (`src/app/services/location.service.ts`) | GET | `/regions` (marketplace base); `http://ip-api.com/json/...` (external geo-IP) | | | `TelegramSessionApiService` (`src/app/services/telegram-session-api.service.ts`) | POST/GET/DELETE | `{authApiUrl}/users/sessions`, `/users/sessions/{id}` | session auth | | `AuthApiService` (`src/app/core/auth/services/auth-api.service.ts`) | GET/POST | `{authApiUrl}/api/admin/auth/challenge|verify|refresh|logout` | **not implemented server-side yet** | | `ApiProductDataProvider` | (delegates to `ApiService`) | see above | | --- ## 5. Domain: Auth (customer + admin) Two distinct auth mechanisms coexist. ### 5a. Telegram session auth (LIVE) — customer AND admin `src/app/services/telegram-session-api.service.ts` — `TelegramSessionApiService`. Single source for both customer (`AuthService`) and admin (`AdminAuthService`) login; there is no separate admin backend endpoint. Only storage is kept separate (distinct cookie/signals). | Method | HTTP | Path | Request | Response (normalized) | |---|---|---|---|---| | `createSession()` | POST | `{authApiUrl}/users/sessions` | `{ webSessionID }` + header `WebSessionID` | `WebSessionStart { webSessionID, url }` (url = `https://t.me/{bot}?start={id}`) | | `checkSessionOnce(id)` | GET | `{authApiUrl}/users/sessions/{id}` | — | `AuthSession | null` (heavily field-tolerant normalizer) | | `logout(id)` | DELETE | `{authApiUrl}/users/sessions/{id}` | header `WebSessionID` | ignored | Consumers: `AuthService` (`src/app/services/auth.service.ts`, customer), `AdminAuthService` (`src/app/core/admin-auth/admin-auth.service.ts`, admin — separate cookie `adminSessionID`, has dev-only `devBypassLogin()`), `AuthFacade` (`src/app/core/auth/services/auth-facade.service.ts`) wrapping AuthService/SessionService/ PermissionService for components. Also `src/app/shared/qr-login/`. Models: `AuthSession`, `WebSessionStart`, `AuthStatus` (`src/app/models/auth.model.ts`); `AdminAuthStatus` (`src/app/models/admin-auth.model.ts`). ### 5b. Ed25519 challenge/response admin auth (LIVE wiring, backend absent) `src/app/core/auth/services/auth-api.service.ts` — `AuthApiService`. Real `HttpClient` wiring against a documented contract that the backend has NOT implemented yet (calls 404 today, mapped to a `backend-unavailable` error screen). No mocks fabricated. | Method | HTTP | Path (`{authApiUrl}/api/admin/auth`) | Request | Response | |---|---|---|---|---| | `requestChallenge()` | GET | `/challenge` | — | `AuthChallenge { nonce, issuedAt, expiresAt }` | | `verifySignature(req)` | POST | `/verify` | `VerifySignatureRequest { publicKey, signature, nonce }` | `AuthTokenPair { token, refreshToken }` | | `refresh(req)` | POST | `/refresh` | `RefreshTokenRequest { refreshToken }` | `AuthTokenPair` | | `logout(refreshToken)` | POST | `/logout` | `{ refreshToken }` | void | Models: `src/app/core/auth/models/auth-api.model.ts` (`AuthChallenge`, `VerifySignatureRequest`, `AuthTokenPair`, `RefreshTokenRequest`, `JwtClaims`). Supporting: `src/app/core/auth/services/ed25519-keypair.service.ts` (keypair gen/signing); `src/app/core/admin-auth/ed25519-verification.model.ts` + `noop-ed25519-verification.service.ts` (bound in `app.config.ts` via `{ provide: Ed25519VerificationService, useClass: NoopEd25519VerificationService }`). Permissions/roles: `src/app/core/auth/models/permission.model.ts` — `AdminRole` (`Owner|Administrator|Editor|Support|ReadOnly`), `Permission` union. Errors: `src/app/core/auth/models/auth-error.model.ts` — `AuthErrorCode`, `AuthError`. Guards: `src/app/core/admin-auth/admin-auth.guard.ts`, `src/app/guards/**`. --- ## 6. Domain: Bootstrap / config / tenant The runtime configuration document that drives the entire multi-tenant platform. - **Contract interface**: `ConfigProvider` (`src/app/core/config/config-provider.interface.ts`) — `loadBootstrap(): Observable`. - **DI token**: `CONFIG_PROVIDER` (`src/app/core/config/config-provider.token.ts`), factory switches on `getBootstrapProviderMode()`: `mock` → `MockBootstrapProvider` (`/assets/mock/bootstrap/bootstrap.json`), else → `ApiBootstrapProvider` (`GET /bootstrap`). - **Implementations**: `ApiBootstrapProvider`, `MockBootstrapProvider` (`src/app/core/bootstrap/providers/*`). - **Consuming services**: `ConfigService` (`src/app/core/config/config.service.ts`, holds the bootstrap snapshot), `ApiConfigService`, `FeatureConfigService`, `TenantResolverService`, `FooterResolverService`, `StaticPageResolverService` (all `src/app/core/config/*`). - **Consuming facades**: `UiRuntimeFacade` (`src/app/facades/runtime/ui-runtime.facade.ts`), `WebsiteRuntimeFacade` (`src/app/facades/website/website-runtime.facade.ts`), `ProjectEditorFacade`, `ContentManagementFacade`, `DiagnosticsFacade`. `BootstrapConfig` (`src/app/shared/models/config/bootstrap-config.model.ts`) aggregates ~24 sub-configs, each its own file under `src/app/shared/models/config/`: `schemaVersion, generatedAt, tenant, branding, theme, company, featureFlags, features?, apiEndpoints, localization, seo, permissions, header?, catalog?, layout?, navigation, footer?, productPage?, userExperience?, pages[], staticPages?, widgetRegistry?` Sub-config model files (all backend-shaped, served inside bootstrap): `api-endpoints.model.ts` (`ApiEndpointConfig{path,method,timeoutMs?}`, `ApiEndpointsConfig{ bootstrap, website:Record<...>, builder:Record<...>, backoffice:Record<...>}`), `tenant.model.ts` (`TenantConfig{id,slug,code,host,name,websiteBaseUrl,builderBaseUrl, backofficeBaseUrl,defaultLocale,supportedLocales,defaultCurrency,supportedCurrencies,timezone}`), `branding.model.ts`, `theme.model.ts`, `company.model.ts`, `feature-flags.model.ts`, `features-config.model.ts`, `footer-config.model.ts`, `header-config.model.ts`, `layout.model.ts`, `localization.model.ts`, `navigation.model.ts`, `page.model.ts`, `permissions.model.ts`, `product-page-config.model.ts`, `catalog-config.model.ts`, `seo.model.ts`, `static-page.model.ts`, `user-experience-config.model.ts`, `widget-registry.model.ts`, `widget.model.ts`, `section.model.ts`. Barrel: `src/app/shared/models/config/index.ts`. `ApiEndpointsConfig.website/builder/backoffice` are `Record` — i.e. the bootstrap document is where a tenant's PLANNED endpoint paths are declared at runtime. No literal builder/backoffice path constants exist in code (see §24). --- ## 7. Domain: Products & catalog - **Contract interface**: `ProductDataProvider` (`src/app/core/products/providers/product-data-provider.interface.ts`). - **DI token**: `PRODUCT_DATA_PROVIDER` (`src/app/core/products/product-data-provider.token.ts`) — factory returns `ApiProductDataProvider` for all modes (no mock provider class bound). - **Real impl (LIVE)**: `ApiProductDataProvider` (`src/app/core/products/providers/api-product-data.provider.ts`) — delegates to `ApiService` + `CategoryService`; contains inline mapping (item→reviews/questions/rating summary). - **Domain service**: `ProductDataService` (`src/app/core/products/product-data.service.ts`) injected by `ProductFacade`. - **Consuming facade**: `ProductFacade` (`src/app/facades/platform/product.facade.ts`). - **Consuming components**: `catalog-container.component.ts`, `product-details-container.component.ts` (`src/app/features/website/**`), home/catalog pages. Interface methods: `getProducts(query?)`, `getProduct(productID)`, `getCategories()`, `searchProducts(query)`, `getFeaturedProducts(query?)`, `getLatestProducts(query?)`, `getProductsByCategory(categoryID,query?)`, `getRelatedProducts(query)`, `loadRating(productID)`, `loadReviews(productID,query?)`, `loadQuestions(productID,query?)`, `submitReview(productID,input)`, `submitQuestion(productID,input)`. Models — `src/app/core/products/models/`: - `product-domain.model.ts`: `Product = Item` (alias), `ProductCategory = Category`, `ProductSort`, `ProductFilters`, `ProductListQuery`, `ProductSearchQuery`, `ProductListResult`, `RelatedProductsQuery`, `RelatedProductCollection`, `ProductVariantSelection`. - `product-engagement.model.ts`: `RatingStars`, `RatingDistributionEntry`, `RatingSummary`, `Review`, `Answer`, `Question`, `EngagementListQuery`, `EngagementListResult`, `SubmitReviewInput`, `SubmitQuestionInput`. - `catalog-experience.model.ts`: `SearchCriteria`, `FilterDefinition`, `FilterOption`, `SortDefinition`, `CatalogView`, `SearchResult`, layout/nav mode types. The **backend-shaped** product DTO is `Item` (`src/app/models/item.model.ts`) — the raw wire shape. `ApiService.normalizeItem()` is the adapter: it reconciles legacy marketplace format and newer backOffice format (string `id`↔numeric `itemID`, `imgs[]`↔`photos[]`, `names[]`↔ `translations`, `itemDetails[]`, `description` key/value array↔string, `comments`↔`callbacks`, `specificationGroups`, `variantOptions`, `relatedCollections`, delivery normalization, color `0xRRGGBB`→`#RRGGBB`, remaining→stock band). This is the single largest inline mapper in the codebase — a backend engineer should treat `normalizeItem`/`normalizeCategory` as the tolerance contract. `Item` supporting types: `ProductMedia`, `DescriptionField`, `ItemName`, `ProductSpecificationField/Group`, `ProductVariantOption(Group)`, `RelatedProductCollection`, `DeliveryOption`, `ItemDetail`, `CartItem`. --- ## 8. Domain: Categories Two parallel category stacks exist (legacy + clean-architecture): **Clean stack (MOCK-SWAPPABLE, real impl LIVE):** - **Interface**: `CategoryRepository` (`src/app/core/categories/repositories/category.repository.ts`) — `getCategories(): Observable`. - **DI token**: `CATEGORY_REPOSITORY` (`src/app/core/categories/category-repository.token.ts`) → `ApiCategoryRepository` for all modes. - **Real impl (LIVE)**: `ApiCategoryRepository` — `GET /category`, retry x2. - **DTO**: `CategoryDto`, `CategoryNameDto` (`src/app/core/categories/dto/category.dto.ts`). - **Adapter**: `CategoryMapper` (`src/app/core/categories/mappers/category.mapper.ts`) — `CategoryDto → Category` domain (flattens subcategory tree, dedupes by id, language normalization `am→hy`). - **Domain model**: `Category`, `CategoryTranslation` (`src/app/core/categories/models/category-domain.model.ts`). - **Facade**: `CategoryFacade` (`src/app/facades/platform/category.facade.ts`) via `CategoryService` (`src/app/core/categories/category.service.ts`). Utils: `category-tree.utils.ts`. **Legacy stack**: `ApiService.getCategories()` → `Category` (`src/app/models/category.model.ts`, with `Subcategory`) via `normalizeCategory()`. Used by `ApiProductDataProvider.getCategories()`. Note: two different `Category` types exist (`src/app/models/category.model.ts` vs `src/app/core/categories/models/category-domain.model.ts`) — a known duplication. --- ## 9. Domain: Backoffice storefront data Storefront-facing "cards" data (distinct from the admin/backoffice feature area). - **Interface**: `BackofficeDataProvider` (`src/app/core/backoffice/providers/backoffice-data-provider.interface.ts`) — `loadProducts(): Observable`, `loadCategories(): Observable`. - **DI token**: `BACKOFFICE_DATA_PROVIDER` (`src/app/core/backoffice/backoffice-data-provider.token.ts`) — `mock` → `MockBackofficeDataProvider`, else → `ApiBackofficeDataProvider`. - **Impls**: `ApiBackofficeDataProvider` (LIVE, `GET /api/backoffice/products`, `GET /api/backoffice/categories`), `MockBackofficeDataProvider` (`src/app/core/backoffice/providers/*`). - **Models**: `ProductCardConfig` (`src/app/shared/models/ui/product-card.model.ts`), `CategoryCardConfig` (`src/app/shared/models/ui/category-card.model.ts`), `ButtonConfig` (`button.model.ts`). Barrel: `src/app/shared/models/ui/index.ts`. --- ## 10. Domain: Cart / orders / payments Cart state is **LOCAL-ONLY** but checkout produces LIVE payment/order calls. - **`CartService`** (`src/app/services/cart.service.ts`) — signal-based cart, persisted to localStorage key `marketplace_cart` (+ Telegram CloudStorage when in Telegram WebApp). No backend for cart contents. Models: `CartItem` (extends `Item`), `DeliveryOption`. - **Checkout → `ApiService`** (see §4): `POST /cart` (`CartPaymentRequest`), `POST /orders` (`CreateOrderRequest`→`CreateOrderResponse`), `POST /purchase-email`, QR/card status polling on `qrApiUrl`. - Request/response DTOs live inline in `api.service.ts`: `QrCreateRequest`, `QrCreateResponse`, `CartPaymentRequest`, `CreateOrderRequest`, `CreateOrderResponse`, `QrDynamicStatusResponse`. - Admin-side order/transaction views are a **separate** mock domain — see §14. --- ## 11. Domain: Reviews & questions (engagement) Customer-facing. LIVE via `ApiService`. Interface methods on `ProductDataProvider`: `loadRating`, `loadReviews`, `loadQuestions`, `submitReview`, `submitQuestion`. Endpoints: `POST /items/{id}/callback` (review), `POST /items/{id}/questiion` (question, typo preserved). Reads derive reviews/questions/rating from `GET /items/{id}` payload (no dedicated list endpoints yet). Models in `product-engagement.model.ts` (§7). Admin **moderation** of reviews/reports is a separate mock domain — see §14. --- ## 12. Domain: Location / regions `LocationService` (`src/app/services/location.service.ts`), LIVE: - `GET /regions` (marketplace base) → `Region[]`; falls back to 6 hardcoded regions on error. - `GET http://ip-api.com/json/?fields=...` (external geo-IP, no key) for auto-detect. Models: `Region`, `GeoIpResponse` (`src/app/models/location.model.ts`). Region id feeds the `X-Region` header (§3). --- ## 13. Domain: Widgets / dynamic renderer Widget manifest is LIVE (static/remote JSON), widget data is derived from products/categories. - **`WidgetManifestService`** (`src/app/widgets/registry/widget-manifest.service.ts`) — GETs `bootstrap.widgetRegistry.manifestUrl` or fallback `/assets/mock/bootstrap/widget-manifest.json` → `WidgetManifestFile`. - **`WidgetRegistryService`** (`src/app/widgets/registry/widget-registry.service.ts`), **`WidgetHostService`** (`src/app/dynamic-renderer/widget-host/widget-host.service.ts`). - Contracts (`src/app/widgets/contracts/`): `widget-manifest.contract.ts` (`WidgetManifestEntry/File`, `WidgetSettingsSchema`, `WidgetMetadataSupport`, `WidgetLayoutSupport`, `WidgetDataSourceName`), `widget-component.contract.ts` (`WidgetRenderContext`, `RegisteredWidget`, `ResolvedWidget`), `widget-data.contract.ts` (`HeroWidgetData`, `CategoriesWidgetData`, `ProductCollectionWidgetData`, `BannerWidgetData`, `HtmlWidgetData`, `PartnersWidgetData`, `FooterWidgetData`, `HeroSlideData`, `WidgetResolvedContext`). - Renderer models: `src/app/dynamic-renderer/{page-renderer,section-renderer,widget-host}/*.model.ts`. - Widget data sources (`featured|latest|category|manual|related|root|parent`) map back onto the product/category providers of §7–§8. --- ## 14. Admin gateways (feature area) `src/app/features/admin/**`. Each domain follows Facade → Gateway (interface) → LocalGateway. **Only categories and dashboard-metrics use a DI token; all others inject the local class directly (MOCK-ONLY, no seam).** Only `AdminCategoriesApiGateway` is a real HTTP impl. | Domain | Interface | Local (mock) impl | Real impl | DI token | Facade | Seam status | |---|---|---|---|---|---|---| | Categories | `admin-categories-gateway.interface.ts` (`AdminCategoriesGateway`) | `admin-categories-local.gateway.ts` | `admin-categories-api.gateway.ts` (**HttpClient**) | `ADMIN_CATEGORIES_GATEWAY` (`admin-categories-gateway.token.ts`) | `AdminCategoriesFacade` | MOCK-SWAPPABLE (real impl exists) | | Dashboard metrics | `admin-dashboard-metrics.gateway.interface.ts` (`AdminDashboardMetricsGateway`) | `admin-dashboard-metrics.local.gateway.ts` | none | `ADMIN_DASHBOARD_METRICS_GATEWAY` (`admin-dashboard-metrics-gateway.token.ts`) | `AdminDashboardFacade` | MOCK-SWAPPABLE (token only) | | Orders | `admin-orders-gateway.interface.ts` (`AdminOrdersGateway`) | `admin-orders-local.gateway.ts` | none | **none** | `AdminOrdersFacade` (injects `AdminOrdersLocalGateway`) | MOCK-ONLY (no seam) | | Products | `admin-products-gateway.interface.ts` (`AdminProductsGateway`) | `admin-products-local.gateway.ts` | none | **none** | `AdminProductsFacade` (injects local) | MOCK-ONLY (no seam) | | Users | `admin-users-gateway.interface.ts` (`AdminUsersGateway`) | `admin-users-local.gateway.ts` | none | **none** | `AdminUsersFacade` (injects local) | MOCK-ONLY (no seam) | | Transactions | `admin-transactions-gateway.interface.ts` (`AdminTransactionsGateway`) | `admin-transactions-local.gateway.ts` | none | **none** | `AdminTransactionsFacade` (injects local) | MOCK-ONLY (no seam) | | Monitoring | `admin-monitoring-gateway.interface.ts` (`AdminMonitoringGateway`) | `admin-monitoring-local.gateway.ts` | none | **none** | `AdminMonitoringFacade` (injects local) | MOCK-ONLY (no seam) | | Moderation | `admin-moderation-gateway.interface.ts` (`AdminModerationGateway`) | `admin-moderation-local.gateway.ts` | none | **none** | `AdminModerationFacade` (injects local) | MOCK-ONLY (no seam) | | Customers | (no gateway of its own) | reuses `AdminOrdersLocalGateway` | none | **none** | `AdminCustomersFacade` (injects orders local) | MOCK-ONLY (derived) | | Analytics | (no gateway of its own) | reuses orders/products/moderation local + `ADMIN_CATEGORIES_GATEWAY` + `AdminDashboardFacade` | none | partial (categories token) | `AdminAnalyticsFacade` | MOCK-ONLY (derived) | Gateway interface method contracts (the shapes a backend must satisfy): - **`AdminCategoriesGateway`**: `loadCategories(filters)`, `loadCategory(id)`, `createCategory`, `updateCategory`, `deleteCategory`, `restoreCategory`, `isSlugTaken(slug,excludingId)`. - **`AdminDashboardMetricsGateway`**: `loadMetrics(): AdminDashboardMetrics`. - **`AdminOrdersGateway`**: `loadOrders(filters)`, `loadOrder(id)`, `updateStatus(id,status)`, `requestRefund(id)`, `addNote(id,note,internal)`, `archiveOrder`, `restoreOrder`, `deleteOrder`. - **`AdminProductsGateway`**: `loadProducts(filters)`, `loadProduct(id)`, `loadCategories()`, `createProduct`, `updateProduct`, `deleteProduct`, `duplicateProduct`, `archiveProduct`, `restoreProduct`. - **`AdminUsersGateway`**: `loadUsers`, `loadRoles`, `loadInvitations`, `loadSessions(userId)`, `loadAudit(userId)`, `setUserRole`, `setUserStatus`, `inviteUser(email,roleId,scope)`, `revokeInvitation`, `revokeSession`. - **`AdminTransactionsGateway`**: `loadTransactions(filters)`, `retryFailed(id)`, `setFraudFlag(id,flagged)`. - **`AdminMonitoringGateway`**: `loadEvents(filters)`, `loadQueues()`, `loadWebhooks()`. - **`AdminModerationGateway`**: `loadReviews(filters)`, `loadReview(id)`, `setReviewStatus`, `setReviewVisible`, `setReviewPinned`, `setReviewFeatured`, `addModeratorNote`, `deleteReview`, `loadReports()`, `setReportStatus(id,status)`. Admin model files (all under `src/app/features/admin//models/`) — see §23. Note: `AdminRole` is defined **twice** with different meaning — `src/app/core/auth/models/ permission.model.ts` (auth roles `Owner|Administrator|Editor|Support|ReadOnly`) vs `src/app/features/admin/users/models/admin-user.model.ts` (`AdminRole` interface {id,name,...}). Flag for backend/naming reconciliation. Local gateways are localStorage / in-memory backed (facades also inject `LocalStorageService` for overlay persistence, e.g. orders/moderation/categories/products). --- ## 15. Domain: Media library MOCK-SWAPPABLE via abstract-class token, no real impl. - **Contract**: abstract class `MediaRepository` (`src/app/core/media/media-repository.ts`) — `list(params?)`, `upload(file,options?)`, `remove(id)`, `update(id,patch)`, `listFolders()`. - **Binding**: `app.config.ts` → `{ provide: MediaRepository, useClass: MockMediaRepository }`. - **Mock impl**: `MockMediaRepository` (`src/app/core/media/mock-media-repository.service.ts`, uses `HttpClient` to read seed assets). Also `MediaUsageService` (`src/app/core/media/media-usage.service.ts`). - **Facade**: `MediaLibraryFacade` (`src/app/features/backoffice/media/facade/media-library.facade.ts`), page `media-library-page.component.ts`. - **Models** (`src/app/core/media/models/media-asset.model.ts`): `MediaAsset`, `MediaAssetKind`, `MediaSort`, `MediaListParams`, `MediaUploadOptions`, `MediaListResult`. - Admin-auth interceptor already gates `/media/` paths (§3), anticipating a real media backend. --- ## 16. Domain: Content management / static pages **LOCAL-ONLY** — operates on the already-loaded `BootstrapConfig.staticPages`, no dedicated backend calls. Publishing/writing bootstrap is not implemented client-side (FUTURE). - **Facade**: `ContentManagementFacade` (`src/app/features/content-management/facade/content-management.facade.ts`) → `ContentPageService` (`.../services/content-page.service.ts`). Public API: `pages(bootstrap)`, `hasSeoContent(page)`, `contentHealth(bootstrap)`, `resolvePage(bootstrap,keyOrSlug,locale)`, `validatePages(bootstrap)`, `toBootstrapRecord(bootstrap)`, `serializePages(pages)`, `normalizeSlug`. - `ContentPageService` maps between bootstrap `StaticPagesConfig` and the editor `ContentPage` view model (normalize / validate / `toBootstrapRecord`). This is the adapter. - **Models** (`src/app/features/content-management/models/`): `ContentPage`, `ContentPageTranslation`, `ContentPageSeoConfig`, `ContentPageStatus`, `ContentPageBootstrapInput` (`content-page.model.ts`); `LegalPageKey`, `LegalPageDefinition` (`legal-pages.model.ts`). Backend-shaped counterpart: `StaticPageConfig`, `StaticPagesConfig`, `ResolvedStaticPage`, `LocalizedHtmlContent`, `LocalizedTextContent` (`src/app/shared/models/config/static-page.model.ts`). - Consumers: `static-pages-editor.component.ts`, `page-editor.component.ts`, `static-page.component.ts` (`src/app/pages/static-page/`), resolved via `StaticPageResolverService`. --- ## 17. Domain: Project editor / builder **LOCAL-ONLY** today — edits an in-memory `BootstrapConfig`, persists drafts to localStorage; no publish/save-to-backend HTTP call exists. A builder API is declared only as `BootstrapConfig.apiEndpoints.builder` (runtime-declared, FUTURE). - **Facade**: `ProjectEditorFacade` (`src/app/features/project-editor/facade/project-editor.facade.ts`) — orchestrates undo/redo `History`, injects `ConfigService`, `ProjectEditorIoService` (JSON import/export of bootstrap), `ProjectEditorPreviewService`, `LocaleSyncService`, `PlatformRuntimeService`, `ProjectValidator`, `ProjectEditorDraftStorageService` (localStorage drafts), `EditorSchemaService`. - Services (`src/app/features/project-editor/services/`): `project-editor-io.service.ts` (`exportBootstrap`/`importBootstrap` = JSON.stringify/parse), `project-editor-draft-storage.service.ts`, `project-editor-preview.service.ts`, `project-validator.service.ts`, `locale-sync.service.ts`. Schema: `schema/editor-schema.service.ts`, `schema/field-schema.model.ts`, `schema/validators/`. - **Models**: `project-editor.model.ts` (`ProjectEditorState`, `ProjectEditorSectionId`, `ProjectEditorWidgetPreset`, `BuilderSectionStatus`), `builder/builder-groups.model.ts`. - Consumers: `project-editor-page.component.ts`, `homepage-section.component.ts`, `project-editor-nav.component.ts`. Also drives admin products/categories/dashboard facades (which inject `ProjectEditorFacade`). --- ## 18. Domain: Search **LOCAL-ONLY orchestration over the product/category providers** — no dedicated search backend; `SearchFacade` composes `ProductFacade` + `CategoryFacade` results and manages history/trending/ autocomplete/cache client-side. - **Facade**: `SearchFacade` (`src/app/features/search/facade/search.facade.ts`) injects `ProductFacade`, `CategoryFacade`, `SearchAutocompleteService`, `SearchHistoryService`, `SearchTrendingService`, `SearchCacheService`, `SearchStore`, `TranslateService`. - Services (`src/app/features/search/services/`): `search-autocomplete.service.ts`, `search-history.service.ts` + `search-history.repository.ts` (interface `SearchHistoryRepository{load,save,clear}`, localStorage), `search-trending.service.ts`, `search-cache.service.ts`. Store: `store/search.store.ts`. - **Models**: `src/app/features/search/models/search.model.ts` (`SearchQuery`, `SearchResult`, `SearchSuggestion`, `SearchFilterType`, `FilterGroup`, `FilterOption`, `SortOption`, `SearchHistory`, `SearchAnalyticsEvent`, `SearchNavigationTarget`), `search-state.model.ts` (`SearchState`). Duplicated under `src/app/core/search/models/`. - Underlying live traffic is `GET /searchitems` (§4) via `ProductFacade.searchProducts`. --- ## 19. Domain: User experience (wishlist/compare/etc.) **LOCAL-ONLY** (guest-first). MOCK-SWAPPABLE token exists for a future authenticated backend. - **Interface**: `UserExperienceRepository` (`src/app/core/user-experience/repositories/user-experience.repository.ts`). - **DI token**: `USER_EXPERIENCE_REPOSITORY` (`src/app/core/user-experience/user-experience-repository.token.ts`) → currently always `LocalUserExperienceRepository` (localStorage). Comment notes it "can be switched to authenticated repository later." - **Facade**: `UserExperienceFacade` (`src/app/facades/platform/user-experience.facade.ts`) — wishlist / compare / recently-viewed / saved-searches / continue-browsing, all signals. - **Models** (`src/app/core/user-experience/models/user-experience.model.ts`): `FavoriteItem`, `ComparedProduct`, `RecentlyViewedItem`, `SavedSearch`, `ContinueBrowsingState`. Config shape: `user-experience-config.model.ts` (limits, from bootstrap). --- ## 20. Domain: Diagnostics **LOCAL-ONLY** — inspects runtime/bootstrap/widget state; the one live-ish probe is API ping. - **Facade**: `DiagnosticsFacade` (`src/app/features/diagnostics/facade/diagnostics.facade.ts`) injects `ConfigService`, `TenantResolverService`, `PlatformRuntimeStateService`, `RuntimeDiagnosticsService`, `WidgetManifestService`, `WidgetRegistryService`, `RuntimeProviderStrategyService`, `DiagnosticsLoggerService`, `TranslateService`, `Router`. - Validators: `validators/runtime-diagnostics.validator.ts` (uses `HttpClient` for API health probe), `bootstrap-diagnostics.validator.ts`, `diagnostics-health-score.util.ts`. - **Models** (`src/app/features/diagnostics/models/diagnostics.model.ts`): `DiagnosticEntry`, `DiagnosticSeverity`, `DiagnosticsHealthSummary`, `DiagnosticsReport`. --- ## 21. Facade catalog | Facade | File | Depends on | Consumed by (examples) | |---|---|---|---| | `ProductFacade` | `facades/platform/product.facade.ts` | `ProductDataService` → `PRODUCT_DATA_PROVIDER` | catalog/product containers, `SearchFacade` | | `CategoryFacade` | `facades/platform/category.facade.ts` | `CategoryService` → `CATEGORY_REPOSITORY` | catalog nav, `SearchFacade` | | `SearchFacade` | `features/search/facade/search.facade.ts` | ProductFacade, CategoryFacade, search services | search bar/pages | | `UserExperienceFacade` | `facades/platform/user-experience.facade.ts` | `USER_EXPERIENCE_REPOSITORY` | wishlist/compare UI | | `UiRuntimeFacade` | `facades/runtime/ui-runtime.facade.ts` | `ConfigService` | header/branding | | `WebsiteRuntimeFacade` | `facades/website/website-runtime.facade.ts` | config/page renderer | dynamic pages | | `AuthFacade` | `core/auth/services/auth-facade.service.ts` | AuthService, SessionService, PermissionService | login/guarded UI | | `MediaLibraryFacade` | `features/backoffice/media/facade/media-library.facade.ts` | `MediaRepository` | media page | | `ContentManagementFacade` | `features/content-management/facade/...` | `ContentPageService` (bootstrap) | content dashboard/editor | | `ProjectEditorFacade` | `features/project-editor/facade/...` | config + editor services (localStorage) | builder pages, admin facades | | `DiagnosticsFacade` | `features/diagnostics/facade/...` | runtime/config/widget services | diagnostics page | | `AdminCategoriesFacade` | `features/admin/categories/facade/...` | `ADMIN_CATEGORIES_GATEWAY`, ProjectEditorFacade | admin categories pages | | `AdminProductsFacade` | `features/admin/products/facade/...` | `AdminProductsLocalGateway`, ProjectEditorFacade | admin products pages | | `AdminOrdersFacade` | `features/admin/orders/facade/...` | `AdminOrdersLocalGateway` | admin orders pages | | `AdminUsersFacade` | `features/admin/users/facade/...` | `AdminUsersLocalGateway` | admin users pages | | `AdminTransactionsFacade` | `features/admin/transactions/facade/...` | `AdminTransactionsLocalGateway` | admin transactions pages | | `AdminMonitoringFacade` | `features/admin/monitoring/facade/...` | `AdminMonitoringLocalGateway` | admin monitoring page | | `AdminModerationFacade` | `features/admin/moderation/facade/...` | `AdminModerationLocalGateway` | moderation pages | | `AdminCustomersFacade` | `features/admin/customers/facade/...` | `AdminOrdersLocalGateway` (derives customers from orders) | customers pages | | `AdminAnalyticsFacade` | `features/admin/analytics/facade/...` | orders/products/moderation local + `ADMIN_CATEGORIES_GATEWAY` + `AdminDashboardFacade` | analytics page | | `AdminDashboardFacade` | `features/admin/dashboard/facade/...` | `ADMIN_DASHBOARD_METRICS_GATEWAY`, ProjectEditorFacade, AdminAuthService | admin dashboard | `ProductFacade` public API: `getProducts, getProduct, getCategories, searchProducts, getFeaturedProducts, getLatestProducts, getProductsByCategory, getRelatedProducts, loadRating, loadReviews, loadQuestions, submitReview, submitQuestion, search(criteria), filter, sort, loadCatalog`. `CategoryFacade`: signals (`allCategories, categoryTree, rootCategories, selectedCategory, breadcrumb, children, loading, error`) + `loadCategories, selectCategory, getAllCategories, getCategoryTree, getRootCategories, getCategoryById, getBreadcrumb, getChildren`. `UserExperienceFacade`: `isInWishlist, toggleWishlist, clearWishlist, isInCompare, addToCompare, removeFromCompare, clearCompare, trackRecentlyViewed, saveSearch, removeSavedSearch, saveContinueBrowsing, getContinueBrowsing` + wishlist/compare signals & counts. --- ## 22. Gateway / provider master table | Gateway/provider | Interface path | Mock/local impl | Real/API impl | DI token | Consuming facade(s) | Status | |---|---|---|---|---|---|---| | ConfigProvider | `core/config/config-provider.interface.ts` | `core/bootstrap/providers/mock-bootstrap.provider.ts` | `core/bootstrap/providers/api-bootstrap.provider.ts` | `CONFIG_PROVIDER` | UiRuntime, WebsiteRuntime, ProjectEditor, ContentMgmt, Diagnostics (via ConfigService) | LIVE (`GET /bootstrap`) | | ProductDataProvider | `core/products/providers/product-data-provider.interface.ts` | none bound | `core/products/providers/api-product-data.provider.ts` | `PRODUCT_DATA_PROVIDER` | ProductFacade | LIVE | | CategoryRepository | `core/categories/repositories/category.repository.ts` | none bound | `core/categories/repositories/api-category.repository.ts` | `CATEGORY_REPOSITORY` | CategoryFacade | LIVE | | BackofficeDataProvider | `core/backoffice/providers/backoffice-data-provider.interface.ts` | `mock-backoffice-data.provider.ts` | `api-backoffice-data.provider.ts` | `BACKOFFICE_DATA_PROVIDER` | storefront cards | LIVE (`/api/backoffice/*`) | | UserExperienceRepository | `core/user-experience/repositories/user-experience.repository.ts` | `local-user-experience.repository.ts` | none | `USER_EXPERIENCE_REPOSITORY` | UserExperienceFacade | LOCAL-ONLY | | MediaRepository | `core/media/media-repository.ts` (abstract class) | `core/media/mock-media-repository.service.ts` | none | `MediaRepository` class (app.config.ts) | MediaLibraryFacade | MOCK-SWAPPABLE | | SearchHistoryRepository | `features/search/services/search-history.repository.ts` | (localStorage impl) | none | (injected concretely) | SearchFacade (via SearchHistoryService) | LOCAL-ONLY | | AdminCategoriesGateway | `features/admin/categories/services/admin-categories-gateway.interface.ts` | `admin-categories-local.gateway.ts` | `admin-categories-api.gateway.ts` | `ADMIN_CATEGORIES_GATEWAY` | AdminCategoriesFacade, AdminAnalyticsFacade | MOCK-SWAPPABLE (real impl exists) | | AdminDashboardMetricsGateway | `features/admin/dashboard/services/admin-dashboard-metrics.gateway.interface.ts` | `admin-dashboard-metrics.local.gateway.ts` | none | `ADMIN_DASHBOARD_METRICS_GATEWAY` | AdminDashboardFacade | MOCK-SWAPPABLE (token only) | | AdminOrdersGateway | `features/admin/orders/services/admin-orders-gateway.interface.ts` | `admin-orders-local.gateway.ts` | none | **none** | AdminOrdersFacade, AdminCustomersFacade, AdminAnalyticsFacade | MOCK-ONLY (no seam) | | AdminProductsGateway | `features/admin/products/services/admin-products-gateway.interface.ts` | `admin-products-local.gateway.ts` | none | **none** | AdminProductsFacade, AdminAnalyticsFacade | MOCK-ONLY (no seam) | | AdminUsersGateway | `features/admin/users/services/admin-users-gateway.interface.ts` | `admin-users-local.gateway.ts` | none | **none** | AdminUsersFacade | MOCK-ONLY (no seam) | | AdminTransactionsGateway | `features/admin/transactions/services/admin-transactions-gateway.interface.ts` | `admin-transactions-local.gateway.ts` | none | **none** | AdminTransactionsFacade | MOCK-ONLY (no seam) | | AdminMonitoringGateway | `features/admin/monitoring/services/admin-monitoring-gateway.interface.ts` | `admin-monitoring-local.gateway.ts` | none | **none** | AdminMonitoringFacade | MOCK-ONLY (no seam) | | AdminModerationGateway | `features/admin/moderation/services/admin-moderation-gateway.interface.ts` | `admin-moderation-local.gateway.ts` | none | **none** | AdminModerationFacade, AdminAnalyticsFacade | MOCK-ONLY (no seam) | | (Auth session) | — (`TelegramSessionApiService`) | mock via `mockDataInterceptor` | `services/telegram-session-api.service.ts` | n/a (concrete) | AuthService, AdminAuthService, AuthFacade | LIVE | | (Ed25519 admin auth) | — (`AuthApiService`) | none | `core/auth/services/auth-api.service.ts` | n/a (concrete) | AuthService (Ed25519 flow) | LIVE wiring, backend absent | --- ## 23. Model / DTO catalog Grouped by boundary role. B = backend-shaped/wire DTO, V = frontend view model, C = bootstrap config shape. Adapter column names the mapper if distinct. ### Core wire DTOs / domain (B) - `Item` + supporting (`src/app/models/item.model.ts`) — **primary product wire shape**; adapter `ApiService.normalizeItem()`. - `Category`, `Subcategory` (`src/app/models/category.model.ts`) — legacy category wire; adapter `ApiService.normalizeCategory()`. - `CategoryDto`, `CategoryNameDto` (`src/app/core/categories/dto/category.dto.ts`) — clean-stack wire DTO; adapter `CategoryMapper`. - `Region`, `GeoIpResponse` (`src/app/models/location.model.ts`). - Payment/order DTOs inline in `src/app/services/api.service.ts`: `QrCreateRequest`, `QrCreateResponse`, `CartPaymentRequest`, `CreateOrderRequest`, `CreateOrderResponse`, `QrDynamicStatusResponse`. - Auth: `AuthSession`, `WebSessionStart` (`src/app/models/auth.model.ts`); `AuthChallenge`, `VerifySignatureRequest`, `AuthTokenPair`, `RefreshTokenRequest`, `JwtClaims` (`src/app/core/auth/models/auth-api.model.ts`). ### Domain / view models (V) - Products: `Product`(=Item alias), `ProductListQuery`, `ProductSearchQuery`, `ProductListResult`, `ProductFilters`, `RelatedProductsQuery`, `RelatedProductCollection`, `ProductVariantSelection` (`core/products/models/product-domain.model.ts`). - Engagement: `Review`, `Answer`, `Question`, `RatingSummary`, `RatingDistributionEntry`, `EngagementListQuery`, `EngagementListResult`, `SubmitReviewInput`, `SubmitQuestionInput` (`core/products/models/product-engagement.model.ts`). - Catalog experience: `SearchCriteria`, `FilterDefinition`, `FilterOption`, `SortDefinition`, `CatalogView`, `SearchResult` (`core/products/models/catalog-experience.model.ts`); catalog state (`features/website/catalog/models/catalog-state.model.ts`). - Category domain: `Category`, `CategoryTranslation` (`core/categories/models/category-domain.model.ts`). - Media: `MediaAsset` + params/results (`core/media/models/media-asset.model.ts`). - User experience: `FavoriteItem`, `ComparedProduct`, `RecentlyViewedItem`, `SavedSearch`, `ContinueBrowsingState` (`core/user-experience/models/user-experience.model.ts`). - Search: `search.model.ts` + `search-state.model.ts` (`features/search/models/`, dup in `core/search/models/`). - Content: `ContentPage`, `ContentPageTranslation`, `ContentPageSeoConfig`, `ContentPageStatus`, `ContentPageBootstrapInput`, `LegalPageKey`, `LegalPageDefinition` (`features/content-management/models/`); adapter `ContentPageService`. - Project editor: `ProjectEditorState`, `ProjectEditorSectionId`, `ProjectEditorWidgetPreset`, `BuilderSectionStatus` (`features/project-editor/models/`), `builder-groups.model.ts`. - Diagnostics: `DiagnosticEntry`, `DiagnosticsHealthSummary`, `DiagnosticsReport` (`features/diagnostics/models/diagnostics.model.ts`). - Widgets: contracts in `src/app/widgets/contracts/*` and renderer `*.model.ts` (see §13). ### Admin models (V, all under `features/admin//models/`) - `admin-order.model.ts`: `AdminOrder`, `AdminOrderCustomer`, `AdminOrderPayment`, `AdminOrderShipping`, `AdminOrderItem`, `AdminOrderTimelineEntry`, `AdminOrderStatus`, `AdminOrderPaymentStatus`, `AdminOrderTimelineEventKey`, `AdminOrderListFilters`, `AdminOrdersListResult`. - `admin-product.model.ts`: `AdminProduct` (+ `AdminProductMedia`, `AdminProductSpecification`, `AdminProductVariant(Price)`, `AdminProductVariantAttributeDef`, `AdminProductAttribute`, `AdminProductTranslation`, `AdminProductSeo`, `AdminProductReview`, `AdminProductQuestion`), `AdminProductListFilters`, `AdminProductsListResult`, `AdminProductCategoryOption`, status/sort/mode types. - `admin-category.model.ts`: `AdminCategory`, `AdminCategoryTranslation`, `AdminCategorySeo`, `AdminCategoryAttribute`, `AdminCategoryListFilters`, status/mode types. - `admin-user.model.ts`: `AdminUser`, `AdminRole`, `AdminInvitation`, `AdminSession`, `AdminUserAuditEntry`, scope/status/invitation-status types. - `admin-transaction.model.ts`: `AdminTransaction`, `AdminTransactionAuditEntry`, `AdminTransactionListFilters`, `AdminTransactionsListResult`, type/status types. - `admin-monitoring.model.ts`: `AdminMonitoringEvent`, `AdminMonitoringEventFilters`, `AdminQueue`, `AdminWebhookDelivery`, category/level/queue/webhook status types. - `admin-review.model.ts`: `AdminReview`, `AdminReviewTimelineEntry`, `AdminReviewListFilters`, `AdminReviewsListResult`, status/timeline types. - `admin-report.model.ts`: `AdminReport`, `AdminReportTargetType`, `AdminReportStatus`. - `admin-customer.model.ts`: `AdminCustomer`. - `admin-analytics.model.ts`: `AdminAnalyticsSummary`, `AdminAnalyticsSeriesPoint`, `AdminAnalyticsTopProduct`, `AdminLowStockProduct`, `AdminRecentActivityEntry`, `AdminMarketplaceHealthCheck`, `AdminProductAnalytics(Row)`, `AdminCustomerAnalytics`, `AdminRecommendationCard`, date-range/severity/health types. - `admin-dashboard.model.ts`: `AdminDashboardMetrics`, `AdminDashboardCardState`, `AdminDashboardQuickAction(Id)`, `AdminDashboardActivityEntry`, `AdminDashboardHealthCheck`, `AdminDashboardHomeHealthCheck`, `AdminDashboardDraftField`, `AdminDashboardShortcut`, status types. - Shell: `features/admin/shell/admin-nav.model.ts`. ### Bootstrap config shapes (C) All under `src/app/shared/models/config/` — see §6 for the full list (24 files + barrel). --- ## 24. Endpoint URL literals found in code Marketplace API (relative to base): `/ping`, `/bootstrap`, `/category`, `/category/{id}`, `/items/{id}`, `/items/randomitems`, `/searchitems`, `/cart`, `/orders`, `/purchase-email`, `/regions`, `/websession/{sessionId}`, `/items/{id}/callback`, `/items/{id}/questiion`. Backoffice storefront: `/api/backoffice/products`, `/api/backoffice/categories`. Payment (`qrApiUrl` = `https://qr.vitanova.network/api`): `/qr`, `/qr/dynamic/{partnerId}/{qrId}`, `/card/{partnerId}/{orderId}`. Const partner id `web-97ec-9c57-4dde-9037-3a68f7f83750`. Session auth (`authApiUrl`): `/users/sessions`, `/users/sessions/{id}`. Ed25519 admin auth (`authApiUrl`): `/api/admin/auth/challenge|verify|refresh|logout` (not implemented server-side). Static assets (not backend): `/assets/mock/bootstrap/bootstrap.json`, `/assets/mock/bootstrap/widget-manifest.json`. External (not this platform): `http://ip-api.com/json/...` (geo-IP), `https://api.qrserver.com/v1/create-qr-code/...` (QR image), `https://t.me/{bot}`, `tg://resolve?...`. `mockDataInterceptor` URL matchers (mock mode only): `/ping`, `/users/sessions[/{id}]`, `/category`, `/category/{id}`, `/items/{id}`, `/searchitems`, `/randomitems`, `/cart`, `/websession/{id}[/qr]`, `/qr`, `/items/{id}/callback`, `/purchase-email`, `/qr/payment/{id}`. **No literal `/admin/*`, `/builder/*`, or per-admin-domain backoffice CRUD paths exist in code.** Those live only as `apiEndpoints.{builder,backoffice}` records inside the runtime bootstrap document, and admin gateways are in-memory (they never construct a URL). Any concrete admin CRUD path is therefore a proposal, not a verified literal — consistent with `docs/BACKEND_API.md` Assumption #2. The admin-auth-headers interceptor gates these path **segments** (anticipatory, not called yet): `/admin/`, `/backoffice/`, `/builder/`, `/media/`. --- ## 25. Cross-check against existing docs Skimmed: `docs/BACKEND_API.md` (canonical master spec, CURRENT/PLANNED/FUTURE tagging), `docs/AUTH.md`, `docs/ADMIN.md`, `docs/BACKEND_API_REMAINING_WORK.md`, `docs/architecture/foundation/**`, `docs/backend/BACKEND-INTEGRATION.md`. Agreements (preserve these conventions downstream): - `docs/BACKEND_API.md` already uses `GET /bootstrap`, the `*LocalGateway` → `*ApiGateway` rebind pattern, and frozen auth/payment (ADR-010). Its CURRENT/PLANNED/FUTURE tagging maps cleanly onto LIVE / MOCK-SWAPPABLE / MOCK-ONLY here. - Assumption #2 (builder/backoffice paths are proposals, not literals) is confirmed by code. - `submitQuestion` typo `questiion` and `callback` review path confirmed against code. Discrepancies / things to flag for a human: 1. **`docs/BACKEND_API.md` PLANNED framing implies every admin domain is a token rebind.** In code, only `ADMIN_CATEGORIES_GATEWAY` and `ADMIN_DASHBOARD_METRICS_GATEWAY` are token-bound. Orders, products, users, transactions, monitoring, moderation (and derived customers/analytics) inject the concrete `*LocalGateway` directly — no seam. A backend integration for those requires adding a token first. This should be reconciled in the docs. 2. **Only one real admin API impl exists** (`AdminCategoriesApiGateway`). Everything else admin is mock. Docs that describe admin endpoints as "PLANNED, served by local gateway" are accurate in spirit but the swap ergonomics differ per domain (see #1). 3. **Duplicate `Category` types** (`src/app/models/category.model.ts` vs `core/categories/models/category-domain.model.ts`) and **duplicate `AdminRole`** (auth `permission.model.ts` string-union vs users `admin-user.model.ts` interface) — naming collisions a backend/contract author should be warned about. 4. **Duplicate search models** under `features/search/models/` and `core/search/models/`. 5. **Content-management & project-editor "save/publish" has no client HTTP call.** Docs that imply a builder publish endpoint should tag it FUTURE — there is no `PUT /bootstrap` or builder-write call anywhere in code today; changes live in localStorage drafts + in-memory bootstrap only. 6. `PRODUCT_DATA_PROVIDER` / `CATEGORY_REPOSITORY` token factories return the Api provider even in `mock` mode (no mock class bound) — so `useMockData` does NOT mock products/categories at the provider layer; mocking there relies entirely on `mockDataInterceptor`. Worth noting if a doc claims a mock product provider exists. --- _Generated from source on branch `B2B`. Every path above is repo-relative to `F:\dx\remote\marketplaces\`._