Compiled from
raw/architecture-docs/app-README.md
Lexery - U1 Gateway
Роль у Pipeline
U1 — вхідна точка всього Brain: приймає запити від control plane, перевіряє авторизацію, нормалізує вхідні дані, зберігає вкладення й створює запис run у Supabase. Стадія цілком детермінована (без LLM), слугує єдиним local boundary між зовнішнім світом і внутрішнім pipeline.
Кожен запит POST /v1/runs проходить такий шлях: auth → rate-limit → attachment processing → runs INSERT (status Intake) → enqueue до BullMQ → відповідь клієнту з run_id. Додатково сервер відповідає на GET /health для liveness / readiness.
Code Surfaces
apps/brain/gateway/auth.ts— перевіркаDEV_API_KEYіDEV_ALLOW_ANONYMOUSmodeapps/brain/gateway/handler.ts— основний HTTP handler дляPOST /v1/runsapps/brain/gateway/attachments.ts— обробка вкладень, byte caps, overflow до R2apps/brain/gateway/storage.ts— persistence run record у Supabaserunsтаблиціapps/brain/gateway/queue*.ts— enqueue до Redis / BullMQ для U2
Конфігурація
| Ключ | Призначення | Приклад |
|---|---|---|
BRAIN_PORT | HTTP порт Brain сервера | 3081 |
DEV_API_KEY | API ключ для dev-середовища | string |
DEV_ALLOW_ANONYMOUS | Дозволити запити без ключа (dev only) | true / false |
RUNS_PER_MINUTE | Rate limit: max runs на хвилину | числове |
MAX_CONCURRENT_RUNS | Обмеження одночасних runs у pipeline | числове |
QUERY_R2_THRESHOLD_BYTES | Поріг byte для overflow query у R2 | числове |
Rate-limiting працює per-tenant: RUNS_PER_MINUTE і MAX_CONCURRENT_RUNS перевіряються до створення run. При перевищенні — HTTP 429 без запису в базу.
Supabase runs Record
При intake U1 створює запис з такими ключовими колонками:
id— internal auto-increment PKrun_id— UUID, зовнішній ідентифікатор run (повертається клієнту)tenant_id— ідентифікатор тенанта (з auth token або dev override)user_id— ідентифікатор користувача (nullable для anonymous)query— оригінальний текст запиту; при перевищенніQUERY_R2_THRESHOLD_BYTESтіло мігрує до R2, у колонці лишається refstatus—Intakeна створення, далі змінюється lifecycle при проходженні stagesattachments_manifest— JSONB з метаданими вкладень (MIME, розмір, R2 key)idempotency_key— optional клієнтський ключ для запобігання дублікатам
Підтримка idempotency key: якщо клієнт передає однаковий ключ повторно, U1 повертає існуючий run_id замість створення нового запису — критично для retry-safe інтеграцій з api.
Attachment Processing
Вкладення проходять:
- Byte-cap перевірка — максимальний розмір кожного файлу з конфігу; перевищення → rejection.
- Run-scoped R2 upload — кожен attachment зберігається під префіксом
runs/{run_id}/attachments/у Cloudflare R2. - Manifest запис —
attachments_manifestJSONB уrunsтаблиці містить масив{filename, mime_type, size_bytes, r2_key}для downstream stages. - Query overflow — якщо
queryперевищуєQUERY_R2_THRESHOLD_BYTES, тіло запиту також мігрує в R2 з ref у колонці.
Runtime Behavior
Auth modes: production — bearer token через apps/api; dev — DEV_API_KEY header або DEV_ALLOW_ANONYMOUS. Handler перевіряє auth першим і відхиляє запит до будь-якого I/O.
Dry-run: частина контракту — клієнт може передати dry_run: true, і U1 створить run з відповідним прапорцем, який downstream stages (U2, U3) перевіряють для skip або mock поведінки.
Enqueue: після успішного запису handler ставить BullMQ job із run_id до черги U2 (RUN_U2). Redis connection переиспользовується між requests для low-latency enqueue.
Test Coverage
| Тест | Фокус |
|---|---|
test_attachment_units.ts | byte caps, MIME validation, R2 upload, manifest |
test_queue_units.ts | BullMQ enqueue, job data, retry semantics |
test_redis_queue_units.ts | Redis connection handling, queue isolation |
test_run_view_units.ts | Run record creation, idempotency key dedup |
test_storage_history_units.ts | Storage persistence, query overflow to R2 |
Failure Modes
- Supabase I/O: якщо INSERT в
runsне пройшов — HTTP 500 без enqueue; клієнт може retry з idempotency key. - Redis / BullMQ: якщо enqueue впав після INSERT — run залишається в status
Intakeбез просування; Health Dashboard показує такі «застряглі» runs. - Rate limit: перевищення лімітів → HTTP 429; run не створюється.
- Attachment rejection: byte-cap або MIME validation fail → HTTP 400 з описом помилки.
Історична еволюція
Legacy bridge repo мав окремий U1 Gateway/Intake + R2 bucket migration. Linear трекав dry-run harness і R2 attachment flow як first-class implementation tasks. Поточна версія зберігає run state переважно через additive snapshot fields, а не через розростання колонок у runs — це дозволяє гнучко додавати нові поля без міграцій.
Key Risk
У міру зрілості production-інтеграцій U1 має перестати бути переважно dev-friendly intake і стати суворішим bridge від apps/api control plane: формальна валідація контрактів, tenant isolation, structured error responses.