Files
specs/openspec/changes/containerized-application-delivery/tasks.md
T
ksv741 b34f23a230
Specs security / security (pull_request) Successful in 6s
Specs verify / verify (pull_request) Successful in 8s
Conventional commits / commits (pull_request) Successful in 11s
Specs security / security (push) Successful in 6s
Specs verify / verify (push) Successful in 9s
spec: define containerized application delivery #10
2026-09-16 09:41:59 +03:00

26 KiB
Raw Blame History

Контейнерная разработка и поставка 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 не изменён.
  • 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; независимая локальная реализация продолжается.

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.
  • 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.
  • 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.

Результаты 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.
  • 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.
  • 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.

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.
  • 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, host node_modules не используется, restart сохраняет local data, production data path отсутствует в rendered config.
  • 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.

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; ссылки и термины согласованы.
  • 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.
  • 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.

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.
  • 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 с явной проверкой потерянного интервала.
  • 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.

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.