[E10-4] gateway-orchestrator: install-pipeline (OCI pull → compose up → health → registry) #82

Closed
claude wants to merge 3 commits from feat/E10-4-install-pipeline into apps-catalog
Owner

Story 10.4 — Install pipeline integration (orchestrator-side)

Под зонтиком #64 (apps-catalog → dev).

Что входит

InstallOrchestratorService в components/gateway-orchestrator/:

  1. (опц.) OCI token у CA-auth → docker pull <imageRef> через CA-auth bearer.
  2. (опц.) docker compose up -d <serviceName> если задан compose-file.
  3. healthcheck poll по url subgraph'а (500ms interval, default timeout 60s).
  4. upsert в subgraph_registry (active=true, healthStatus="ok").
  5. Apollo Gateway за ≤10с подхватит запись polling'ом → supergraph рекомпозируется.
  6. На failure — composeDown rollback + discriminated outcome applied | failed с reason.

Что НЕ входит (отдельные ветки в этом же зонтике)

  • mono controller mutation approvePackage → REST POST /v1/internal/extensions/install orchestrator'а (wiring approve→install) — отдельный feat/E10-4-approve-wire.
  • desktop notification после successful install (init-installed-extensions re-poll) — может попасть в E10-4-desktop-notify или slip в E10-8 chatcoop pilot.
  • E2E на реальном compose + реальном chatcoop subgraph — задача Story 10.8.

Архитектура

Сервис изолирован за тремя портами (DockerRunnerPort, HealthProbePort, OciTokenClientPort) — docker daemon, fetch, CA-auth никогда не вызываются напрямую. Shell-out / HTTP-импленты подключаются в OrchestratorModule через DI-токены. Тесты подменяют порты ин-мемори фейками.

Тесты

7/7 green:

  • happy path c imageRef (OCI → pull → up → healthy → registry)
  • happy path без imageRef (core-style — только healthcheck + registry)
  • healthcheck timeout → failed + rollback composeDown
  • imageRef без cooperativeJwt → failed: oci-token, без shell-вызовов
  • docker pull error → failed: docker-pull
  • registry upsert error → failed: registry-write + rollback composeDown
  • healthcheckTimeoutMs из input пробрасывается в HealthProbe

Файлы

  • src/orchestrator/ports.ts — порты + DI-токены
  • src/orchestrator/install-orchestrator.service.ts — сценарий
  • src/orchestrator/install-orchestrator.service.spec.ts — юнит-тесты
  • src/orchestrator/docker-runner.impl.ts — shell-out impl (execFile, без shell-инъекций)
  • src/orchestrator/health-probe.impl.ts — HTTP polling impl
  • src/orchestrator/oci-token-client.impl.ts — CA-auth /v2/token client
  • src/orchestrator/install.controller.ts — тонкая обёртка над сервисом
  • src/orchestrator/orchestrator.module.ts — DI-проводка
  • package.json + jest.config.js + tsconfig.json — jest infra (29.7.0 + ts-jest)

Канон

  • discriminated outcome applied | failed (client switch on status)
  • порты с DI-токенами, ин-мемори фейки в тестах
  • shell-out через execFile массивом аргументов (нет command-injection)
  • никаких magic numbers — таймауты и интервалы const'ами рядом с кодом
