# System Architecture

This document details the high-level design, layers, request lifecycle, and performance/security boundaries of the **TFB Engine**.

---

## 1. System Goal & Constraints

TFB Engine (Telegram Funnel Builder Bot) is a specialised marketing-funnel engine built on Telegram.
It is architected to run on cheap **shared cPanel hosting** under a **webhook-only** lifecycle (no long polling) with:
* **Zero Runtime Composer Dependencies:** Works natively on PHP 8.1+ with basic MySQL/MariaDB.
* **Low Query Footprint:** Lazy database connections and caching are used to avoid redundant queries on hot webhook paths.
* **No Heavy Framework:** A lightweight MVC structure built from scratch on SOLID, OOP, and PSR-4 conventions.

---

## 2. High-Level Request Lifecycle

Current callback hot path: `public/index.php` → authenticated middleware/update dedupe/rate-limit/user resolve → `UpdateRouter` → admin or quiz callback dedupe/authz → early `answerCallbackQuery` → DB mutation/render → one normal message edit → HTTP 200. `Tfb\\Logging\\PerfTrace` can measure boot, middleware, handler, DB, Telegram, ACK and total timing when explicitly enabled.

```
Telegram Webhook (POST) → public/index.php
  → WebhookKernel::build() (Wires the entire DI container & pipeline)
  → WebhookPipeline (Executes middleware in strict order)
  → UpdateRouter (Parses command/callback/text, dispatches to the correct controller)
    → Controller (Extracts values, validates, delegates to underlying Service)
      → Service (Orchestrates business logic and transactional flows)
        → Repository (Executes prepared SQL statements only)
          → Database (Reuses a single lazy PDO connection)
```

---

## 3. Directory Map & Responsibility Layers

| Layer | Directory | Responsibility |
|---|---|---|
| **Entry Points** | `public/` | HTTP entry points: `index.php` (webhook + health), `install.php` (one-time setup), `secure-setup.php` (secure settings changer). |
| **Bootstrap** | `bootstrap/` | Class autoloader, container/DI wiring, global helper functions. |
| **Core Primitives** | `src/Core/` | Framework-ish components: `App`, `Config`, `Container`, `Database`, `Request`, `Response`, and custom exceptions. |
| **Transport / Bot** | `src/Bot/` | `TelegramClient`, `Update` DTO, webhook pipeline, `UpdateRouter`, and keyboard builders. |
| **Middleware** | `src/Middleware/` | Security and gating: payload constraints, webhook secret verification, maintenance mode, user resolve, rate limiter, and ban check. |
| **Controllers** | `src/Controllers/` | Parses intent, checks authorization, and delegates. *Never contains raw SQL.* |
| **Services** | `src/Services/` | Core business orchestration, validation rules, cache invalidations, and transactions. |
| **Repositories** | `src/Repositories/` | **Only place where SQL is written.** Reuses prepare-statements. |
| **Models** | `src/Models/` | Dumb, typed data transfer objects containing `fromRow` and `toArray`. |
| **Engines** | `src/Engines/` | Pure business algorithms: `ProfileScoreEngine`, `WinnerSelector`, `BranchResolver`, and callback codecs. |
| **Logging** | `src/Logging/` | Centralized diagnostic logging facade (`Diagnostic`), secret-redaction rules (`Redaction`), and global error handling (`GlobalErrorHandler`). |

---

## 4. Webhook Security Middleware Chain

Every webhook POST goes through this strict chain (`src/Middleware/`):
1. **`BodyGuardMiddleware`:** Enforces 1MB size limit and decodes raw JSON to `Update`.
2. **`WebhookAuthMiddleware`:** Checks the `X-Telegram-Bot-Api-Secret-Token` header using constant-time comparison (`hash_equals`). This blocks fake/spoofed webhooks.
3. **`MaintenanceMiddleware`:** Gated by `settings.maintenance_enabled`. Non-admins see `maintenance_text`; admins bypass it.
4. **`RateLimitMiddleware`:** Fixed-window limit per user ID. Admins get a significantly higher limit.
5. **`PrivateChatMiddleware`:** Ignores group/channel updates; only private chats are allowed.
6. **`UserResolveMiddleware`:** Creates/resolves the user row, updating `last_interaction_at` and injecting the user into the `WebhookContext`.
7. **`BanCheckMiddleware`:** Aborts immediately if the user is marked `is_banned = 1` in the database.

---

## 5. Sticky Workspace Message Lifecycle (Admin UI)

To provide a professional, spam-free experience, the Telegram admin panel is modeled as a **sticky in-place workspace message**:
* **Tracking:** The active surface `message_id` is saved in `users.admin_workspace_message_id`.
* **In-Place Edits:** All list, detail, and wizard menus edit this workspace message directly (`editMessageText` + `editMessageReplyMarkup`). The bot never sends a new menu message on click.
* **Automatic Cleanup:** Prompt messages (asking for input) and the user's input messages are automatically deleted (`deleteMessage`) centrally in the message/callback dispatchers upon successful transition, leaving the workspace as the only control message.
* **Self-Healing Fallback:** If editing the workspace message fails (manually deleted/too old), the system sends exactly one new message, saves its ID to `admin_workspace_message_id`, and continues.

---

## 6. Student In-Place Question Loop (Student UI)

The student quiz flow is engineered to feel like an interactive web app while avoiding chat pollution:
* **Inline Options Only:** Options are rendered as full-width inline buttons. No bottom reply keyboards are shown.
* **In-Place Edits:** Answering a question edits the *same* question message in place (`editMessageText`) to render the next question.
* **Anti-Race Protection:** Double-submit/double-tap races are prevented via `ProcessedCallbackRepository::tryClaim()` on callback query ID and `claimQuestionForAnswer` which atomically clears `current_question_id` for the session.

---

## 7. Scale-Safe Broadcast Queue

Bulk operations are never processed inside a single request loop:
* **Population:** Targets are populated into `broadcast_job_items` using a set-based SQL `INSERT...SELECT`.
* **Pumping:** Broadcasts are processed in small batches (using `pump()`) called by the dispatcher or a system cron job (`bin/pump.php`).
* **Time Budgeting:** Pumping is leased (`acquireLease`) and bounded by a 3-second wall-clock budget per batch to ensure workers never hang or hit host timeouts.
* **Progress Throttling:** Live progress editing of the admin status message is throttled (every N items) to respect Telegram's message-edit limits.
