Services
Trans-Atlas-Backend: Sprint 0
Der Plan, die Demo-SPA in eine Anwendung mit serverseitiger Quelle der Wahrheit zu verwandeln: Firmenkonten, persistente Angebote, Referenzdaten in der Datenbank, ein Ereignisprotokoll.
Dies ist eine Spezifikation und ein Protokoll bereits durchgeführter Artefaktprüfungen, kein angebundenes Backend: index.html bleibt eine einzelne Datei ohne Build-Schritt, ohne PostgreSQL, ohne NestJS-Server und ohne echte API. Der Abschnitt „Geplante Frontend-Änderungen“ beschreibt den nächsten Schritt, nicht das bereits Angewendete - LISTINGS, der localStorage-Login und test-data/ funktionieren weiterhin genau wie vor dieser Seite.
Umfang von Sprint 0
- PostgreSQL 18 + PostGIS: схема, міграції, довідники з реєстрів SPA
- Автентифікація: реєстрація компанії, вхід, ротація refresh-токенів, підтвердження email, ролі
- CRUD заявок і стрічка з фільтрами, що повторюють filteredListings()
- Імпорт наявних 10 773 демо- і тестових заявок у БД без втрати даних
- Append-only журнал подій
- Розгортання, міграції, бекапи, моніторинг
Bewusst außerhalb des Umfangs
| Was |
Warum |
Verschoben nach |
| Модуль SEARCH (маршрути, магістраль→фідери, POST_DRONE) | Власний REST-контракт і власний CI | Окремий етап |
| Верифікація контрагента (KYB, реєстри, дельта-моніторинг) | Напрям A плану | Тижні 3–7 |
| Ingest-агент | Напрям B плану | Тижні 4–8 |
| SSE-стрічка, push, PWA | Напрям C плану | Тижні 6–10 |
| Ставки, торг, ескроу, розрахунки | Межа модулів A.1.3 рамкового ТЗ | Після перших угод |
Stack und Umgebung
| Komponente |
Entscheidung |
Warum |
| Мова | TypeScript, Node.js 24 LTS | Одна мова від схеми до інтерфейсу |
| Каркас | NestJS | Модульність, DI, готова інтеграція валідації та OpenAPI |
| БД | PostgreSQL 18 + PostGIS 3.6 | PostGIS потрібен уже зараз для країн і відстаней |
| Кеш і черга | Redis 7 | Ідемпотентність, ліміти запитів, надалі шина подій стрічки |
| Міграції | node-pg-migrate або Flyway, тільки вперед | Застосовність до продової бази без ручних кроків |
| Пошта | SMTP із SPF/DKIM/DMARC | Підтвердження email і скидання пароля |
| Спостережуваність | JSON-логи, /api/v1/health, Prometheus | Мінімум, без якого продакшн не запускається |
Wichtige Invarianten auf Datenbankebene
| Invariante |
Mechanismus |
| mode='multi' ⇒ components містить ≥ 2 плеча, лише базові види | CHECK listings_components_rule |
| mode<>'multi' ⇒ components IS NULL | той самий CHECK |
| mode='drone' ⇔ існує рядок у listing_drone_details | відкладений CONSTRAINT TRIGGER |
| Місто відправлення ≠ місто призначення | CHECK listings_origin_ne_destination |
| is_cross_border не редагується вручну | GENERATED ALWAYS AS ... STORED |
| Рівень верифікації вище L0 неможливий без дати перевірки | CHECK companies_verified_needs_date |
| У компанії рівно один власник | частковий UNIQUE INDEX по role='owner' |
| Email унікальний без урахування регістру | тип citext |
| Журнал подій не редагується застосунком | REVOKE UPDATE, DELETE для ролі застосунку |
Parität der API-/SPA-Filter
GET /api/v1/listings muss dasselbe Ergebnis liefern wie das heutige filteredListings().
| SPA state.filters |
API-Parameter |
state.filters.mode | mode |
state.filters.multiModes | components |
state.filters.from | origin_city_id |
state.filters.to | destination_city_id |
state.filters.fromCountry | origin_country |
state.filters.toCountry | destination_country |
state.filters.borderScope | border_scope |
state.filters.currency | currency |
Authentifizierung und Sicherheit
| Anforderung |
Wert |
| Хешування пароля | argon2id, m=64 MiB, t=3, p=1 |
| Мінімальна довжина пароля | 10 символів; перевірка за списком скомпрометованих |
| Access-токен | JWT, 15 хв, EdDSA, kid для ротації ключів |
| Refresh-токен | 30 днів, лише SHA-256; ротація з родиною, повторне використання вбиває всі сесії |
| Блокування | 10 невдалих спроб → блок на 15 хвилин |
| Підтвердження email | Одноразовий токен, 24 години; до підтвердження - перегляд без публікації |
| Ролі | owner, manager, viewer; редагувати заявку може лише її компанія |
Nichtfunktionale Anforderungen
| Kennzahl |
Ziel |
| Стрічка з фільтрами, p95 | ≤ 200 мс на 100 тис. заявок |
| Публікація заявки, p95 | ≤ 300 мс |
| Доступність | 99.5% на місяць |
| Бекап | Щодоби повний, WAL безперервно, відновлення - щомісяця |
| Міграції | Тільки вперед, без ручних кроків |
Tatsächliche Testläufe
| Lauf |
Was geprüft wurde |
Ergebnis |
tools/extract_registries.py | Витягування реєстрів із index.html | 175 міст, 9 вантажів, 32 валюти, порожніх полів немає |
ci/check_backend_contract.py | 8 груп перевірок артефактів | 15 із 15 пройдено |
ci/acceptance_db.py | Жива PostgreSQL 18.6 + PostGIS 3.6 | 25 із 25 пройдено |
Geplante Frontend-Änderungen
Der nächste Schritt, sobald ein echtes Backend existiert - in dieser Demo nicht angewendet:
- LISTINGS перестає бути літералом і стає результатом GET /api/v1/listings; loadExternalListings() і LISTINGS_FEED замінюються курсорною пагінацією
- getUsers(), setUsers(), saveUser() видаляються. localStorage лишається лише для мови, вибраного виду транспорту та інших втрачуваних станів UI
- Форма модального вікна отримує третій режим — публікацію заявки
- Помилки показуються з problem+json, поле в помилці підсвічується за JSON Pointer
- Перемикач API_BASE: за відсутності бекенду сайт чесно повідомляє про це, як уже роблять вкладки погоди й кордонів
CI-Gates: erforderliche Prüfungen
Zwölf erforderliche Prüfungen aus drei Pipelines; jede Pipeline hat einen eigenen Gate-Job, der fehlschlägt, wenn ein Job, von dem er abhängt, fehlschlägt.
| Pipeline |
Job |
Prüfung im Regelwerk |
.github/workflows/contract.yml |
schema |
Схема і сценарії T16-T27 |
|
i18n |
Валютні та мовні сценарії C1-C13, L1-L12 |
|
proto |
Контракт proto модуля SEARCH |
|
ui |
UI-сценарії U1-U8 вибору виду транспорту |
|
contract-gate |
contract-gate |
.github/workflows/backend.yml |
backend-contract |
Контракт бекенду Спринту 0 |
|
backend-db |
Приймальні тести БД Спринту 0 |
|
verification-contract |
Контракт модуля верифікації |
|
verification-db |
Інваріанти верифікації |
|
backend-gate |
backend-gate |
.github/workflows/web3.yml |
web3-tests |
web3-sprint0-tests |
|
blockchain-gate |
blockchain-gate |
Dies ist eine angewendete Konfiguration, kein Entwurf: Das Regelwerk des main-Branches verlangt alle zwölf in der Tabelle oben genannten Prüfungen, und `.github/workflows/` enthält drei erforderliche Pipelines - `contract.yml`, `backend.yml` und `web3.yml` - sowie das nicht blockierende `source-probe.yml`. Die von der Backend-Pipeline aufgerufenen `sprint-0-backend/ci/*`-Skripte liegen im Repository und laufen gegen eine echte PostgreSQL mit PostGIS: Im Lauf auf main gingen Migration, Registerbefüllung, der Import von 10773 Angeboten und die negativen Invariantentests durch - insgesamt 42 Prüfungen auf einer echten Datenbank. `ci/check_live_ruleset.py` vergleicht die Regelwerksdatei mit dem Live-GitHub und meldet auf dem aktuellen main Übereinstimmung: 12 Prüfungen in der Datei, 12 auf GitHub. Der Konsistenzprüfer `ci/check_ruleset.py` läuft ebenfalls: 14 Regeln, 35 von 35 Mutationen erkannt. Was weiterhin nicht angewendet ist: Diese Seite selbst bleibt eine einzelne Datei ohne Backend - die Pipelines prüfen Verträge und die Datenbank, sie bedienen index.html nicht.
Modelldateien