## Story 10.4 — Install pipeline integration (orchestrator-side) Под зонтиком #64 (apps-catalog → dev). ### Что входит `InstallOrchestratorService` в `components/gateway-orchestrator/`: 1. (опц.) OCI token у CA-auth → `docker pull <imageRef>` через CA-auth bearer. 2. (опц.) `docker compose up -d <serviceName>` если задан compose-file. 3. healthcheck poll по `url` subgraph'а (500ms interval, default timeout 60s). 4. upsert в `subgraph_registry` (active=true, healthStatus="ok"). 5. Apollo Gateway за ≤10с подхватит запись polling'ом → supergraph рекомпозируется. 6. На failure — composeDown rollback + discriminated outcome `applied | failed` с `reason`. ### Что НЕ входит (отдельные ветки в этом же зонтике) - mono controller `mutation approvePackage` → REST `POST /v1/internal/extensions/install` orchestrator'а (wiring approve→install) — отдельный feat/E10-4-approve-wire. - desktop notification после successful install (init-installed-extensions re-poll) — может попасть в E10-4-desktop-notify или slip в E10-8 chatcoop pilot. - E2E на реальном compose + реальном chatcoop subgraph — задача Story 10.8. ### Архитектура Сервис изолирован за тремя портами (`DockerRunnerPort`, `HealthProbePort`, `OciTokenClientPort`) — docker daemon, fetch, CA-auth никогда не вызываются напрямую. Shell-out / HTTP-импленты подключаются в `OrchestratorModule` через DI-токены. Тесты подменяют порты ин-мемори фейками. ### Тесты 7/7 green: - happy path c imageRef (OCI → pull → up → healthy → registry) - happy path без imageRef (core-style — только healthcheck + registry) - healthcheck timeout → failed + rollback composeDown - imageRef без cooperativeJwt → failed: oci-token, без shell-вызовов - docker pull error → failed: docker-pull - registry upsert error → failed: registry-write + rollback composeDown - healthcheckTimeoutMs из input пробрасывается в HealthProbe ### Файлы - `src/orchestrator/ports.ts` — порты + DI-токены - `src/orchestrator/install-orchestrator.service.ts` — сценарий - `src/orchestrator/install-orchestrator.service.spec.ts` — юнит-тесты - `src/orchestrator/docker-runner.impl.ts` — shell-out impl (execFile, без shell-инъекций) - `src/orchestrator/health-probe.impl.ts` — HTTP polling impl - `src/orchestrator/oci-token-client.impl.ts` — CA-auth `/v2/token` client - `src/orchestrator/install.controller.ts` — тонкая обёртка над сервисом - `src/orchestrator/orchestrator.module.ts` — DI-проводка - `package.json` + `jest.config.js` + `tsconfig.json` — jest infra (29.7.0 + ts-jest) ### Канон - discriminated outcome `applied | failed` (client switch on `status`) - порты с DI-токенами, ин-мемори фейки в тестах - shell-out через `execFile` массивом аргументов (нет command-injection) - никаких magic numbers — таймауты и интервалы const'ами рядом с кодом
claude added 3 commits 2026-06-04 14:34:29 +00:00
Story 10.4 — pipeline установки subgraph-расширения:
1. (опц.) OCI token у CA-auth → docker pull образа;
2. (опц.) docker compose up сервиса;
3. healthcheck poll по url subgraph'а до 200 OK;
4. upsert в subgraph_registry (Apollo Gateway за ≤10с подхватит);
5. на failure — composeDown rollback + discriminated outcome {applied|failed}.

InstallController стал тонкой обёрткой над InstallOrchestratorService.
Внешние зависимости (docker shell / fetch / CA-auth) изолированы за
портами; тесты (7/7 green) гоняют сценарий через ин-мемори моки без
реального docker daemon'а и сети.

Что ОСТАЁТСЯ для отдельной ветки под этим зонтиком:
- wiring approve→install REST из mono controller (mutation approvePackage);
- desktop notification после успешного install'а;
- E2E на реальном compose + chatcoop subgraph (Story 10.8).
Story 10.5 — orchestrator слушает события apps-contract и автоматически
синхронизирует установленные расширения с тем, что в блокчейне.

Обрабатываемые события (discriminated union по `kind`):
- `release-published` → scope check → fetch metadata → install pipeline;
- `subscription-activated` → fetch active release → install pipeline;
- `release-withdrawn` → registry.deactivate;
- `subscription-expired` → registry.deactivate (для нашего coopname).

Все три триггера install'а идут через единый InstallOrchestratorService
(idempotent, upsert в registry). Apollo Gateway за ≤10с подхватит
изменения polling'ом — supergraph рекомпозируется без рестарта.

Порты (AppsContractEventStreamPort, ReleaseMetadataPort) изолируют
watcher от реального chain-чтения. В этом PR — Noop-импленты в
WatcherModule + контракт; реальный parser2/RPC-impl поедет в
follow-up'е (`feat/E10-5b-chain-rpc-impl`).

11/11 unit-тестов покрывают все 4 типа событий + scope-фильтрацию
(all/cooperatives/subnets/empty) + coopname-фильтрацию по своему
кооперативу. Тесты гоняют сценарий через ин-мемори фейки портов
без реальной chain-ноды и Postgres.
ant added this to the AppsCatalog project 2026-06-05 07:51:12 +00:00
Author
Owner

Замещён консолидированным PR #117 (вся работа apps-catalog/Federation в одной ветке на dev). Закрываю как superseded.

Замещён консолидированным PR #117 (вся работа apps-catalog/Federation в одной ветке на dev). Закрываю как superseded.
claude closed this pull request 2026-06-09 12:01:42 +00:00

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: C9S/mono#82