feat(apps-catalog): консолидация Federation MWP (E9+E10+9.3.b) — один PR взамен стэка #82–88 #117

Open
claude wants to merge 19 commits from feat/apps-catalog-finish into dev
Owner

Консолидация всей работы apps-catalog / Federation MWP (E9 demo pilot + E10 runtime federation + 9.3.b publish) в один PR на dev, взамен стэка из 7 PR (#82–#88).

Что внутри

  1. Revert-of-revert #64 — возвращает весь umbrella apps-catalog (controller apps-catalog-proxy, orchestrator, sdk, desktop).
  2. +4 leaf-коммита: [E9-3b-sub] subscribePackage, [E9-3b-ui] форма publishPackage, [E10-5] on-chain watcher (каркас, impl-заглушки), [E10-3b] dynamic supergraph manager.
  3. Пакет фиксов по итогам полной инспекции (2026-06-09):
    • orchestrator: boot-crash DI исправлен; dynamic supergraph реально подключён (recompose без рестарта, @apollo/composition + _service{sdl}); POST /v1/internal/composition/refresh форсит recompose; healthcheck по /_health; OCI-токен по фактическому контракту ca-auth (GET /v2/auth/token, Basic); docker pull через изолированный DOCKER_CONFIG + login; Dockerfile + compose-сервис (profile federation).
    • controller: enum-статусы publishPackage/publishRelease; .env.example дополнен APPS_CATALOG_AUTH_URL/APPS_CATALOG_TENANT_JWT.
    • ZEUS перегенерирован от merged-схемы и закоммичен (controller/zeus + sdk/zeus + sdk build зелёный) — прежний долг «sdk не компилируется на ветке» закрыт.
    • sdk: обёртки SubscribePackage / ApproveModeration / RejectModeration / AppsCatalogPendingModerations.
    • desktop: канон (Material-иконки, Base*-обёртки, скелетоны); живая подписка из витрины; шаг «публикация релиза» (Mutation.publishRelease); страница «Модерация» (операторский approve/reject); авто-подхват новых пакетов без F5 (поллинг 60с).

⚠️ Перед приёмом / известные ограничения

  • apps-catalog (операторская сторона) на dev стоит на revert'е — endpoints GET /v1/public/packages, install.js, GET /v1/admin/moderation, OCI /v2/auth/token живут в PR apps-catalog #9–#11. Без их merge mono-сторона работает в degraded-режиме.
  • On-chain watcher — каркас с Noop-портами (авто-install по событиям цепи — отдельный PR feat/E10-5b-chain-rpc-impl); ручной install через POST /v1/internal/extensions/install работает.
  • Юнит-тесты orchestrator: 26 passed. Тесты затронутых компонентов sdk/controller — на CI.
  • Локальный пробный merge в dev: 0 конфликтов (флаг gitea может отставать).
Консолидация всей работы **apps-catalog / Federation MWP** (E9 demo pilot + E10 runtime federation + 9.3.b publish) в один PR на `dev`, взамен стэка из 7 PR (#82–#88). ## Что внутри 1. **Revert-of-revert #64** — возвращает весь umbrella apps-catalog (controller apps-catalog-proxy, orchestrator, sdk, desktop). 2. **+4 leaf-коммита**: `[E9-3b-sub]` subscribePackage, `[E9-3b-ui]` форма publishPackage, `[E10-5]` on-chain watcher (каркас, impl-заглушки), `[E10-3b]` dynamic supergraph manager. 3. **Пакет фиксов по итогам полной инспекции (2026-06-09):** - orchestrator: boot-crash DI исправлен; dynamic supergraph реально подключён (recompose без рестарта, `@apollo/composition` + `_service{sdl}`); `POST /v1/internal/composition/refresh` форсит recompose; healthcheck по `/_health`; OCI-токен по фактическому контракту ca-auth (`GET /v2/auth/token`, Basic); docker pull через изолированный `DOCKER_CONFIG` + login; Dockerfile + compose-сервис (profile `federation`). - controller: enum-статусы `publishPackage`/`publishRelease`; `.env.example` дополнен `APPS_CATALOG_AUTH_URL`/`APPS_CATALOG_TENANT_JWT`. - **ZEUS перегенерирован от merged-схемы и закоммичен** (controller/zeus + sdk/zeus + sdk build зелёный) — прежний долг «sdk не компилируется на ветке» закрыт. - sdk: обёртки SubscribePackage / ApproveModeration / RejectModeration / AppsCatalogPendingModerations. - desktop: канон (Material-иконки, Base*-обёртки, скелетоны); живая подписка из витрины; шаг «публикация релиза» (Mutation.publishRelease); страница «Модерация» (операторский approve/reject); авто-подхват новых пакетов без F5 (поллинг 60с). ## ⚠️ Перед приёмом / известные ограничения - **apps-catalog (операторская сторона) на `dev` стоит на revert'е** — endpoints `GET /v1/public/packages`, `install.js`, `GET /v1/admin/moderation`, OCI `/v2/auth/token` живут в PR apps-catalog #9–#11. Без их merge mono-сторона работает в degraded-режиме. - On-chain watcher — каркас с Noop-портами (авто-install по событиям цепи — отдельный PR `feat/E10-5b-chain-rpc-impl`); ручной install через `POST /v1/internal/extensions/install` работает. - Юнит-тесты orchestrator: 26 passed. Тесты затронутых компонентов sdk/controller — на CI. - Локальный пробный merge в `dev`: 0 конфликтов (флаг gitea может отставать).
claude added 5 commits 2026-06-09 12:01:17 +00:00
This reverts commit 96e16ee6ab.
Story 9.3.b-sub: пайщик в десктопе нажимает Подписаться в ExtensionsShowcase.
Backend проксирует это в ca-auth POST /v1/subscriptions/activate с tenant
JWT кооператива-партнёра. ca-auth активирует подписку (trial → active по
free_trial_period_seconds; pay-period после expired); on-chain
apps::regsub подписывает ca-auth от имени каталога-оператора. После
активации pricing-watcher на coopback партнёра подхватит подписку
(Story 9.6).

GraphQL:
- Mutation.subscribePackage(data: SubscribePackageInputDTO!)
  → SubscribePackageResultDTO. Discriminated outcome:
    activated / alreadyActive (409) / clientNotRegistered (403) /
    unavailable (423) / failed.

Защита: chairman кооператива-партнёра (GqlJwtAuthGuard + RolesGuard +
AuthRoles).

Config:
- APPS_CATALOG_AUTH_URL — base URL ca-auth (отдельный от admin).
- APPS_CATALOG_TENANT_JWT — JWT кооператива-партнёра.

Tenant читается ca-auth'ом ТОЛЬКО из JWT — body НЕ может его
переопределить (закрывает «активировать от имени другого tenant'а»).

На degraded-mode (нет AUTH_URL/TENANT_JWT) — mutation возвращает failed
с явной причиной, а не silent no-op.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
(cherry picked from commit dbe349f742)
Story 9.3.b-ui. Закрывает UI-петлю Эпика 9 «MVP demo-app pilot».

SDK (@coopenomics/sdk):
- mutations/extensions/publishPackage.ts — wrapper над Mutation.publishPackage,
  селектор {status, requestId, error}.
- mutations/extensions/publishRelease.ts — wrapper над Mutation.publishRelease,
  селектор {status, requestId, transactionId, error}. Готов для отдельной
  страницы публикации релизов (следующая story 9.3.b-rel-ui).
- mutations/extensions/index.ts: добавлены PublishPackage / PublishRelease.
- Codegen (controller/sdk): pnpm generate-schema + generate-client + sdk build —
  zeus подхватил PublishPackageInputDTO / PublishReleaseInputDTO.

Desktop:
- features/PublishPackage/{api,model}/index.ts — каноническая пара по mono-ai-N
  FSD-конвенции: api тонко оборачивает client.Mutation, model задаёт
  IPublishPackageInput = Mutations.Extensions.PublishPackage.IInput['data'] и
  composable usePublishPackage (isSubmitting / lastResult / lastError / submit).
- pages/DeveloperPublishReleasePage.vue: форма из BaseForm + BaseInput
  (packageId @scope/name + ownerUsername Antelope-name + compatibleSubnets
  textarea с chain_id). Валидация регуляркой ДО отправки. BaseBanner с
  warning если роль текущей сессии не chairman; кнопка submit disabled.
  Зелёный banner при applied, оранжевый — при conflict. Канон BaseBanner
  variant='warn|pos', BaseCard variant='default'. Session-данные читаются
  через useSessionStore (pinia auto-unwrap, без .value).

Что не делалось:
- Форма publishRelease (manifest + sha256) — отдельная страница; mutation
  в SDK уже готова под неё.
- Реальная привязка к списку «Мои пакеты» — пока кнопка отдельной страницы;
  список и интеграция (post-success refresh) — последующая итерация.

(cherry picked from commit 1a0ac54f88)
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.

(cherry picked from commit b926dc2a15)
[E10-3b] feat(orchestrator): dynamic supergraph manager — recompose без рестарта
Typecheck / desktop (pull_request) Failing after 6m29s
Typecheck / controller (pull_request) Failing after 6m36s
29ab3ad00f
Story 10.3b — custom SupergraphManager, который на каждый poll-tick
re-читает subgraph registry и если список изменился — пересобирает
supergraph и вызывает gateway update(newSdl).

Раньше Apollo Gateway получал статический список subgraph'ов на
bootstrap'е через IntrospectAndCompose — добавление нового
расширения (Story 10.4 install pipeline) требовало рестарта контейнера.
Теперь watcher install pipeline → registry upsert → manager на
следующий tick видит новую запись → recompose → gateway swap'ает
supergraph in-memory. Без рестарта.

Идемпотентность через fingerprint (`name:url` sorted join):
- список не изменился → composer НЕ зовётся, ничего не делаем;
- список изменился → composer.compose() → update().

Скрытая ловушка: fingerprint обновляем только ПОСЛЕ успешного
compose'а — иначе exception в composer'е навсегда залипает в
устаревшем состоянии (следующий tick думает что состояние актуально).
Покрыто continuity-тестом.

7/7 unit-тестов покрывают: initial, idempotent tick, add/remove/url-change,
continuity на ошибке composer'а, cleanup. Используют jest fake timers.

Интеграция с Apollo Gateway (gateway.module.ts) — отдельный follow-up
(`feat/E10-3b-apollo-integration`), требует @apollo/composition impl
для SupergraphComposerPort.

(cherry picked from commit 6ac6a0319b)
claude closed this pull request 2026-06-09 12:14:54 +00:00
claude reopened this pull request 2026-06-09 12:29:13 +00:00
claude added 1 commit 2026-06-10 19:17:53 +00:00
[E10-5b] feat(orchestrator): реальный on-chain watcher — авто-установка расширений без ручных вызовов
Typecheck / desktop (pull_request) Successful in 13m36s
Typecheck / controller (pull_request) Successful in 13m13s
27220c8572
- ChainRpcAppsEventStream: поллинг таблиц apps-контракта (releases/subs/
  packages) через nodeos get_table_rows, синтез событий из диффа снапшотов;
  маппинг on-chain package_id (eosio::name) → npm @scope/name через
  packages.package_name; initial-снапшот доводит стенд до chain-состояния;
- CaAuthReleaseMetadata: install-spec из npm-манифеста CA-auth registry —
  signed-request (канон X-Signature k1: + canonicalize) → per-package JWT
  (выдаётся только при активной подписке) → coopenomics.backend секция;
  тот же JWT идёт в docker login (подписка = единственный источник доступа);
- docker run-путь install pipeline'а: контейнер расширения поднимается
  прямым docker run (имя/сеть/env из spec'а), без заранее описанного
  compose-сервиса; rollback снимает контейнер;
- DI-проводка по env: CHAIN_RPC_URL / COOPERATIVE_WIF включают реальные
  impl'ы, без них — Noop (dev-стенд стартует как раньше);
- compose: env-переменные watcher'а у сервиса orchestrator;
- 41 юнит-тест зелёный (8 новых на поллер, 6 на metadata/подпись)
claude added 1 commit 2026-06-11 07:16:11 +00:00
install.js активного релиза качается с ca-admin при установке/обновлении
пакета (watcher-события подписки/релиза), проверяется по sha256
(заголовок ca-admin + независимая сверка с coopenomics.frontend.installSha256
из манифеста в ca-auth registry, fail-closed) и складывается в volume.
Endpoints /v1/internal/extensions/frontend{,/:scope/:name/install.js} —
источник для coopback-прокси (E12-3): desktop получает только фронты
реально установленных у кооператива пакетов.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude added 1 commit 2026-06-11 07:21:34 +00:00
coopback: ORCHESTRATOR_URL + методы listInstalledFrontends /
fetchInstalledInstallScript; GET /v1/apps-catalog/installed-frontends
(JWT); install/:scope/:name переключён на volume-кэш orchestrator'а с
проброской X-Install-Script-Sha256/X-Package-Version (fallback на прямой
ca-admin только без ORCHESTRATOR_URL — degraded dev). desktop
remote-loader: список remote-расширений — installed-frontends (реально
установленные по подписке), sha256 install.js сверяется через
crypto.subtle перед eval.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude added 1 commit 2026-06-11 08:14:19 +00:00
[E2E][@ant] fix: объявить директиву @auth в субграф-схеме + типы elliptic/bs58 для orchestrator
Typecheck / controller (pull_request) Has been cancelled
Typecheck / desktop (pull_request) Has been cancelled
e7697c82d8
- buildSubgraphSchema (federation v2) строго валидирует SDL: @auth из
  AuthRoles-декоратора без объявления валит boot coopback'а
  ('Unknown directive "@auth"' x100). Объявление через
  buildSchemaOptions.directives — transformSchema продолжает работать.
- orchestrator не компилился ts-node-dev'ом: elliptic/bs58 без типов
  (TS7016). @types/bs58 строго ^4 — v5-пакет это deprecation-пустышка
  под bs58@5, который шипит собственные типы.
claude added 1 commit 2026-06-11 08:16:18 +00:00
[E2E][@ant] fix(orchestrator): экспортировать InstallOrchestratorService из OrchestratorModule
Typecheck / desktop (pull_request) Successful in 13m58s
Typecheck / controller (pull_request) Failing after 8m7s
b267ee2d24
WatcherModule инжектит install-pipeline в OnChainWatcherService, но
модуль провайдера его не экспортировал — boot падал DI-резолвом
(скрытый баг E10-5b: с полным federation-профилем orchestrator ни разу
не стартовал).
claude added 1 commit 2026-06-11 10:26:45 +00:00
fix(apps-catalog-proxy): авто-выпуск tenant JWT по COOPERATIVE_WIF вместо статического env-токена
Typecheck / controller (pull_request) Has been cancelled
Typecheck / desktop (pull_request) Has been cancelled
b5a22d04ab
Tenant JWT ca-auth живёт 30 минут — статический APPS_CATALOG_TENANT_JWT
умирал через полчаса после деплоя, и subscribe mutation навсегда падала
401. Теперь coopback сам выпускает токен (challenge → подпись
coopname@active → verify), кэширует до exp с минутным запасом и
обновляет автоматически. Статический env-токен остаётся как
отладочный override.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude added 1 commit 2026-06-11 10:35:14 +00:00
fix(controller): BigInt(BN) не компилируется с @types/bn.js из lock-файла
Typecheck / controller (pull_request) Has been cancelled
Typecheck / desktop (pull_request) Has been cancelled
5d88d8c655
После обновления pnpm-lock (типы для orchestrator) приехал @types/bn.js,
и UInt64.value стал типизированным BN — BigInt(BN) перестал собираться,
dev-запуск controller падал TS2345. Конвертация через десятичную строку.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude added 1 commit 2026-06-11 10:40:03 +00:00
fix(controller): UInt128 из antelope + from(string) — конфликт инстанций wharfkit после обновления lock
Typecheck / desktop (pull_request) Successful in 14m20s
Typecheck / controller (pull_request) Successful in 13m28s
9d9cb7f5cf
UInt128 из re-export'а @wharfkit/session перестал совпадать по типам с
API.v1.TableIndexType, а UInt128.from не имеет перегрузки под bigint
(возврат unknown) — dev-запуск controller падал TS2345.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Some checks are pending
Typecheck / desktop (pull_request) Successful in 14m20s
Typecheck / controller (pull_request) Successful in 13m28s
Checking for merge conflicts…
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/apps-catalog-finish:feat/apps-catalog-finish
git checkout feat/apps-catalog-finish
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#117