ADR

ADR-006: Live Data Layer для Reality Bridge

ADR-006: Live Data Layer для Reality Bridge

Дата: 2026-06-17 Статус: draft


Контекст

SprosOS строится как конституционно-управляемая система. Текущий фронтенд (63 страницы, System Console, offer flow) работает на localStorage и mock-данных. Для подключения реальных данных (1С, Яндекс.Метрика, сайт) нужен минимальный, но production-sane persistence-слой.

Проблемы текущей модели

  1. localStorage не переживает деплой, очистку браузера, смену пользователя
  2. Данные 1С (каталог: группы, товары, цены, остатки) не помещаются в localStorage
  3. Метрика (трафик по дням × страницам) — табличные данные большого объёма
  4. Sync logs и connector health требуют персистентности
  5. Product Binding (MetaProduct ↔ CatalogProduct ↔ SitePage) — реляционные связи

Решение

Выбор: PostgreSQL (via Neon/Supabase) + API Routes (Next.js)

PostgreSQL — прагматичный минимальный выбор:

  • Реляционная модель идеально подходит для Reality Bridge сущностей
  • Neon/Supabase дают serverless PostgreSQL без администрирования
  • pgvector — опция для будущего semantic слоя
  • Знакомый стек (уже есть в docker-compose проекта)

Альтернативы, которые рассматривались

ВариантProsConsРешение
SQLiteНет сервера, файлНе подходит для cloud-deploy, race conditions
SupabaseHosted Postgres + API + AuthVendor lock, costs✅ fallback
NeonServerless Postgres, branch per PRVendor lock✅ fallback
FirebaseServerlessНе реляционная
Локальный JSON/файлыПростоНет запросов, нет sync, нет ACL

Решение: PostgreSQL, развёрнутый как Docker-контейнер на сервере (мастерхост? другой VPS?) или через Neon/Supabase для быстрого старта.


Архитектура

┌─────────────────────────────────────────────────────┐
│                   Next.js App                        │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────┐  │
│  │  UI Layer   │  │  API Routes  │  │  System   │  │
│  │  (pages)    │◄─┤  /api/v1/    │◄─┤  Console  │  │
│  └─────────────┘  └──────┬───────┘  └───────────┘  │
│                          │                          │
└──────────────────────────┼──────────────────────────┘
                           │ fetch / server action
┌──────────────────────────▼──────────────────────────┐
│               PostgreSQL (Docker/Neon)               │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │ Catalog  │  │ Metrika │  │ Sync Logs        │  │
│  │ Groups   │  │ Metrics  │  │ Connector Health │  │
│  │ Products │  │ Goals    │  │ Bindings         │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└──────────────────────────────────────────────────────┘

Сущности (первая миграция)

См. docs/registries/entity-registry.yaml — Reality Layer секция:

  • CatalogGroup — группа товаров из 1С
  • CatalogProduct — товар/SKU
  • CatalogSyncRun — лог синхронизации
  • SitePage — страница сайта
  • SitePageLink — связка продукт↔страница
  • MetrikaCounter — счётчик
  • TrafficMetricDaily — трафик по дням
  • GoalMetricDaily — цели по дням
  • MetrikaSyncRun — лог синхронизации Метрики
  • MetaProductBinding — связка MetaProduct ↔ Catalog ↔ Site ↔ Metrika
  • ConnectorStatus — статус коннектора

Sync-модель

1С ──(n8n)──►  CatalogSyncRun ──► CatalogGroup/CatalogProduct
                                            │
Метрика ──(api)──► MetrikaSyncRun ──► TrafficMetricDaily / GoalMetricDaily
                                            │
Сайт ──(parse)──► SitePage / SitePageLink ──► MetaProductBinding
  • Каждый sync — отдельная запись с started_at, finished_at, status, records_count
  • ConnectorHealth — last_sync, last_error, uptime

Separation: live vs mock

  • Mock-данные остаются в src/data/mock*.ts — для разработки и UI preview
  • Live-данные в PostgreSQL — source of truth для прода
  • UI сначала пытается читать из live-данных, fallback на mock если не подключено
  • В System Console — переключатель Data Source: Mock / Live

API маршруты (первые)

GET  /api/v1/catalog/groups         — все группы товаров
GET  /api/v1/catalog/products       — товары с фильтрами
GET  /api/v1/catalog/sync/runs      — история синхронизации
GET  /api/v1/metrika/metrics        — метрики по страницам/дням
GET  /api/v1/metrika/sync/runs      — история синхронизации
GET  /api/v1/binding/meta-products  — связки MetaProduct ↔ реальность
GET  /api/v1/system/connectors      — статусы всех коннекторов

Почему не Supabase сразу

  • Supabase — хороший выбор для hosted, но добавляет vendor lock
  • На данном этапе Docker-контейнер на сервере даёт больше гибкости
  • Миграция на Supabase — всегда опция, если Docker-хостинг неудобен

Исполнение

  1. Создать миграцию с Reality Layer таблицами (Alembic / Prisma / raw SQL)
  2. Развернуть PostgreSQL (Docker или Neon)
  3. Создать API routes /api/v1/catalog/*, /api/v1/metrika/*, /api/v1/system/connectors
  4. Обновить UI — заменить чтение из localStorage на чтение из API
  5. Добавить fallback на mock в админке
  6. Добавить в System Console: переключатель источника, статусы

Решение

PostgreSQL как базовый live data layer.
n8n как оркестратор sync для 1С (или прямой Python worker).
API Routes в Next.js для чтения данных.
✅ Mock-данные сохраняются как development fallback.
✅ Адресация — connector registry → API → DB.


Связанные документы

  • docs/reports/REPORT-LIVE-CONNECTORS-AUDIT.md — что вообще есть
  • docs/registries/entity-registry.yaml — entity definitions
  • docs/registries/connector-registry.yaml — connector definitions
  • docs/dna/product-dna.yaml — продуктовая DNA