From d84073ee0438a951a99bf13d531a92567f29d2d8 Mon Sep 17 00:00:00 2001 From: vitaliytv Date: Wed, 12 Aug 2026 09:47:15 +0300 Subject: [PATCH] =?UTF-8?q?docs(architecture):=20=D1=81=D1=85=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=89=D0=B5=20relay=20=E2=80=94=20=D1=96=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=20store,=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B7=D0=B2=D0=BE=D0=BB=D0=B5=D0=BD=D1=96=20SQLite=20=D1=96=20?= =?UTF-8?q?PostgreSQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stack.md фіксував «Bun + PostgreSQL», а реалізація в nitra/mt-rust зробила персистентний store на SQLite — канон розійшовся з кодом. Розвʼязання не «переписати PostgreSQL на SQLite», а зняти хибну привʼязку: stack.md за власним фронтматером — шар reference, де вибір бекенда вільний, а нормативним є контракт. Тому названо інтерфейс store зі схемою за access.md і три дозволені реалізації (in-memory, SQLite, PostgreSQL), а умова поставлена одна й перевірна — спільний контрактний набір тестів. Явно зафіксовано, чому це не порушує принцип №10 «один код контракту»: один раз існує семантика операцій store, а не спосіб їх зберігання. --- .changes/260812-0946.md | 5 +++++ .cspell.json | 2 ++ docs/architecture/stack.md | 7 ++++--- docs/log.md | 4 ++++ 4 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 .changes/260812-0946.md diff --git a/.changes/260812-0946.md b/.changes/260812-0946.md new file mode 100644 index 0000000..8d854bb --- /dev/null +++ b/.changes/260812-0946.md @@ -0,0 +1,5 @@ +--- +bump: patch +section: Changed +--- +docs(architecture): сховище relay — інтерфейс store із дозволеними реалізаціями SQLite і PostgreSQL замість жорсткої привʼязки до PostgreSQL; нормативна умова — спільний контрактний набір тестів diff --git a/.cspell.json b/.cspell.json index 5243ce7..c4e05aa 100644 --- a/.cspell.json +++ b/.cspell.json @@ -361,6 +361,8 @@ "низьковажільні", "ноди", "облікується", + "одноінстансний", + "одноінстансного", "однопакетний", "однопострільні", "опробувані", diff --git a/docs/architecture/stack.md b/docs/architecture/stack.md index 9dde2b1..0920fce 100644 --- a/docs/architecture/stack.md +++ b/docs/architecture/stack.md @@ -29,7 +29,7 @@ Changelog: | Desktop-додатки (macOS) | Tauri v2 — тонкий клієнт + lifecycle agent-server | планується | | Mobile (Android) | Tauri v2 — ЛИШЕ клієнт через relay | планується | | `ui/` — спільний фронтенд поверхонь | Vue 3 + Vite, plain JS + JSDoc (БЕЗ TypeScript) | планується | -| `relay/` | Bun-сервіс, plain JS + JSDoc; PostgreSQL | планується | +| `relay/` | Bun-сервіс, plain JS + JSDoc; store — SQLite або PostgreSQL за спільним контрактом | планується | ## Правило одного коду контракту @@ -83,9 +83,10 @@ Changelog: ## Relay-інфраструктура -- Bun + PostgreSQL; auth — інтерфейс `verifySession(token) → {account_id}` із dev-реалізацією (magic tokens), продакшн — Ory Kratos за тим самим інтерфейсом; +- Bun; сховище — **інтерфейс store** зі схемою за [access.md](access.md), дозволені реалізації: in-memory (dev, без персистентності), **SQLite** і **PostgreSQL**. Вибір — питання деплою, не архітектури: SQLite (єдиний файл, без інфраструктури) достатній для одноінстансного relay, PostgreSQL — коли інстансів кілька або сховище має бути керованим окремо від процесу. Обов'язкова умова для будь-якої реалізації — проходити **спільний контрактний набір тестів**: взаємозамінність доводиться однаковою поведінкою, а не однаковим переліком методів. Це не суперечить принципу «один код контракту» ([principles.md](principles.md), №10): контракт store — це схема й семантика операцій ([access.md](access.md), шар `contract`), а бекенд зберігання належить шару реалізації, і саме контрактний набір не дає реалізаціям розійтись; +- Auth — інтерфейс `verifySession(token) → {account_id}` із dev-реалізацією (magic tokens), продакшн — Ory Kratos за тим самим інтерфейсом; - Push: FCM (data-повідомлення трьох типів — див. [access.md](access.md)); модуль за інтерфейсом, dev-заглушка; -- Деплой: Dockerfile (oven/bun) + k8s (Deployment + Service; Postgres — CNPG); +- Деплой: Dockerfile (oven/bun) + k8s (Deployment + Service; SQLite — PVC, PostgreSQL — CNPG); - Ліміти: rate limit на з'єднання, кадр ≤ 2 MB, буфер ≤ 200 Envelope/run. ## Демонізація agent-server diff --git a/docs/log.md b/docs/log.md index 9921bf7..afc4686 100644 --- a/docs/log.md +++ b/docs/log.md @@ -1,5 +1,9 @@ # Журнал змін документації +## 2026-08-12 + +* **Update**: [architecture/stack.md](architecture/stack.md) — сховище relay перестає бути одним названим продуктом: замість «Bun + PostgreSQL» зафіксовано **інтерфейс store** зі схемою за [architecture/access.md](architecture/access.md) і три дозволені реалізації — in-memory (dev), SQLite і PostgreSQL. Привід — реалізація в `nitra/mt-rust`: персистентний store зроблено на SQLite (вбудований `bun:sqlite`, без зовнішньої залежності), і канон розійшовся з кодом. Розв'язання не «переписати PostgreSQL → SQLite», а зняти хибну прив'язку: вибір бекенда — питання деплою (одноінстансний relay проти кількох інстансів), а не архітектури, і `stack.md` за власним фронтматером — шар `reference`, де реалізація вільна. Нормативна умова натомість одна й перевірна: будь-яка реалізація мусить проходити **спільний контрактний набір тестів** — взаємозамінність доводиться однаковою поведінкою, а не однаковим переліком методів (у реалізації цей набір уже відпрацював: він упіймав, що `setMemberRole` мусить бути upsert-ом, інакше accept запрошення тихо ламається). Явно зафіксовано, що це не суперечить принципу «один код контракту» ([architecture/principles.md](architecture/principles.md), №10): один раз існує **семантика** операцій store, а не спосіб їх зберігання. Рядок деплою уточнено (SQLite — PVC, PostgreSQL — CNPG). Запис від 2026-07-11 нижче («PostgreSQL — окрема задача») лишається як історія рішення, а не як чинна норма. + ## 2026-08-09 * **Update**: [architecture/operations.md](architecture/operations.md), [architecture/graph.md](architecture/graph.md), [architecture/runtime.md](architecture/runtime.md) — другий прохід поділу «контракт ↔ реалізація» (перший — запис нижче): конкретні значення виїхали з глав контракту в довідник. Нова підсекція «Дефолти, на які посилаються глави» в operations.md збирає те, що раніше було розсипане інлайн: `model_tier` (`AVG`), `agent_cli`/`MT_AGENT_CLI` (`claude`), `agent_retry_max` (`3`), дефолтний склад `retry_ladder` (базова → `diagnose-first` → `alternative-approach`), ліміт кадру протоколу (2 MB). Туди ж переїхав блок `~/.zshenv` з ENV виконавців — operations.md і так є главою конфігурації, а runtime.md лишає семантику змінних і посилання. Глави тепер називають **ім'я** ключа й дають посилання на значення: у graph.md прибрано «(3)» біля `agent_retry_max`, склад щаблів драбини та приклад мапи моделей; у runtime.md — «(дефолт)» біля `claude`, `→ claude` у ланцюжку резолву та «2 MB» у backpressure. Канонічним джерелом baseline-дефолтів лишається `CONFIG_DEFAULTS` у коді — таблиця в довіднику явно позначена як довідкове дзеркало шару `reference`. Свідомо не чіпали: дефолти полів файлового контракту (`export: true` у `## Children`) — це схема, а не конфіг, і блок ACP-адаптерів у runtime.md — він уже під маркером «Реалізація (не контракт)».