Task Breakdown: Plugins Capabilities (HTTP Surface)
Feature ID: plugins-capabilities
Plan: ./plan.md
Status: Done (retrospective; surface already shipped on develop)
Last updated: 2026-05-08
How to use
This is a retrospective task list — every numbered task already shipped on
develop. Outstanding follow-ups (T16 onward) are not blockers for the
spec backfill but are good candidates for a future hourly-tracker run.
Phase 1 — Module scaffolding
- T1.
DeployModuleatapps/api/src/plugins-capabilities/deploy/deploy.module.ts- Imports:
FacadesModule,DatabaseModule,WebsiteGeneratorModule,WorkModule,ActivityLogModule,forwardRef(() => AuthModule) - Providers:
DeployService,DeploymentVerifierService - Exports:
DeployService,DeploymentVerifierService
- Imports:
- T2.
SearchModuleatapps/api/src/plugins-capabilities/search/search.module.ts - T3.
ScreenshotModuleatapps/api/src/plugins-capabilities/screenshot/screenshot.module.ts - T4.
OAuthModuleatapps/api/src/plugins-capabilities/oauth/oauth.module.ts - T5.
GitProviderModuleatapps/api/src/plugins-capabilities/git-provider/git-provider.module.ts - T6.
DeviceAuthModuleatapps/api/src/plugins-capabilities/device-auth/device-auth.module.ts - T7. Mount all six modules in
apps/api/src/api.module.ts(lines 18-24 imports + 64-71 module list).
Phase 2 — Controllers
- T8.
DeployControllercovering 13 endpoints (providers/configured, works/:id deploy + check + lookup + teams + domains GET/POST/DELETE + verify, batch, validate-token, /teams placeholder).- Owner gate:
WorkOwnershipService.ensureCanEdit/.ensureCanViewon every:id-scoped endpoint. - Activity-log emission:
work.deployed(single deploy) +deployment.batch_started(batch) — both fire-and-forget with.catch(() => {}). - Domain regex validation on
AddDomainDto.
- Owner gate:
- T9.
SearchControllercovering 2 endpoints (/check-availability,/).- Per-call provider resolution via private
resolveConfiguredProviderhelper (no per-callproviderOverridefrom the DTO — see OQ-4). - Two distinct unconfigured-vs-not-enabled messages on
/check-availability. NoProviderErrorre-mapped; non-Error throws coerce to"Search failed".
- Per-call provider resolution via private
- T10.
ScreenshotControllercovering 3 endpoints (/check-availability,/capture,/get-url).- Three-tier sort (default → configured → name) on the provider list.
cacheUrlpreferred overimageUrlin the response.imageBuffer.toString('base64')only when present; elsenull.
- T11.
OAuthControllercovering 6 endpoints (providers list, connection, connect/url, callback/plugins, user, DELETE disconnect).- Strict-
'true'parse onforceConsent. - Missing-code
BadRequestBEFORE service call. - 200-envelope-with-error on
getUser/disconnect.
- Strict-
- T12.
GitProviderControllercovering 5 endpoints (providers list, connection, organizations, repositories, user).parseInt(_, 10)onpage/perPage, each independently undefined-able.- Two-branch auth resolution (OAuth vs PAT) with shape-discriminated
getUsercalls.
- T13.
DeviceAuthControllercovering 2 endpoints (/status,/start).- Two-line passthroughs to
DeviceAuthService; errors propagate unwrapped.
- Two-line passthroughs to
Phase 3 — Services
- T14.
DeployService.deploy(workId, userId, options)— orchestrates the dispatch chain (resolve plugin + token + settings → fetch git token → ensure repo context → enable workflows → set required + optional + cron secrets → call plugingetDeploymentSecrets→ dispatch with retry → emitDeploymentDispatchedEvent). - T15.
DeployService.deployBatch— rolling batches of 5 with 2 000 ms sleep between batches. - T16.
DeploymentVerifierService.startVerification— replaces any existing poller for the work, then registers a freshsetInterval(10s)loop (max 18 cycles + 13 min wall-clock cap). - T17.
DeploymentVerifierService.lookupExistingDeployment— one-shot lookup helper used byPOST /api/deploy/works/:id/lookup. - T18.
OAuthService— six methods (isConfigured, available providers, connection check, OAuth URL builder, callback handler, disconnect). - T19.
GitProviderService— five methods (isConfigured, available providers, connection check, get user/organizations/ repositories). - T20.
DeviceAuthService— two passthrough methods.
Phase 4 — Plugin contract evolution
- T21. Add optional
IDeploymentPlugin.getWorkflowFilenames()topackages/plugin/src/deployment/. - T22. Add optional
IDeploymentPlugin.getDeploymentSecrets(settings)topackages/plugin/src/deployment/. - T23. Implement
getWorkflowFilenamesinpackages/plugins/vercel/to return['deploy_vercel.yaml', 'deploy_prod.yaml'].