# White Label CMS — Architecture Blueprint

**Product:** Enterprise White Label Digital Marketing CMS
**Owner:** 18Pixels
**Stack:** PHP 8.3 · MySQL 8 · Apache · Tailwind · Alpine.js · No framework
**Document status:** Living document — updated at the end of every phase.

---

## 1. Purpose & Principles

This is a **reusable commercial CMS**, not a website or a template. A single
installation must produce unlimited, fully-distinct digital-agency websites by
changing data only (brand, colours, fonts, menus, content, SEO, integrations) —
never code.

Every design decision serves five non-negotiable properties:

1. **Reusable** — one codebase, many tenants. Anything brand-specific lives in
   the database or `.env`, never in source.
2. **Scalable** — stateless request handling, lazy connections, cache-friendly
   rendering, and a layered design that lets modules grow independently.
3. **Secure by default** — prepared statements everywhere, CSRF on every mutating
   request, hardened sessions, output escaping, a strict CSP, and audit logging.
4. **SEO / AEO / GEO first** — every public URL emits complete metadata, schema,
   and machine-readable answer structures from a central SEO service.
5. **Customisable from the admin panel** — configuration is data; the UI edits
   the data.

### Engineering standards

- PSR-4 autoloading, PSR-12 code style, `declare(strict_types=1)` in every file.
- No framework. A small, owned core provides MVC, DI, routing, and data access.
- Repository pattern for data access; service layer for business logic; thin
  controllers.
- No demo code, no placeholder content, no `TODO` comments, no lorem ipsum in
  committed source. Every file is complete and production-intent.

---

## 2. High-Level Architecture

```
HTTP request
    │
    ▼
public/index.php  ──►  Application (kernel)
                          │  loads .env, config, DI bindings, error handling
                          ▼
                       Router  ──► Middleware pipeline ──► Controller
                          │                                     │
                          │                                Service layer
                          │                                     │
                          │                                Repository
                          │                                     │
                          │                                Connection (PDO)
                          ▼                                     ▼
                       Response  ◄───  View (native PHP templates)  MySQL 8
```

### Layers

| Layer | Responsibility | Location |
|------|-----------------|----------|
| Kernel | Bootstrap, DI container, config, errors | `src/Core` |
| HTTP | Request, Response, Router, Controller, View, Middleware | `src/Core/Http`, `src/Middleware` |
| Domain services | Business logic, orchestration | `src/Services` |
| Repositories | Data access behind intent-revealing methods | `src/Repositories` |
| Data | PDO connection, query builder, migrations | `src/Core/Database` |
| Security | Hashing, CSRF, sessions, sanitisation | `src/Core/Security` |
| Presentation | Layouts, pages, partials | `resources/views` |

---

## 3. Request Lifecycle

1. `public/index.php` loads the autoloader (Composer, or the dev fallback) and
   instantiates `Application` with the project root.
2. The kernel loads `.env`, builds the `Config` repository from `config/*.php`,
   sets the timezone/encoding/bcrypt cost, and registers the global error handler.
3. Core services are registered as singletons in the DI container.
4. `boot()` loads `routes/web.php` and `routes/api.php` into the `Router`.
5. `run()` starts the session, captures the `Request`, and dispatches it.
6. The `Router` matches a `Route`, then runs the request through the route's
   **middleware pipeline** (e.g. `SecurityHeaders`, `VerifyCsrfToken`) to the
   controller action, resolving parameters via the container.
7. The action returns a `Response` (HTML via `View`, or JSON). Unmatched routes
   raise `HttpException` (404/405); any throwable is caught and rendered by the
   `ExceptionHandler` (developer trace in debug, branded page/JSON in production).
8. `Response::send()` emits status, headers, cookies, and body.

---

## 4. Core Components (Phase 1 — built)

- **Container** — constructor autowiring via reflection, singletons, aliases,
  and callable invocation with dependency resolution.
- **Config** — dot-notation access over the merged `config/` tree.
- **Env** — dependency-free `.env` parser (quotes, inline comments, `${VAR}`).
- **Router / Route** — verb methods, groups (prefix + shared middleware), named
  routes with reverse generation, `{param}` and `{param:regex}` constraints,
  automatic HEAD, and 404/405 discrimination.
