{
"meta": {
"agent": "planner",
"task_id": "356",
"title": "MT-12: Create TenantResolver service + TenantContext",
"created_at": "2026-04-08T12:00:00Z"
},
"inputs": [
{
"name": "issue-356",
"type": "link",
"ref": "https://github.com/AgentSDE/agent-core/issues/356",
"notes": "MT-12: TenantResolver + TenantContext — Wave 3 foundational piece"
},
{
"name": "dispatch-event-dto",
"type": "file",
"ref": "src/webhook/dto/dispatch-event.dto.ts",
"notes": "DispatchEvent class to extend with tenantContext"
},
{
"name": "webhook-controller",
"type": "file",
"ref": "src/webhook/webhook.controller.ts",
"notes": "Controller to inject TenantResolverService into"
},
{
"name": "tenant-module",
"type": "file",
"ref": "src/tenant/tenant.module.ts",
"notes": "Existing tenant module to update with resolver"
}
],
"outputs": [
{
"name": "plan",
"type": "plan",
"format": "md",
"content": "plan.md"
}
],
"files": [
{
"path": "src/tenant/tenant-context.interface.ts",
"action": "create",
"reason": "Define TenantContext interface with tenant, repoConfig, platformProvider, llmProvider"
},
{
"path": "src/tenant/tenant-resolver.service.ts",
"action": "create",
"reason": "Service resolving webhooks/repos to single-tenant default context"
},
{
"path": "src/tenant/tenant-resolver.service.spec.ts",
"action": "create",
"reason": "Unit tests for resolver"
},
{
"path": "src/tenant/tenant.module.ts",
"action": "modify",
"reason": "Export resolver, import dependent modules"
},
{
"path": "src/webhook/dto/dispatch-event.dto.ts",
"action": "modify",
"reason": "Add optional tenantContext field"
},
{
"path": "src/webhook/webhook.controller.ts",
"action": "modify",
"reason": "Inject resolver, attach tenant context to events"
}
],
"steps": [
{
"id": "S1",
"summary": "Create TenantContext interface and TenantResolverService with resolveFromWebhook and resolveFromRepo methods",
"acceptance": [
"TenantContext interface has tenant, repoConfig, platformProvider, llmProvider fields",
"resolveFromWebhook(platform, headers, body) returns default single-tenant context",
"resolveFromRepo(repo) returns default single-tenant context",
"Both methods fall back to ENV-based defaults for unrecognized orgs/repos"
],
"depends_on": []
},
{
"id": "S2",
"summary": "Extend DispatchEvent with tenantContext, wire resolver into WebhookController and TenantModule",
"acceptance": [
"DispatchEvent and DispatchEventParams have optional tenantContext?: TenantContext field",
"WebhookController resolves and attaches TenantContext after adapter normalization",
"TenantModule exports TenantResolverService and imports PlatformModule, LLMModule, CredentialModule",
"tsc --noEmit passes",
"npm run lint passes"
],
"depends_on": [
"S1"
]
},
{
"id": "S3",
"summary": "Create unit tests for TenantResolverService",
"acceptance": [
"Test: webhook payload resolves to correct tenant context",
"Test: repo string resolves to correct tenant context",
"Test: TenantContext carries correct provider instances",
"npm run test passes"
],
"depends_on": [
"S1"
]
}
],
"risks": [
{
"risk": "Wave 2 dependencies (#345, #347, #348) not merged — missing PlatformProvider, LLMProvider, TenantConfigService interfaces",
"mitigation": "Implementation must stub or co-create minimal interfaces if Wave 2 is not yet available"
},
{
"risk": "DispatchEvent constructor change may affect downstream serialization",
"mitigation": "Field is optional — existing code unaffected; new field only populated when resolver is wired"
}
],
"assumptions": [
"Wave 2 modules (PlatformModule, LLMModule, CredentialModule) will be available or can be stubbed at implementation time",
"Single-tenant MVP: all requests resolve to the same ENV-based context — no DB lookup needed",
"TenantContext is passed through DispatchEvent, not via NestJS REQUEST scope"
],
"open_questions": []
}