Skip to content

feat(coordination): dynamic plugin loader (ADR-028 D6) [#1420] - #1617

Merged
susumutomita merged 1 commit into
mainfrom
feat/coordination-plugin-loader
Jun 1, 2026
Merged

susumutomita merged 1 commit into
mainfrom
feat/coordination-plugin-loader

Conversation

@susumutomita

Copy link
Copy Markdown
Owner

Summary

#1606 が coordination dispatcher core(state store + dispatchCoordinationOp / projectCoordinationForTeam)をマージしたが、問題が同梱する CoordinationPlugin を runtime に取得する loader が欠けていた。ADR-028 D6(「plugin module を S3 = ADR-008 payload 経路から fetch + import() で動的 load」)の loader 部分を実装する。

静的レジストリではなく動的 import を採る理由: community が coordination 付き問題を後から追加するたびに platform を再デプロイせずに済むため。静的だと platform が各問題に結合し、「問題は plugin、platform は host」を壊して問題カタログの community moat を殺す。

coordination-plugin-loader.ts

  • isCoordinationPlugin — 動的 load した未知 module が SDK 契約(initialState + 3 必須 hook、tick は optional)を満たすか構造判定する門番。
  • loadCoordinationPlugin(importer, ref) — import 関数を 注入(本番は S3 materialize 後の module、test は fake)。import 失敗 / 契約不一致は null を返し、caller が safe fallback。
  • loadAndDispatchCoordinationOp / loadAndProjectCoordinationForTeam — 動的 load → 既存 feat(coordination): dispatcher core — state store + orchestration (ADR-028 D3/D6) #1606 dispatcher への委譲を 1 経路にした orchestration。load 不可は plugin_unavailable / fallbackProjection で participant API を壊さない。

別 isolate sandbox は立てない(ADR-028 D6、cost/複雑度): plugin の hook は SDK 契約上すべて純関数で、bug は当該 event の 1 row に閉じる(optimistic lock + DDB write fail で停止)。

Test plan

  • coordination-plugin-loader.test.ts 12 test、loader file 100%(17/17 stmts, 16/16 branch, 4/4 func, 14/14 lines)。
  • 純追加(新 file + 新 test のみ、既存 source 無改変)→ infra 全体 2278 test 緑(従来 2266 + 12)。
  • typecheck 0 / biome clean / make harness no findings(INVARIANT_PR_SHIPS_WORKING_INCREMENT 含む違反なし)。

Regression analysis

  • 既存 source を一切変更しないため既存挙動は不変。loader は import 関数を DI 境界に置いたので、意味論は S3 経路の有無と独立に検証済み。
  • scope 外(= 次 increment): 実 importer(S3 から plugin を materialize)と HTTP route 配線(POST /portal/me/coordination/op + GET /projection、auth/event-scope 解決)。

Physical impact

  • NO-OP on CFn / deployed artifacts。participant-handler Lambda の source に純関数 module を追加するのみ(新 IAM / table / env なし)。

Relates #1420

#1606 で dispatcher core (state store + dispatchCoordinationOp /
projectCoordinationForTeam) はマージ済みだが、 問題が同梱する CoordinationPlugin を
runtime に取得する loader が無かった。 ADR-028 D6 の「plugin module を S3 (ADR-008 payload
経路) から fetch + import() で動的 load」 の loader 部分を実装する。

静的レジストリではなく動的 import を採るのは、 community が coordination 付き問題を後から
追加するたびに platform を再デプロイせずに済むため (= 問題は plugin、 platform は host。
静的だと platform が各問題に結合し問題カタログの moat を殺す)。

coordination-plugin-loader.ts:
- `isCoordinationPlugin` — 動的 load した未知 module が SDK 契約 (initialState + 3 必須 hook、
  tick は optional) を満たすか構造判定する門番。
- `loadCoordinationPlugin(importer, ref)` — import 関数を注入 (本番は S3 materialize 後の
  module、 test は fake)。 import 失敗 / 契約不一致は null を返し caller が safe fallback。
- `loadAndDispatchCoordinationOp` / `loadAndProjectCoordinationForTeam` — 動的 load → 既存
  #1606 dispatcher への委譲を 1 経路にした orchestration (load 不可は plugin_unavailable /
  fallbackProjection で participant API を壊さない)。

別 isolate sandbox は立てない (ADR-028 D6、 cost/複雑度): plugin の hook は SDK 契約上すべて
純関数で、 bug は当該 event の 1 row に閉じる (optimistic lock + DDB write fail で停止)。