- **Request / Response** — immutable request capture (JSON bodies, method
  spoofing, proxy-aware IP); fluent response builder with hardened cookies.
- **View** — native PHP templates with layout inheritance (`extend`), named
  `section`/`yield`, partial `include`, and escaping helpers.
- **Connection / QueryBuilder / Repository** — lazy PDO, injection-safe fluent
  builder (identifier whitelisting + bound values only), base repository with
  pagination, transactions.
- **Migrator** — timestamped migrations with a ledger table, batches,
  rollback, and `fresh`.
- **Security** — `Hash` (bcrypt, rehash detection), `Csrf` (per-session tokens,
  constant-time verify), `Session` (hardened cookies, fixation rotation, flash),
  `Sanitizer` (typed input normalisation, slugs).
- **Logger** — PSR-3-style daily/single channels with retention pruning.
- **ExceptionHandler** — unified error/exception/shutdown handling.

---

## 5. Database Strategy

- MySQL 8, InnoDB, `utf8mb4_unicode_ci` throughout.
- All access through prepared statements; identifiers validated and back-tick
  quoted; user values only ever bound, never interpolated.
- Schema evolves exclusively through migrations under `database/migrations`.
- Core schema (Phase 1): `roles`, `permissions`, `users`, `permission_role`,
  `personal_access_tokens`, `password_resets`, `login_attempts`, `settings`,
  `activity_logs`, plus the `migrations` ledger.
- White-label configuration lives in `settings` (grouped key/value with type
  and public/private visibility), so a new tenant is a data change, not a
  deployment.

---

## 6. Security Model

| Threat | Control |
|--------|---------|
| SQL injection | Prepared statements + identifier whitelisting |
| XSS | Output escaping (`e()` / `View::escape`) + strict CSP |
| CSRF | Per-session token on all POST/PUT/PATCH/DELETE |
| Session fixation | Id regeneration on interval and on login |
| Credential theft | bcrypt (cost ≥ 12), rehash on cost change |
| Clickjacking | `X-Frame-Options` + `frame-ancestors` |
| Brute force | `login_attempts` tracking + rate-limit config (enforced in auth phase) |
| Information leak | Debug forced off in production; safe error messages |
| Auditability | `activity_logs` for security-relevant events |

API authentication uses JWT (config in `config/security.php`) and/or hashed
personal access tokens, implemented in the authentication phase.

---

## 7. Module Roadmap

The build proceeds in phases; each phase must lint and boot before the next.

1. **Foundation core** ✅ — kernel, HTTP, data, security, error handling.
2. **Auth & RBAC** — login/JWT, password reset, roles/permissions enforcement,
   admin shell, rate limiting, activity logging.
3. **Settings & White-Label** — browser-based `/install` wizard (no-SSH setup),
   settings service, theme/brand manager, media library, cache.
4. **Content engine** — pages, page builder, menus, header/footer builders,
   blog, portfolio, testimonials, team, case studies.
5. **Business modules** — services, industries, pricing, FAQs, CRM & lead
   pipeline, newsletter, email marketing, SMTP.
6. **SEO / AEO / GEO** — meta + schema generator, sitemaps, redirects, robots,
   internal linking, answer/PAA blocks, AI-overview optimisation.
7. **Ops & QA** — analytics dashboard, backups, maintenance mode, API keys,
   security settings, hardening, automated tests, documentation.

Detailed per-file tracking lives in `PROJECT_CHECKLIST.md`.

---

## 8. Conventions

- Namespaces: `App\Core\*` (framework), `App\Controllers\*`, `App\Services\*`,
  `App\Repositories\*`, `App\Models\*`, `App\Middleware\*`.
- One class per file, file named after the class.
- Configuration read only via `config()` / `Config`; environment only via
  `env()` / `Env` at config-build time.
- Controllers return `Response`; they never `echo` or `header()` directly.
- All state-changing forms include `csrf_field()`.
