- One codebase, unlimited tenants. No tenant-specific implementation code in the frontend.
- Tenant behavior is controlled entirely by configuration loaded at bootstrap (`GET /bootstrap`, tenant resolved server-side by domain).
- Prefer configuration over conditionals, composition over inheritance.
- Authentication, payment, and authorization contracts/behavior are frozen and must not be redesigned as part of platform work (`docs/architecture/foundation/adr/ADR-010-backward-compatibility-for-auth-payment-authorization.md`).
- No circular dependencies; shared/UI layers are feature-agnostic.
These rules are enforced, not aspirational — see `docs/architecture/foundation/README.md` and the ADR set below, plus `npm run arch:check` (import-boundary + circular-dependency checks).
## Architecture Decision Records (source of truth — read directly, do not treat this file as a paraphrase)
All under `docs/architecture/foundation/adr/`:
- **ADR-001** — platform model (multi-tenant, config-driven).
- **ADR-002** — layered feature architecture.
- **ADR-003** — import boundaries and dependency direction.
- **ADR-004** — configuration bootstrap and provider abstraction.
Component (container) --> Facade --> Domain Service --> Repository/Provider --> Mock | API
```
- **Container/page components** own routing, orchestration, and DI of a facade. They hold no business logic.
- **Presentational components** are `@Input()`/`@Output()`-only: no `HttpClient`, no storage, no environment access, no facade injection (ADR-006). The Project Editor's *sections* (`features/project-editor/sections/*`) are an accepted exception — they are container/section components, not shared presentational UI, so they may inject the facade directly (see `docs/EDITOR.md`).
- **Facades** (`facades/**`, or feature-local `facade/`) are the only thing components talk to. They expose signals/observables and imperative methods; they compose one or more domain services (ADR-007).
- **Domain services** (`core/<domain>/*.service.ts`) convert backend DTOs into domain models via a **mapper**, and expose domain-shaped methods. DTOs never leak past the mapper boundary.
- **Repositories/providers** are swappable via injection tokens (e.g. `PRODUCT_DATA_PROVIDER`, `CATEGORY_REPOSITORY`, `BACKOFFICE_DATA_PROVIDER`, `ADMIN_DASHBOARD_METRICS_GATEWAY`) so mock and real-API implementations can be swapped without touching facades or components — the same pattern used throughout `core/`, `features/admin/*`, and `features/backoffice/*`.
-`ConfigService` loads `BootstrapConfig` (see `docs/BACKEND.md#1-bootstrap`) once at startup; `PlatformRuntimeService` applies it (theme, branding, runtime state) and can `reloadFromBootstrap()` for in-memory preview without a full page reload.
- **Section Engine** (`dynamic-renderer/section-engine/section-engine.service.ts`) builds an ordered page render model from `PageConfig.sections`, applying `order`, `layout` (`SectionLayoutConfig.strategy`: `stack | grid | hero | carousel | split`), and `visibility` (desktop/tablet/mobile).
- **Page Renderer** (`dynamic-renderer/page-renderer/page-renderer.service.ts`) delegates to the Section Engine.
- **Widget Host** (`dynamic-renderer/widget-host/widget-host.service.ts`) resolves each widget's component via the **Widget Manifest** (`widgets/registry/widget-manifest.service.ts`, `widgets/contracts/widget-manifest.contract.ts`) and its data via the **Data Source Resolver** (`widgets/resolvers/data-source-resolver.service.ts`), which delegates to `CategoryFacade`/`ProductFacade` — widgets never call APIs directly.
- Widgets receive only `{ section config, resolved data }` as inputs; they render presentation only, never fetch or mutate.
- Unknown/unregistered widget types render a safe fallback; this is also surfaced in `features/diagnostics` (dev-only, route `/__diagnostics`).
-`dynamic-page-layout.component.ts` (`layouts/containers/`) is the top-level container that composes Section Engine output using `PlatformLayoutConfig.type` (`default | sidebar-left | carousel-home | minimal`).
- Feature resolution falls back across older config surfaces to preserve behavior as the flag model evolved across sprints — see `docs/BACKEND.md#1-bootstrap` for the full field list.