26 KiB
Контейнерная разработка и поставка WealthLedger
Основание — утверждённые Proposal, Delta Specs и Design revision 1. UI/UX package неприменим: пользовательские экраны и interactions не меняются.
Checkbox закрывается только после выполнения действия и его Verification.
Перед Node-командами активируется .nvmrc соответствующего независимого
репозитория. Git-команды выполняются из репозитория-владельца; production data,
secrets и опубликованные release tags не используются как test fixtures.
Задачи выполняются по порядку разделов. Frontend 2.1–2.2 и backend 3.1–3.2 могут идти параллельно после 1.2. Workspace orchestration начинается после готовности обоих component images. Реальный server rollout выполняется только после локального production smoke и документированного backup.
1. SDD и внешние prerequisites
-
1.1 [specs] Проверить утверждённый SDD package закреплённым OpenSpec CLI и сохранить canonical change структурно валидным до Apply.
- Covers:
N/A— обязательный gate canonical SDD authority; он не добавляет runtime behavior, но разрешает реализацию утверждённых требований и Design. - Verification: с версией из
openspec/.cli-versionвыполнитьopenspec schema validate wealth-ledger-sdd --verbose,openspec validate containerized-application-delivery --type change --strict --store wealth-ledger-specs,openspec validate --specs --strict --store wealth-ledger-specs, затемnpm run verify. - Result (2026-09-16): по явному уточнению владельца использован установленный OpenSpec 1.13.0 вместо 1.10.0. Все четыре проверки прошли; 25 specs passed, 0 failed. Repository-wide pin не изменён.
- Covers:
-
1.2 [workspace] Подтвердить prerequisites выбранного Solution Assessment: Docker Compose на development/server hosts, Docker-capable Gitea runner, Container Registry и раздельные package write/read credentials.
- Covers:
N/A— техническое предусловие утверждённой Compose/Registry delivery; оно не вводит самостоятельное поведение приложения и блокирует custom fallback при отсутствии platform capability. - Verification: зафиксировать поддерживаемые Docker/Compose и Gitea versions;
docker version,docker compose version, успешные authenticated registry login для CI publisher и server pull-only identity без вывода credentials. - Partial result (2026-09-16): локально Docker Desktop 4.91.0, Engine 29.8.0 (Linux arm64), Compose 5.5.1; Gitea API сообщает 1.27.3. Server Docker/Compose и Docker-capable runner пока не подтверждены. MCP identity не имеет доступа к Actions secrets (
user should be the owner of the repo); раздельные publisher/pull-only login не проверены. Publication и server rollout остаются внешними gates; независимая локальная реализация продолжается.
- Covers:
2. Frontend image и ingress
-
2.1 [frontend] Добавить development и production image targets: Dockerized Vite watch с same-origin
/api/proxy и nginx runtime со SPA fallback, API proxy, runtime DNS re-resolution, cache policy и non-root-compatible filesystem.- Covers:
application-delivery—Локальная среда воспроизводит границы поставленного приложения;application-delivery—Серверное приложение имеет одну внешнюю точку входа. - Verification: собрать оба targets; development container через container network отдаёт HMR и сохраняет
/api/v1/...; production container отдаёт SPA/deep link, проксирует API без rewrite, не раскрывает backend port и после backend recreation подключается к новому container address.
- Covers:
-
2.2 [frontend] Добавить release-tag workflow публикации frontend image с проверкой версии, canonical frontend gate, OCI revision metadata и immutable semver tags без
latest.- Covers:
application-delivery—Поставка допускает независимое обновление компонентов. - Verification: workflow syntax принимается Gitea; controlled candidate run после
npm run verifyпубликует image, registry возвращает digest, clean pull по digest запускает тот же static artifact; credential отсутствует в logs и image history.
- Covers:
-
2.3 [frontend] Выполнить frontend repository completion gate после packaging и routing changes.
- Covers:
N/A— repository-owned проверка реализации Design и отсутствие regression в существующем frontend; отдельного observable requirement не создаёт. - Verification:
npm ci,npm run verify,git diff --check; вручную просмотреть новые Docker/nginx/workflow files и отсутствие secrets.
- Covers:
Результаты frontend (2026-09-16)
- 2.1: оба targets собраны на Linux arm64; Vite HMR WebSocket connected,
/api/v1/probe?check=pathсохранён. nginx read-only + tmpfs отдаёт deep link сno-cache, proxy сохраняет path/query/host/proto/request ID. Backend без host port пересоздан с другим IP (.2 → .5); nginx восстановил proxy без restart. - 2.2: release-tag workflow реализован с
ubuntu-latest(label подтверждён владельцем). Реальный runner Docker access, registry write/read credentials, Gitea workflow acceptance и controlled publication пока не проверены. - 2.3:
npm ci,npm run verify,git diff --checkпрошли. Docker context ограничен allowlist;.env, credentials и host dependencies не копируются. Новые Docker/nginx/workflow files просмотрены; publication secrets идут только в отдельный Docker login, не в image build arguments.
3. Backend image, migration и readiness
-
3.1 [backend] Добавить development и production image targets с Linux native dependencies, compiled application, generated Prisma client, runtime Prisma CLI/migrations, T-Bank proto assets, non-root process и выделенным data path.
- Covers:
application-delivery—Локальная среда воспроизводит границы поставленного приложения;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle;application-delivery—Обновление API сохраняет целостность данных. - Verification: development target выполняет Nest watch; production target стартует из чистого image, находит proto contracts, принимает config только из environment, пишет только в data path; одноразовый
prisma migrate deployпроходит на fresh и representative existing SQLite, а приложение не стартует после контролируемой migration failure.
- Covers:
-
3.2 [backend] Добавить release-tag workflow публикации backend image с проверкой версии, полными backend gates, OCI revision metadata и immutable semver tags без
latest.- Covers:
application-delivery—Поставка допускает независимое обновление компонентов. - Verification: workflow syntax принимается Gitea; controlled candidate run выполняет
npm run verifyиnpm run test:e2e, публикует image и получает digest; clean pull по digest выполняет migration и production start, credential отсутствует в logs и image history.
- Covers:
-
3.3 [backend] Выполнить backend repository completion gates и проверить container readiness без нового публичного endpoint.
- Covers:
N/A— repository-owned проверка packaging, existing auth boundary и SQLite integration из Design; самостоятельного нового API behavior нет. - Verification:
npm ci,npm run verify,npm run test:e2e,git diff --check; healthcheck принимает завершённый HTTP-ответ existing auth route, а stopped/uninitialized process остаётся unhealthy.
- Covers:
4. Workspace Compose orchestration
-
4.1 [workspace] Добавить production Compose topology с version-tagged frontend/backend references, migration service, healthchecks, persistent host data directory, internal-only backend и единственным configurable frontend loopback port.
- Covers:
application-delivery—Серверное приложение имеет одну внешнюю точку входа;application-delivery—Поставка допускает независимое обновление компонентов;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle;application-delivery—Обновление API сохраняет целостность данных. - Verification:
docker compose configс non-secret fixture environment; rendered config содержит один host port, один backend replica, одинаковый backend image reference у migration/runtime и отдельный data mount; missing required image/config/secret values дают blocking configuration/start failure.
- Covers:
-
4.2 [workspace] Добавить development Compose override с local image targets, source watch/mounts, container-owned dependencies, отдельным local data volume и одним frontend browser origin.
- Covers:
application-delivery—Локальная среда воспроизводит границы поставленного приложения;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle. - Verification: с чистыми local volumes запустить Compose; frontend edit появляется через HMR, backend edit перезапускает Nest,
/api/v1/...идёт через frontend origin, hostnode_modulesне используется, restart сохраняет local data, production data path отсутствует в rendered config.
- Covers:
-
4.3 [workspace] Обновить root tracking allowlist и README entrypoints без custom scripts или нового root CI, затем проверить orchestration configuration.
- Covers:
N/A— root только связывает независимые component repositories и объясняет стандартные Compose entrypoints согласно Design; runtime behavior реализуется component images и Compose tasks 4.1–4.2. - Verification:
docker compose configдля production и development variants,git diff --check, просмотрgit status --shortи staged paths подтверждают только явно разрешённые root files; root workflow остаётся только commitlint.
- Covers:
5. Эксплуатационная документация
-
5.1 [docs] Добавить ADR об ограниченном single-server SQLite deployment и обновить container architecture фактической Docker/Caddy topology, secret и persistence boundaries.
- Covers:
application-delivery—Серверное приложение имеет одну внешнюю точку входа;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle. - Verification: ADR явно связывает решение с прежним local-only baseline, одним backend instance и triggers пересмотра; architecture diagram показывает только frontend port наружу, internal backend и persistent SQLite; ссылки и термины согласованы.
- Covers:
-
5.2 [docs] Описать development, first deployment, independent component update, stopped-backend backup, compatibility check, rollback и explicit restore runbooks.
- Covers:
application-delivery—Локальная среда воспроизводит границы поставленного приложения;application-delivery—Поставка допускает независимое обновление компонентов;application-delivery—Обновление API сохраняет целостность данных;application-delivery—Восстановление не выдаёт откат приложения за откат данных. - Verification: dry-run runbook на disposable data проходит без неописанного шага; frontend-only и backend-only paths не пересоздают другой component; restore требует отдельного решения и сообщает о потере данных после backup.
- Covers:
-
5.3 [docs] Выполнить docs repository completion gate.
- Covers:
N/A— repository-owned проверка durable as-built documentation и ссылок без нового runtime behavior. - Verification:
npm ci,npm run verify,git diff --check; проверить Mermaid rendering, взаимные ADR/architecture/runbook links и отсутствие credentials или host-private values.
- Covers:
6. Сквозная проверка поставки
-
6.1 [workspace] Проверить development Compose на чистом checkout и production Compose на локально собранных release-equivalent images.
- Covers:
application-delivery—Локальная среда воспроизводит границы поставленного приложения;application-delivery—Серверное приложение имеет одну внешнюю точку входа. - Verification: development подтверждает HMR/watch и same-origin login; production smoke подтверждает SPA deep link, registration/login/refresh, API proxy, отсутствие host backend port и clean startup через migration service.
- Covers:
-
6.2 [workspace] На disposable representative SQLite проверить persistence, frontend-only update, backend-only update, migration failure и rollback boundaries.
- Covers:
application-delivery—Поставка допускает независимое обновление компонентов;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle;application-delivery—Обновление API сохраняет целостность данных;application-delivery—Восстановление не выдаёт откат приложения за откат данных. - Verification: restart сохраняет user/session/card data и decryptable test connection; frontend update не recreates backend/data, backend update не recreates frontend; failed migration не делает backend healthy; возврат совместимого image сохраняет current data, а restore отдельной backup copy выполняется только в изолированном scenario с явной проверкой потерянного интервала.
- Covers:
-
6.3 [workspace] Проверить release images из Gitea по выбранным version tags перед первым server rollout и сохранить точную установленную пару версий.
- Covers:
application-delivery—Поставка допускает независимое обновление компонентов;application-delivery—Постоянное состояние и секреты переживают штатный lifecycle. - Verification: pull-only server identity получает оба versioned images;
docker image inspectподтверждает expected revisions; production smoke проходит на этих images с disposable config/data, после чего оператор записывает выбранные image references без secrets.
- Covers:
Apply verification — 2026-09-16
Backend (3.1–3.3)
- Development и production targets собраны на Linux arm64 / Node 24.21.0.
Node/nginx base images закреплены digest; OS packages — точными версиями.
Чистый production runtime обнаружил неверный прежний fallback proto path:
Nest копирует assets в
dist/src; loader теперь использует__dirname. Nest watch используетps;procpsдобавлен только в development target. npm ci,npm run verify— PASS (35 suites).npm auditпри переносе существующего Prisma 7.10.0 в runtime dependencies — 0 vulnerabilities.npm run test:e2eна macOS дважды завершился native Node SIGABRT (RemoveEnvironmentCleanupHook,env != nullptr). Тот же штатный gate выполнен в Linux development image: 8 suites / 98 tests PASS. Это Linux delivery proof; macOS native cleanup limitation не скрывается.npm run test:container -- wealthledger-backend:production— runnable image regression: fresh/existing migration, runtime без source/.env/compiler, non-root + read-only filesystem, существующий auth readiness, user/session persistence. Он же вызывается publish workflow после clean pull.- Controlled broken SQLite migration возвращает non-zero; backend остаётся остановленным. После возвращения исправного data path migration идемпотентна.
- 3.2 остаётся открытой: YAML и shell syntax проверены локально, но Gitea acceptance, authenticated publication и pull по registry digest не выполнены.
Compose, docs и lifecycle (4–6)
- Production/development
docker compose config— PASS. Проверены один loopback host port, backend scale 1, общий backend image/data mount у migration/runtime, readiness dependency и отсутствие production bind mount в development services. Пустая production environment блокирует config. docker compose up -d --wait— PASS для development и production на локально собранных release-equivalent images. Production smoke использовал временный override local image references; canonical config остаётся digest-pinned. Реальный Gitea digest pull этим не подменяется.- Development: source edit вызвал HMR event и изменённый HTTP module, backend source edit — новый Nest process и готовый API. Временные изменения восстановлены. Same-origin registration/login/refresh и data restart PASS.
- Clean checkout proof: отдельный HEAD export + task diff, без host .env и node_modules, новый Compose project/volume; startup и HMR/watch PASS.
- Browser proof (bundled Playwright/Chrome): clean development и production registration/login/reload-refresh PASS; все API requests same-origin, httpOnly/path сохранены, production cookie Secure. Caddy/TLS вне локальной проверки.
- Production: SPA deep link, registration/login/refresh, неизменённый API path, отсутствие backend host port, non-root read-only runtime — PASS.
- Representative disposable SQLite содержит user/session/card и connection, зашифрованный настоящим TbankCrypto на вымышленном token. Restart, migrations и independent recreation сохраняют данные и расшифровку без внешнего T-Bank.
- Отдельные local fixture image IDs проверили frontend-only/backend-only update без recreation другого компонента. Возврат прежнего совместимого backend image сохраняет запись после backup. Это compatibility fixture, не обещание совместимости произвольных будущих релизов.
- Stopped-backend backup и isolated restore с отдельным project/port/data path — PASS: login, карта до backup и decryptable connection доступны; запись после backup отсутствует в восстановленной копии. Текущая база не заменялась.
- Docs: ADR 015 расширяет ADR 001; topology и runbook взаимно связаны.
npm ci,npm run verify— PASS (44 Markdown files),git diff --check— PASS. Mermaid source семантически просмотрен, но renderer в доступном окружении не найден; 5.3 оставлена открытой до проверки rendering. - Root Boy Scout/allowlist review: только Compose, два безопасных env examples, README и .gitignore; новых root scripts/dependencies/CI нет. Source markers watch checks восстановлены. Чужие runtime data и checkout changes сохранены.
- Docker disk был заполнен. После адресной очистки intermediates этой задачи и отдельно разрешённой очистки unused build cache старше суток проверки продолжены; чужие images/containers/volumes не удалялись.
Оставшиеся внешние gates
- 1.2: server Docker/Compose, Docker capability runner
ubuntu-latest, раздельные package writer и server pull-only authenticated login. - 2.2/3.2: реальные Gitea candidate workflows и публикация frontend/backend,
OCI revisions, registry digests, clean pull и отсутствие credentials в logs.
Нужны Actions secrets
REGISTRY_USERNAME/REGISTRY_TOKENв каждом component repo и отдельная server identity. Workflow не публикуетlatestи fail-closed отказывается от overwrite или недоказанного отсутствия tag. - 6.3: smoke опубликованной пары version tags на disposable server config/data, запись installed image references/revisions до первого server rollout. Server rollout, Caddy, TLS и реальный финансовый запрос не выполнялись.
Упрощение deployment configuration по запросу владельца
Обязательные FRONTEND_DIGEST/BACKEND_DIGEST и отдельные repository fields
заменены на FRONTEND_IMAGE/BACKEND_IMAGE с release version tags.
Design и runbook синхронизированы. Результаты выше описывают первоначальную
проверку; обязательный digest pinning более не является deployment contract.
Migration и backend по-прежнему используют один image reference.
Verification упрощения: production/development docker compose config PASS;
разные version tags выбираются независимо, migration/runtime получают один
backend image, один loopback port и development volume сохранены. Пустые
image/secret values блокируют config. Docs npm run verify, OpenSpec strict
change validation и git diff --check в affected repos — PASS.
По следующему запросу владельца из FROM удалены base image digests:
используются node:24.21.0-bookworm-slim и nginx:1.28.0-alpine.
Version tags не гарантируют неизменность содержимого базового image.
Verification: повторная сборка production/development targets обоих компонентов
— PASS (с использованием Docker cache). Dockerfile остаются в component repos,
чтобы standalone build и release CI не зависели от root checkout.
По запросу владельца удалены дополнительные commit tags из обоих workflows; release tag защищён от перезаписи, revision остаётся в OCI label. Production Compose наследует healthchecks из images; development содержит собственные checks с прежними таймингами, migration отключает check. Verification: production/development Compose config и invariants, healthchecks локальных production images, shell syntax обоих workflows, docs verify, OpenSpec strict validation и diff checks — PASS. Registry publication остаётся внешней непроверенной частью задач 2.2/3.2.