Plan — BJ-11: Tenant config routing (platform → service triple)#
Summary#
Add platform-aware service lookup to TenantConfigService so a task's platform field resolves to the correct { adapter, service, authProvider } triple. Refactor dispatch-path consumers to resolve services via tenant config instead of importing GitHubService directly.
Files#
| Path | Action | Purpose |
|---|---|---|
src/tenant/tenant-config.service.ts | modify | Add getPlatformServices(platform) returning { adapter, service, authProvider }. Inject AdapterRegistry, PLATFORM_AUTH_PROVIDER, and a new PLATFORM_SERVICES map. |
src/tenant/platform-services.ts | create | New file: export PLATFORM_SERVICES injection token and PlatformServicesMap type. |
src/tenant/tenant.module.ts | modify | Register PLATFORM_SERVICES as a factory providing { github: GitHubService }. Import WebhookAdapters module (or re-provide AdapterRegistry) so it is injectable here. |
src/phase-router/phase-router.service.ts | modify | Replace GitHubService injection with TenantConfigService; resolve via getPlatformServices(event.source).service. |
src/hooks/phase-hooks.service.ts | modify | Same refactor; task.repo + event source drives platform lookup (default github until platform threads through PhaseTask). |
src/hooks/compound.service.ts | modify | Same refactor. |
src/tenant/tenant-config.service.spec.ts | create | Unit tests for getPlatformServices: valid platform, unknown platform throws, missing platform throws. |
src/phase-router/phase-router.service.spec.ts | modify | Update DI mocks: swap GitHubService provider for TenantConfigService returning a stub triple. |
src/hooks/phase-hooks.service.spec.ts | modify | Same spec update. |
src/hooks/compound.service.spec.ts | modify | Same spec update. |
Steps#
- Add
PLATFORM_SERVICEStoken +PlatformServicesMaptype in a new file undersrc/tenant/. - Extend
TenantConfigServiceconstructor to injectAdapterRegistry,PLATFORM_AUTH_PROVIDER, andPLATFORM_SERVICES; implementgetPlatformServices(platform)that returns the triple, throwingBadRequestExceptionon missing andNotFoundExceptionon unknown platform. - Register
PLATFORM_SERVICESprovider inTenantModulewith{ github: GitHubService }and ensureAdapterRegistryis resolvable (import fromWebhookModuleor move registry to a shared module if circular). - Refactor
PhaseRouterServiceto dropGitHubServiceimport; resolveserviceviatenantConfigService.getPlatformServices(event.source ?? 'github').service. - Refactor
PhaseHooksServiceandCompoundServicethe same way; default to'github'where the currentPhaseTaskhas no platform field (add aplatform?field onPhaseTaskif a caller can supply it without scope creep). - Update the three spec files to inject a
TenantConfigServicestub returning{ adapter, service, authProvider }instead of mockingGitHubServicedirectly. - Run
npm run lintandnpm run test— fix any breaks; ensure zero warnings.
Verification#
grep -r "from '../github/github.service'" src/phase-router src/hooks src/dispatchreturns zero matches.TenantConfigService.getPlatformServices('github')returns a non-null triple;'bitbucket'throwsNotFoundException;undefined/''throwsBadRequestException.- All existing unit tests pass;
phase-router,phase-hooks,compoundspecs verify service calls route through the resolved provider.
Risks#
PlatformProviderinterface is currently minimal (postComment,closePR,deleteBranch) and dispatch consumers call many moreGitHubServicemethods (addLabel,mergePR,getCheckStatus,createPR, …). Typingserviceas the concreteGitHubServicefor thegithubkey preserves existing method access without expandingPlatformProvider—PlatformProviderexpansion is deferred to sibling Wave 3 tickets.AdapterRegistrycurrently lives inWebhookModule; importing it intoTenantModulemay introduce a circular dependency. If so, promoteAdapterRegistryto a shared module (src/platform/) in this PR.
Open Questions#
- Should
PhaseTaskgain aplatformfield now, or do we hard-default to'github'at call sites and wire platform through in a follow-up? (Current default keeps diff small and matches the single-platform reality onrc/atlassian-integration.)