# BOTz Cloner ☕︎ architecture

## Request boundaries

| Boundary | Guard/middleware | Responsibility |
| --- | --- | --- |
| Public landing | none | Brand, Google-only entry point |
| User OAuth | `throttle:google-auth` + Socialite state | Find/create a user by unique Google provider ID |
| User workspace | `auth`, `active.user`, `platform.available` | Own dashboard, templates, bot lifecycle |
| Bot connection | `throttle:bot-connect`, Form Request, policy | `getMe` → duplicate check → instance/settings → webhook verify |
| Telegram webhook | `throttle:telegram-webhook`, CSRF exception, secret header | Identify bot → idempotent update row → trusted module handler |
| Admin | `admin.session`, `admin.password` | Separate credentials, forced first-password change, audited controls |

## Route contract

### User

- `GET /` — landing page
- `GET /auth/google` — Socialite redirect
- `GET /auth/google/callback` — state-validated callback
- `GET /dashboard` — user dashboard
- `GET /bots/create` / `POST /bots` — template selection and connection
- `GET /bots/{bot}` — policy-protected bot detail
- `PUT /bots/{bot}/settings` — schema-validated module settings
- `PATCH /bots/{bot}/status` — enable/disable
- `POST /bots/{bot}/reconnect` — reconfigure and verify webhook
- `DELETE /bots/{bot}` — delete Telegram webhook and instance
- `POST /logout` — invalidate user session

### Admin

- `GET /admin/login` / `POST /admin/login` — separate admin guard
- `GET /admin` — metrics and activity overview
- `/admin/users` — search, view, suspend, activate
- `/admin/templates` — import, review, publish, archive
- `/admin/bots` — operational bot inventory
- `/admin/activity` — audit log
- `/admin/settings` — safe site/platform controls and OAuth readiness
- `/admin/profile` — admin email/name
- `/admin/profile/password` — password change / forced bootstrap change

### Telegram

- `POST /telegram/webhook/{public_identifier}` — centralized endpoint. The identifier is an opaque UUID and the request must include the per-bot `X-Telegram-Bot-Api-Secret-Token` generated during setup.

## Connection sequence

1. `ConnectBotRequest` validates template ID, token shape, internal name, and configuration array.
2. The selected template must be `published`.
3. `ModuleRegistry` resolves the template's `module_identifier` from an explicit trusted class allow-list.
4. `TelegramService::getMe()` validates the token without returning it to the browser.
5. `telegram_bot_id` is checked globally. An ID owned by another user is rejected without disclosing owner details.
6. The instance is created/updated inside a database transaction with an encrypted token and encrypted module settings.
7. `WebhookService` creates a random encrypted secret, calls `setWebhook`, then calls `getWebhookInfo`.
8. The instance becomes `active` only when the URL matches and Telegram reports no webhook error.
9. The activity event records identifiers and template metadata only; the logger redacts token/secret/password-like keys.

## Module contract

`BotModuleInterface` defines metadata, defaults, a configuration schema, validation, permissions, supported update types, and `handleUpdate`. A module is application code deployed by the operator, not user-uploaded executable code.

`ModuleImportService` accepts `bot.json` or a ZIP containing a root `bot.json`/`manifest.json`, reads bytes only, validates JSON, and resolves the identifier against `config/botz.php`. It never extracts an archive, includes a path, uses `eval`, or registers a class from user input. The default registry includes `AutoReactionModule`, `LinkRemoverModule`, and `AiChatModule`; the latter calls `AiChatService` with `AI_CHAT_ENDPOINT`, `AI_CHAT_GEM_ID`, and a server-only `AI_CHAT_API_KEY`.

## Webhook sequence

1. Reject oversized request bodies.
2. Resolve the opaque bot identifier.
3. Compare the Telegram secret header with the encrypted per-bot secret using `hash_equals`.
4. Ignore disabled/unknown/duplicate updates with HTTP 200 so Telegram does not retry endlessly.
5. Encrypt the update payload and insert an `(bot_instance_id, update_id)` unique record.
6. Resolve the module through the trusted registry and process in the request.
7. Mark the update processed/failed and update safe bot health timestamps.
8. Return HTTP 200 quickly. No permanent workers or per-bot processes are used.

## Data invariants

- `users.google_id`, `users.email`, `admins.email`, `bot_templates.slug`, `bot_templates.identifier`, `bot_instances.public_identifier`, and `bot_instances.telegram_bot_id` are unique.
- A normal user has no password column or local password flow.
- `bot_instances.user_id` is always policy-checked for user routes.
- Telegram tokens, webhook secrets, module settings, Google metadata, and Telegram payloads are encrypted columns/casts.
- `telegram_updates` is idempotent per bot/update ID.
- Admin seed is `firstOrCreate`, so re-running the seeder does not reset a production password.