## Regression analysis
- 純追加 (新 file + 新 test のみ、 既存 source 無改変)。 既存 2266 test は不変、 新 12 test 追加で
  infra 2278 緑。 loader file 100% (17/17 stmts, 16/16 branch, 4/4 func, 14/14 lines)。
- typecheck 0 / biome clean / make harness no findings (scaffolding 含む invariant 違反なし)。
- 実 importer (S3 から plugin を materialize) と HTTP route 配線は本 PR の scope 外 (= 次 increment)。
  importer を DI 境界に置いたので、 loader の意味論は S3 経路の有無と独立に検証済み。

## Physical impact
- NO-OP on CFn / deployed artifacts。 participant-handler Lambda の source に純関数 module を
  追加するのみ (新 IAM / table / env 無し)。 既存 handler の挙動は不変。

Relates #1420

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@susumutomita, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 14 minutes and 1 second. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9bdb8f88-3ade-4a56-a3de-72e647523306

📥 Commits

Reviewing files that changed from the base of the PR and between 3938f87 and d01fc50.

📒 Files selected for processing (2)
  • infrastructure/lib/problem-deploy/handlers/participant-handler/coordination-plugin-loader.ts
  • infrastructure/test/problem-deploy/coordination-plugin-loader.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/coordination-plugin-loader

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@susumutomita
susumutomita merged commit 7c5b856 into main Jun 1, 2026
8 checks passed
@susumutomita
susumutomita deleted the feat/coordination-plugin-loader branch June 1, 2026 06:53
@codecov

codecov Bot commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.26%. Comparing base (3938f87) to head (d01fc50).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1617   +/-   ##
=======================================
  Coverage   93.26%   93.26%           
=======================================
  Files         382      383    +1     
  Lines       10460    10475   +15     
  Branches     3200     3206    +6     
=======================================
+ Hits         9755     9770   +15     
  Misses        217      217           
  Partials      488      488           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

susumutomita added a commit that referenced this pull request Jun 1, 2026
… (#1619)

#1606 (dispatcher core) + #1617 (動的 loader) を participant-portal の HTTP route に接続する。
problem は plugin、 platform は host の原則どおり、 platform は dispatch / projection だけを担い、
semantics (alliance / routing / shared queue 等) は問題同梱 plugin に閉じる。

- `coordination-handler.ts` — team-login-key 認証 → scope 解決 → loader+dispatcher 委譲。
  outcome は ok / rejected / conflict / unavailable / not_configured。 scope resolver は active な
  deployment 行から tenant/event/team を引き、 その問題が interTeamCoordination を宣言していれば
  moduleRef を確定する。 `parseCoordinationConfig` は `PROBLEM_COORDINATION` env を parse。
- `index.ts` — `POST /portal/me/coordination/op` + `GET /portal/me/coordination/projection` を登録。
  outcome→HTTP は StatusCodes 名で明示 (rejected=422 / conflict=409 / unavailable=503 /
  not_configured=404)。
- `schemas.ts` — `CoordinationOpBodySchema` ({ op })。 op の意味論は plugin の validateOp が判定。

**importer は seam (ADR-028 D6)**: 問題同梱 plugin を S3 (ADR-008 payload) から materialize して
import する実装と、 `PROBLEM_COORDINATION` env の CDK 配線、 full event roster の ctx.teamIds 解決は
別 increment (owner 領域: 未信頼コード実行 + Lambda bundling/IAM)。 未配線の間は loader が null →
route は unavailable / fallback projection で安全に応答する (= participant API を壊さない)。

## Regression analysis
- 既存 route は無改変。 新 route 2 本 + handler module の追加。 index.ts は宣言的 wiring のみ。
- infra 全 2291 test 緑 (従来 2278 + coordination-handler 13)。 handler module 100%
  (23/23 stmts, 20/20 branch, 5/5 func)。 typecheck 0 / biome clean / make harness 違反なし。
- `PROBLEM_COORDINATION` env は optional。 未設定時は parseCoordinationConfig→{}→全 route
  not_configured で、 既存挙動 (coordination 無効) と等価。

## Physical impact
- **NO-OP** on CFn / deployed artifacts。 participant-handler Lambda の source に route + handler を
  追加するのみ (新 IAM / table 無し)。 optional env `PROBLEM_COORDINATION` は CDK 未配線でも
  absent=安全。 既存 Function URL / IAM / DDB は不変。

Relates #1420

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant