diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index d7bd6d8..0c9a228 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,27 +1,28 @@ -# System Architecture Overview +# Обзор архитектуры системы -This document is the single source of truth for the platform’s architecture, protocols, data flows, and operational details. It supersedes previous scattered docs. +Этот документ — единый и актуальный источник информации по платформе: архитектура, протоколы, данные, конфигурация, сценарии, эксплуатация. Заменяет собой разрозненные и устаревшие документы. -## Contents -- Components & Topology -- Decentralized Layer (Membership, Replication, Metrics) -- Upload/Conversion Pipeline -- Content View & Purchase Flow -- API Surface (selected endpoints) -- Data Keys & Schemas -- Configuration & Defaults -- Observability & Metrics -- Sequence Diagrams (Mermaid) +## Содержание +- Компоненты и топология +- Децентрализованный слой (членство, оценка размера сети, репликации, метрики) +- Загрузка и конвертация контента +- Просмотр и покупка контента (UI/UX требования) +- API (ключевые эндпойнты и полезная нагрузка) +- Ключи и схемы данных (DHT) +- Конфигурация и значения по умолчанию +- Наблюдаемость и метрики +- Диаграммы последовательностей (Mermaid) +- Сборка и тестирование --- -## Components & Topology +## Компоненты и топология -- Backend API: Sanic-based service (Telegram bots embedded) with PostgreSQL (SQLAlchemy + Alembic). -- Storage: Local FS for uploaded/derived data; IPFS used for discovery/pinning; tusd for resumable uploads. -- Converter workers: Dockerized ffmpeg pipeline (convert_v3, convert_process) driven by background tasks. -- Frontend: Vite + TypeScript client served via nginx container. -- Decentralized overlay (in-process DHT): Membership, replication lease management, windowed content metrics. +- Backend API: сервис на Sanic (Python) с бота́ми Telegram; база данных PostgreSQL (SQLAlchemy + Alembic). +- Хранилище: локальная ФС (uploads/derivatives); IPFS (kubo) для ретривания/пининга; tusd (resumable upload). +- Конвертеры: воркеры (ffmpeg) в контейнерах — `convert_v3`, `convert_process`. +- Frontend: SPA (Vite + TypeScript), отдается nginx-контейнером. +- Децентрализованный слой: встроенный DHT (в процессе) — членство, лизы реплик, метрики контента. ```mermaid flowchart LR @@ -29,7 +30,7 @@ flowchart LR Frontend -- REST --> API[Backend API] API -- tus hooks --> tusd API -- SQL --> Postgres - API -- IPC --> Workers[Converter Workers] + API -- IPC --> Workers[Converters] API -- IPFS --> IPFS API -- DHT --> DHT[(In-Process DHT)] DHT -- CRDT Merge --> DHT @@ -37,183 +38,238 @@ flowchart LR --- -## Decentralized Layer +## Децентрализованный слой -### Identity & Versions -- NodeID = blake3(Ed25519 public key), ContentID = blake3(encrypted_blob) -- schema_version = v1 embedded into DHT keys/records. +### Идентификаторы и версии +- NodeID = blake3(Ed25519 публичного ключа) — шестнадцатеричная строка (256 бит). +- ContentID = blake3(зашифрованного блоба) — неизменяемый идентификатор контента. +- schema_version = v1 — фиксируется во всех DHT-ключах/записях. -### Membership -- Signed `/api/v1/network.handshake` with Ed25519; includes: - - Node info, capabilities, metrics, IPFS metadata. - - reachability_receipts: (issuer, target, ASN, timestamp, signature). -- State: LWW-Set for members + receipts, HyperLogLog for population estimate. -- Island filtering: nodes with `reachability_ratio < q` are excluded (`k=5`, `q=0.6`, TTL=600s). -- N_estimate: `max(valid N_local reports)` across sufficiently reachable peers. +### Членство (membership) +- Рукопожатие `/api/v1/network.handshake` — запрос подписан Ed25519; верифицируется на стороне получателя. Без корректной подписи — 400 BAD_SIGNATURE. +- Полезная нагрузка включает: сведения о ноде (версия, возможности, IPFS), метрики, массив известных публичных нод, квитанции достижимости (reachability_receipts: issuer, target, ASN, timestamp, signature). +- Состояние членства — CRDT LWW-Set (добавления/удаления) с TTL (`DHT_MEMBERSHIP_TTL=600` сек), плюс HyperLogLog для оценки мощности (N_local). +- Фильтрация «островов»: ноды с `reachability_ratio < q` (по умолчанию `q=0.6`) исключаются при вычислении N_estimate и выборе реплик. +- Итоговая оценка `N_estimate = max(валидных N_local от пиров)`. -### Replication & Leases -- Compute prefix `p = max(0, round(log2(N_estimate / R_target)))` with `R_target ≥ 3`. -- Responsible nodes: first `p` bits of NodeID equal first `p` bits of ContentID. -- Leader = min NodeID among responsible. -- Leader maintains `replica_leases` with TTL=600s and diversity: ≥3 IP first octets and ≥3 ASN if available. -- Rendezvous ranking: blake3(ContentID || NodeID) for candidate selection. -- Heartbeat interval 60s, miss threshold 3 → failover within ≤180s. +```mermaid +sequenceDiagram + participant A as Узел A + participant B as Узел B + A->>B: POST /network.handshake {nonce, ts, node, receipts, signature} + B->>B: верификация ts/nonce, подписи + B->>B: upsert member; merge(receipts) + B-->>A: {node, known_public_nodes, n_estimate, server_signature} + A->>A: merge; N_estimate = max(N_local, полученные) +``` -### Metrics (Windowed CRDT) -- On view: PN-Counter for views; HyperLogLog for uniques (ViewID = blake3(ContentID || device_salt)); G-Counter for watch_time, bytes_out, completions. -- Keys are windowed by hour; commutative merges ensure deterministic convergence. +### Репликации и лизы +- Выбор префикса: `p = max(0, round(log2(N_estimate / R_target)))`, где `R_target ≥ 3` (по умолчанию 3). +- Ответственные ноды: чьи первые `p` бит NodeID совпадают с первыми `p` бит ContentID. +- Лидер — минимальный NodeID среди ответственных. +- Лидер выдаёт `replica_leases` (TTL=600 сек), соблюдая разнообразие: не менее 3 разных первых октетов IP и, если доступно, 3 разных ASN. +- Ранжирование кандидатов — rendezvous score `blake3(ContentID || NodeID)`. +- Сердцебиение (heartbeat) держателей — каждые 60 сек; 3 пропуска → признать down и переназначить ≤180 сек. +- Недобор/перебор фиксируются в `conflict_log` и прометеус‑метриках. ```mermaid stateDiagram-v2 [*] --> Discover - Discover: Handshake + receipts - Discover --> Active: k ASN receipts & TTL ok - Active --> Leader: Content prefix p elects min NodeID - Leader --> Leased: Assign replica_leases (diversity) - Leased --> Monitoring: Heartbeats every 60s - Monitoring --> Reassign: Missed 3 intervals + Discover: Рукопожатия + квитанции + Discover --> Active: TTL & кворм ASN + Active --> Leader: Выбор лидера префикса p + Leader --> Leased: Выдача лизов (diversity) + Leased --> Monitoring: Heartbeat 60s + Monitoring --> Reassign: 3 пропуска Reassign --> Leased ``` +### Метрики (окна) +- На событии просмотра формируются дельты CRDT: + - PN‑Counter — количество просмотров; + - HyperLogLog — уникальные ViewID (ViewID = blake3(ContentID || соль_устройства)); + - G‑Counter — watch_time, bytes_out, количество завершений. +- Окно по часу (`DHT_METRIC_WINDOW_SEC`), ключ `MetricKey = blake3(ContentID || WindowID)`. +- Мерджи коммутативные, детерминированные. + --- -## Upload & Conversion Pipeline +## Загрузка и конвертация контента -1) Client uploads via `tusd` (resumable). Backend receives hooks (`/api/v1/upload.tus-hook`). -2) Encrypted content is registered; converter workers derive preview/low/high (for media) or original (for binaries). -3) Derivative metadata stored in DB and surfaced via `/api/v1/content.view`. +1) Клиент грузит в `tusd` (resumable). Бэкенд получает HTTP‑hooks `/api/v1/upload.tus-hook`. +2) Создается запись в БД для зашифрованного контента, воркеры размещают производные: + - для медиа — preview/low/high; + - для бинарей — оригинал (доступен только при наличии лицензии). +3) `/api/v1/content.view` возвращает `display_options` и агрегированное состояние конвертации/загрузки. ```mermaid sequenceDiagram - participant C as Client + participant C as Клиент participant T as tusd - participant B as Backend - participant W as Workers + participant B as Бэкенд + participant W as Воркеры participant DB as PostgreSQL - C->>T: upload chunks + C->>T: upload T->>B: hooks (pre/post-finish) - B->>DB: create content record - B->>W: enqueue conversion - W->>DB: store derivatives + B->>DB: create content + B->>W: очередь конвертации + W->>DB: derive/previews C->>B: GET /content.view - B->>DB: resolve latest derivatives + B->>DB: resolve derivatives B-->>C: display_options + status ``` --- -## Content View & Purchase Flow +## Просмотр и покупка (UI/UX) -- `/api/v1/content.view/` resolves content and derivatives: - - For binary content without previews: present original only when licensed. - - For audio/video: use preview/low for unauth; decrypted_low/high for licensed users. - - Frontend shows processing state when derivatives are pending. -- Purchase options (TON/Stars) remain in a single row (UI constraint). -- Cover art layout: fixed square slot; image fits without stretching; background follows page color, not black. +- `/api/v1/content.view/` определяет доступные отображения: + - бинарный контент без превью — оригинал только при наличии лицензии; + - аудио/видео — для неавторизованных preview/low, для имеющих доступ — decrypted_low/high. +- В процессе конвертации фронтенд показывает статус «processing», без фальшивых ссылок. +- Обложка (cover): + - фиксированный квадратный слот; изображение «вписывается» без растягивания/искажения; + - пустые области не заполняются чёрным — фон совпадает с фоном страницы. +- Кнопки «Купить за TON/Stars»: всегда в одной строке (без горизонтального/вертикального скролла контента на малых экранах). ```mermaid flowchart LR - View[content.view] --> Resolve[Resolve encrypted/decrypted rows] - Resolve --> Derivations{Derivatives ready?} - Derivations -- No --> Status[processing/pending] - Derivations -- Yes --> Options - Options -- Binary + No License --> Original hidden - Options -- Media + No License --> Preview/Low - Options -- Licensed --> Decrypted Low/High or Original + View[content.view] --> Resolve[Определение деривативов] + Resolve --> Ready{Готово?} + Ready -- Нет --> Info[Статус: processing/pending] + Ready -- Да --> Options + Options -- Бинарь + нет лицензии --> HideOriginal[Скрыть оригинал] + Options -- Медиа + нет лицензии --> PreviewLow[preview/low] + Options -- Есть лицензия --> Decrypted[decrypted low/high|original] ``` --- -## Selected APIs +## API (ключевые) -- `GET /api/system.version` – liveness/protocol version. -- `POST /api/v1/network.handshake` – signed membership exchange. -- `GET /api/v1/content.view/` – resolves display options, status, and downloadability. -- `GET /api/v1.5/storage/` – static file access. -- `POST /api/v1/storage` – legacy upload endpoint. +- `GET /api/system.version` — актуальность сервиса. +- `POST /api/v1/network.handshake` — обмен членством (обязательная Ed25519‑подпись запроса). Пример запроса: + +```json +{ + "version": "3.0.0", + "schema_version": "v1", + "public_key": "", + "node_id": "", + "public_host": "https://node.example", + "node_type": "public|private", + "metrics": {"uptime_sec": 123, "content_count": 42}, + "capabilities": {"accepts_inbound": true, "is_bootstrap": false}, + "ipfs": {"multiaddrs": ["/ip4/.../tcp/4001"], "peer_id": "..."}, + "known_public_nodes": [], + "reachability_receipts": [], + "timestamp": 1710000000, + "nonce": "", + "signature": "" +} +``` + +- `GET /api/v1/content.view/` — `display_options`, `status`, `conversion`. +- `GET /api/v1.5/storage/` — отдача файла. +- `GET /metrics` — экспозиция метрик Prometheus (либо fallback‑дамп счётчиков). --- -## Data Keys & Schemas +## Ключи и схемы DHT -- MetaKey(content_id): tracks `replica_leases`, `leader`, `conflict_log`, `revision`. -- MembershipKey(node_id): LWW-Set of members & receipts, HyperLogLog population, N_reports. -- MetricKey(content_id, window_id): PN-/G-/HLL serialized state. +- `MetaKey(content_id)` — метаданные репликаций: + - `replica_leases`: карта `{lease_id -> {node_id, issued_at, expires_at, asn, ip_first_octet, heartbeat_at, score}}`; + - `leader`: NodeID лидера; `revision`: номер ревизии; + - `conflict_log`: массив событий `UNDER/OVER/LEASE_EXPIRED` и т.п. -All DHT records are signed and merged via deterministic CRDT strategies + LWW dominance (logical_counter, timestamp, node_id). +- `MembershipKey(node_id)` — членство: + - `members`: LWW‑Set; `receipts`: LWW‑Set; + - `hll`: HyperLogLog; `reports`: карты локальных оценок N; + - `logical_counter`: логический счётчик для LWW‑доминации. + +- `MetricKey(content_id, window_id)` — метрики окна: + - `views`: PN‑Counter; `unique`: HLL; `watch_time`, `bytes_out`, `completions`: G‑Counters. + +Все записи подписываются и сливаются детерминированно: CRDT‑логика + LWW‑доминация (`logical_counter`, `timestamp`, `node_id`). --- -## Configuration & Defaults +## Конфигурация и значения по умолчанию -- Network: `NODE_PRIVACY`, `PUBLIC_HOST`, `HANDSHAKE_INTERVAL_SEC`, TLS verify, IPFS peering. -- DHT: `DHT_MIN_RECEIPTS=5`, `DHT_MIN_REACHABILITY=0.6`, `DHT_MEMBERSHIP_TTL=600`, `DHT_REPLICATION_TARGET=3`, `DHT_LEASE_TTL=600`, `DHT_HEARTBEAT_INTERVAL=60`, `DHT_HEARTBEAT_MISS_THRESHOLD=3`, `DHT_MIN_ASN=3`, `DHT_MIN_IP_OCTETS=3`, `DHT_METRIC_WINDOW_SEC=3600`. -- Conversion resources: `CONVERT_*` limits (CPU/mem), `MAX_CONTENT_SIZE_MB`. +- Сеть/рукопожатия: `NODE_PRIVACY`, `PUBLIC_HOST`, `HANDSHAKE_INTERVAL_SEC`, `NETWORK_TLS_VERIFY`, IPFS‑пиры/бустрапы. +- DHT: + - `DHT_MIN_RECEIPTS=5`, `DHT_MIN_REACHABILITY=0.6`, `DHT_MEMBERSHIP_TTL=600`; + - `DHT_REPLICATION_TARGET=3`, `DHT_LEASE_TTL=600`, + - `DHT_HEARTBEAT_INTERVAL=60`, `DHT_HEARTBEAT_MISS_THRESHOLD=3`; + - `DHT_MIN_ASN=3`, `DHT_MIN_IP_OCTETS=3`, + - `DHT_METRIC_WINDOW_SEC=3600`. +- Конвертация: квоты `CONVERT_*`, `MAX_CONTENT_SIZE_MB`. + +Примечание: PoW‑допуски и Kademlia k‑buckets на текущем этапе не активированы в коде — заложены в дизайн и могут быть реализованы отдельно. --- -## Observability & Metrics +## Наблюдаемость и метрики -Prometheus (exported in-process): -- dht_replication_under / dht_replication_over / dht_leader_changes_total -- dht_merge_conflicts_total -- dht_view_count_total / dht_unique_view_estimate / dht_watch_time_seconds +Prometheus: +- `dht_replication_under_total`, `dht_replication_over_total`, `dht_leader_changes_total`; +- `dht_merge_conflicts_total`; +- `dht_view_count_total`, `dht_unique_view_estimate`, `dht_watch_time_seconds`. -Logs track replication conflict_log entries and HTTP structured errors (with session_id/error_id). +Логи: структурированные ошибки HTTP (с id), `conflict_log` по репликациям, события регистрации нод. --- -## Sequence Diagrams (Consolidated) +## Диаграммы последовательностей (сводные) -### Membership & N_estimate +### Обновление N_estimate ```mermaid sequenceDiagram - participant A as Node A - participant B as Node B - A->>B: POST /network.handshake {nonce, ts, signature} - B->>B: verify ts, nonce, signature - B->>B: upsert member; store receipts - B-->>A: {node, known_public_nodes, n_estimate, signature} - A->>A: merge; recompute N_estimate = max(N_local, peers) + participant Peer + participant Membership + participant DHT + Peer->>Membership: handshake(payload, receipts) + Membership->>Membership: merge LWW/receipts + Membership->>Membership: update HLL и N_local + Membership->>DHT: persist MembershipKey + Membership->>Membership: N_estimate = max(valid reports) ``` -### Replication Leader Election +### Выбор лидера и выдача лизов ```mermaid sequenceDiagram participant L as Leader - participant Peers as Responsible Nodes - L->>L: compute p from N_estimate - L->>Peers: rendezvous scores for ContentID + participant R as Responsible + L->>L: p = round(log2(N_est/R)) + L->>R: rank by rendezvous(ContentID, NodeID) L->>L: assign leases (diversity) - Peers-->>L: heartbeat every 60s - L->>L: reassign on 3 misses (≤180s) + R-->>L: heartbeat/60s + L->>L: reassign on 3 misses ``` -### Metrics Publication +### Публикация метрик окна ```mermaid sequenceDiagram participant C as Client participant API as Backend - participant M as MetricsAggregator + participant M as Metrics participant D as DHT - - C->>API: GET content.view?watch_time&bytes_out + C->>API: GET content.view?watch_time,bytes_out API->>M: record_view(delta) - M->>D: merge MetricKey(ContentID, Window) - M->>API: update gauges + M->>D: merge MetricKey(ContentID, window) + API-->>Prom: /metrics ``` --- -## Run & Test +## Сборка и тестирование ```bash -# Spin services +# Старт окружения (пример для /home/configs) docker compose -f /home/configs/docker-compose.yml --env-file /home/configs/.env up -d --build -# Backend unit tests (DHT integration) +# Тесты слоя DHT cd uploader-bot python3 -m unittest discover -s tests/dht ``` - diff --git a/README.md b/README.md index 4881a5f..3ba7b8e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Sanic Telegram Bot [template] -See the consolidated system design with protocol, flows, configuration, and diagrams in `ARCHITECTURE.md`. +Полная документация по системе (архитектура, протоколы, конфигурация, диаграммы) — см. `ARCHITECTURE.md`. -### Running DHT integration tests +### Запуск тестов интеграции DHT ```shell cd uploader-bot