chore(release): 0.1.3 #29
@@ -2,6 +2,9 @@
|
||||
|
||||
**Status:** Accepted; supersedes the refresh-token reuse rule in ADR-006.
|
||||
|
||||
Cookie-clearing policy уточнена в [ADR 018](018-minimal-runtime-coordination.md):
|
||||
неуспешный refresh больше не удаляет cookie. CAS и отказ superseded token сохранены.
|
||||
|
||||
## Context
|
||||
|
||||
Два одновременных запроса могут предъявить один действительный refresh token. Отзыв Session для проигравшего запроса делает недействительной сессию успешного запроса, а сохранение отдельной истории token или grace-window для различения replay добавляет непропорциональное состояние локальному MVP.
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
**Status:** Accepted — архитектурное направление согласовано.
|
||||
|
||||
Prefetch policy ниже заменена [ADR 018](018-minimal-runtime-coordination.md):
|
||||
свечи загружаются по запрошенному диапазону, без предварительной загрузки
|
||||
всей истории бумаг портфеля. Остальные гарантии локального хранения сохранены.
|
||||
|
||||
Реализация `persist-tbank-data` добавлена в рабочие ветки приложения;
|
||||
performance/browser и canonical application gates пройдены. Это не отметка
|
||||
развёртывания в production. Ниже сохранён контекст
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 018. Минимальная runtime-координация
|
||||
|
||||
**Status:** Accepted. Уточняет cookie policy ADR 009 и prefetch policy ADR 017.
|
||||
|
||||
## Context
|
||||
|
||||
Изоляция владельцев данных, атомарные финансовые изменения и локальное чтение
|
||||
не требуют отдельного протокола согласования каждого HTTP-ответа. Дополнительная
|
||||
координация оправдана только наблюдаемым поведением, которое иначе нарушается.
|
||||
|
||||
## Decision
|
||||
|
||||
- Refresh сохраняет атомарную ротацию. Неуспешный refresh не меняет cookie:
|
||||
поздний отказ не должен удалять cookie успешного запроса. Logout очищает cookie.
|
||||
- Frontend объединяет refresh и упорядочивает cookie-writing requests только
|
||||
внутри вкладки. Cross-tab auth synchronization не является требованием;
|
||||
после изменения сессии в другой вкладке допускаются reload или re-login.
|
||||
- Отменой, сбросом и публикацией query results владеет TanStack Query.
|
||||
Смена session/connection очищает соответствующий cache; отдельные registries
|
||||
HTTP-запросов, access epochs и URL-wide latest-read counters не используются.
|
||||
Локальная auth boundary предотвращает применение старого auth result и
|
||||
повтор mutation под другой identity.
|
||||
- Status GET читает только состояние работы. Открытый экран перечитывает
|
||||
resources через `sync=observe` во время работы и после завершения.
|
||||
Сверка hashes между status и data GET, публичные progress counters и
|
||||
невыдаваемые sync states не нужны. Полнота истории остаётся в resource metadata.
|
||||
- Свечи загружаются для запрошенного диапазона. Предзагрузки всей истории
|
||||
портфеля и автоматического расширения короткого периода до `all` нет.
|
||||
- Backend формирует согласованные entries и aggregates из одних исходных
|
||||
данных; frontend доверяет этому contract и не выполняет вторую сверку групп.
|
||||
- Request context и HTTP completion принадлежат `nestjs-pino`/`pino-http`.
|
||||
Проект сохраняет safe field filtering, redaction и route-template logging.
|
||||
- Deployment всегда выполняет один stop → backup → migration → readiness
|
||||
цикл. No-op и frontend-only оптимизации не обещаются; короткий простой принят.
|
||||
|
||||
## Consequences
|
||||
|
||||
Первое открытие нового диапазона свечей может ждать загрузку. Наблюдение активной
|
||||
работы может перечитать неизменившиеся локальные данные, зато не требует
|
||||
checksum protocol. Повтор deployment создаёт новый backup и может остановить API.
|
||||
|
||||
DB ownership подключения, conditional publication, coverage, staging,
|
||||
банковские intent fingerprints и версии записей сохраняются. Отмена HTTP
|
||||
не считается отменой уже выполняющейся server-side transaction.
|
||||
Сохранённый полный forecast не заменяется candidate с изменившимися dependencies.
|
||||
@@ -22,3 +22,4 @@
|
||||
- [015 — SQLite в ограниченном single-server deployment](015-single-server-sqlite-deployment.md)
|
||||
- [016 — Версионируемый комплект развёртывания](016-versioned-deployment-bundle.md)
|
||||
- [017 — Локальное чтение данных T-Bank и фоновая синхронизация](017-local-tbank-reads-and-background-sync.md)
|
||||
- [018 — Минимальная runtime-координация](018-minimal-runtime-coordination.md)
|
||||
|
||||
@@ -43,6 +43,10 @@ Status GET и data GET с `sync=observe` не запускают работу.
|
||||
наблюдение прекращается. Поздний ответ не заменяет уже принятый новый.
|
||||
[HTTP API](../http-api.md) объясняет envelope и экранный refresh.
|
||||
|
||||
Отменой query lifecycle владеет TanStack Query. Status не пересобирает
|
||||
финансовые ответы и не передаёт hash notifications. Свечи нового диапазона
|
||||
загружаются при его открытии; предзагрузка всей истории портфеля не выполняется.
|
||||
|
||||
## Смена подключения
|
||||
|
||||
Каждое чтение проверяет локальную сессию, текущее подключение, известный отказ
|
||||
|
||||
@@ -142,20 +142,15 @@ backups находятся рядом с data directory, вне checkout, и а
|
||||
не удаляются. Незавершённая копия помечается `.partial-` и не подходит для restore.
|
||||
Ключ шифрования хранится отдельно. Локальная копия не защищает от потери диска.
|
||||
|
||||
## Независимое обновление frontend
|
||||
## Единый цикл обновления
|
||||
|
||||
Если изменились только image или конфигурация frontend, backend не
|
||||
пересоздаётся, backup и migration не выполняются. Возможен короткий перерыв
|
||||
на внешней точке входа; старым browser tabs может потребоваться reload.
|
||||
При неизменных исправных контейнерах повтор команды не пересоздаёт сервисы.
|
||||
|
||||
## Независимое обновление backend
|
||||
|
||||
Изменение image или конфигурации backend запускает stop → backup → migration →
|
||||
readiness. Неизменный frontend не пересоздаётся. Во время простоя возможен 502.
|
||||
Каждое обновление, включая повтор того же тега и изменение только frontend,
|
||||
выполняет stop → backup → migration → readiness. Сравнение hashes контейнеров
|
||||
и конфигурации не выполняется. Приняты короткий простой API и дополнительный
|
||||
backup; во время простоя возможен 502, вкладкам может потребоваться reload.
|
||||
Ошибка migration блокирует старт, ошибка готовности останавливает новый backend;
|
||||
ошибка frontend не останавливает исправный backend. Успех фиксируется только
|
||||
после проверок запуска затронутых компонентов.
|
||||
после проверок запуска обоих компонентов.
|
||||
|
||||
Одна file lock защищает установку от параллельных команд. Маркер незавершённого
|
||||
обновления блокирует повтор до разбора оператором. Он содержит этап, версии
|
||||
|
||||
@@ -26,8 +26,8 @@ T-Bank data GET возвращают envelope `{ data, meta }`. `data` може
|
||||
при missing или неполном финансовом агрегате; partial ledger/candles могут
|
||||
содержать подтверждённые строки. `meta` разделяет availability, freshness,
|
||||
lastSuccessfulAt, sync, coverage и состояния зависимостей. `dataRevision`
|
||||
описывает набор данных, `stateVersion` — наблюдаемое состояние, включая
|
||||
пустое завершённое покрытие. Ни одно поле не раскрывает connection revision.
|
||||
описывает набор данных; пустое завершённое покрытие явно представлено в coverage.
|
||||
Публичной hash-версии состояния нет. Ни одно поле не раскрывает connection revision.
|
||||
|
||||
Обычный GET планирует missing/stale зависимости после проверки доступа.
|
||||
GET с `sync=observe` только читает. `POST /api/v1/tbank-sync` принимает
|
||||
@@ -35,6 +35,11 @@ GET с `sync=observe` только читает. `POST /api/v1/tbank-sync` пр
|
||||
scope. `GET /api/v1/tbank-sync/:id` наблюдает разрешённую работу; чужой или
|
||||
прежний handle возвращает `404`. Приём работы не означает её успех.
|
||||
|
||||
Status возвращает state/errorCode без данных ресурсов и численных progress
|
||||
counters. Клиент перечитывает показанные resources через `sync=observe` во время
|
||||
работы и после завершения, сохраняя generated query identity. Sync states ресурса:
|
||||
`idle`, `running`, `failed`; отдельного публичного `queued` нет.
|
||||
|
||||
Source failure принятой работы передаётся безопасным `meta.sync.errorCode`;
|
||||
HTTP transport/access/input errors сохраняют Problem Details. Старые данные
|
||||
при transient failure сохраняют исходное успешное время. Детали поведения —
|
||||
|
||||
@@ -55,15 +55,16 @@ sequenceDiagram
|
||||
B-->>F: Access token, профиль, новая refresh-cookie
|
||||
F->>B: Protected request с Bearer
|
||||
else Cookie нет или refresh отклонён
|
||||
B-->>F: 401 и очистка cookie
|
||||
B-->>F: 401 без изменения cookie
|
||||
Note over F: Готовое неавторизованное состояние
|
||||
end
|
||||
```
|
||||
|
||||
В одном экземпляре frontend одновременные refresh используют один
|
||||
незавершённый запрос. Между вкладками используется Web Locks, если браузер
|
||||
его поддерживает. Backend всё равно защищает ротацию атомарно: координация
|
||||
браузеров не заменяет серверную проверку.
|
||||
В одной вкладке одновременные refresh используют один незавершённый запрос;
|
||||
cookie-writing requests упорядочены локально. Межвкладочная синхронизация
|
||||
не поддерживается: после смены сессии в другой вкладке допустимы reload/re-login.
|
||||
Backend защищает ротацию атомарно. Неуспешный refresh не удаляет cookie
|
||||
победившего запроса; недействительный token по-прежнему не восстанавливает сессию.
|
||||
|
||||
Обычный защищённый запрос с `401 UNAUTHORIZED` проходит refresh и один повтор
|
||||
через общий транспорт; auth endpoints из этого цикла исключены. Само
|
||||
|
||||
@@ -91,13 +91,11 @@ Selected, previous и yearAgo имеют независимую готовнос
|
||||
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
|
||||
Это поле принадлежит ответу аналитики; общий журнал операций его не требует.
|
||||
|
||||
Frontend проверяет принадлежность выплат по полученному ключу до подготовки
|
||||
плоского списка выплат. Отсутствующий, пустой или
|
||||
нестроковый ключ, неоднозначные ключи инструментов, неизвестная группа, другая
|
||||
валюта или несовпадение числа выплат приводят к существующему локальному
|
||||
состоянию ошибки аналитики с повторной попыткой. Частичный список выплат не показывается как
|
||||
полный; формула идентификации в клиенте не восстанавливается. Полностью пустой
|
||||
ответ допустим. Состав и исходный серверный порядок записей и знак сумм
|
||||
Backend обеспечивает принадлежность выплат, валюту и receipt count при
|
||||
построении entries и instrument groups из одного набора данных. Frontend
|
||||
доверяет типизированному contract, не восстанавливает формулу идентификации
|
||||
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
|
||||
Состав и исходный серверный порядок записей и знак сумм
|
||||
сохраняются, frontend не пересчитывает денежные итоги. Стабильный ID в пределах подключения и счёта определяет одну операцию:
|
||||
повторная сверка обновляет её без двойного учёта. Одинаковые ID разных счетов
|
||||
остаются разными выплатами. Изменение источника логотипа позволяет заново
|
||||
|
||||
@@ -130,15 +130,12 @@ Backend хранит token в шифротексте AES-256-GCM с новым n
|
||||
[validateEnv](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/config/env.validation.ts) (справочный источник).
|
||||
Общий FIFO-лимитер ограничивает поток RPC и не допускает более 50
|
||||
ожидающих. Для `UNAVAILABLE`, `DEADLINE_EXCEEDED` и `RESOURCE_EXHAUSTED`
|
||||
обычный RPC допускает один повтор через секунду. Deadline каждой попытки — 15 секунд,
|
||||
каждый RPC допускает один повтор через секунду. Deadline каждой попытки — 15 секунд,
|
||||
а ожидание места в лимитере не является временем этой сетевой попытки.
|
||||
Для поиска метаданных `GetInstrumentBy` разрешены две повторные попытки
|
||||
с паузами 2 и 4 секунды после неудачных попыток. Они применяются к тем же
|
||||
временным кодам и к переполнению локальной очереди; перед каждой попыткой
|
||||
проверяется её вместимость. Постоянные ошибки и отказ авторизации
|
||||
Метаданные используют ту же retry policy. Переполненная очередь завершается
|
||||
ошибкой сразу, без повторов admission. Постоянные ошибки и отказ авторизации
|
||||
не повторяются. Подтверждённый `NOT_FOUND` при поиске метаданных означает
|
||||
отсутствие инструмента, а не временный сбой. Остальные RPC при полной
|
||||
очереди завершаются сразу.
|
||||
отсутствие инструмента, а не временный сбой.
|
||||
Параметры попыток принадлежат
|
||||
[T-Bank client](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/integrations/tbank/tbank.client.ts) (справочный источник);
|
||||
решение об ограниченных повторах — [ADR 005](../adr/005-tbank-upstream-resilience.md).
|
||||
|
||||
Reference in New Issue
Block a user