diff --git a/apps/api/src/federation/federation-agent.service.ts b/apps/api/src/federation/federation-agent.service.ts index d82a9e6..26af6d4 100644 --- a/apps/api/src/federation/federation-agent.service.ts +++ b/apps/api/src/federation/federation-agent.service.ts @@ -44,6 +44,7 @@ export interface AgentCommandResponse { export class FederationAgentService { private readonly logger = new Logger(FederationAgentService.name); private readonly orchestratorUrl: string; + private readonly enabled: boolean; constructor( private readonly prisma: PrismaService, @@ -60,18 +61,28 @@ export class FederationAgentService { const validationResult = validateUrl(url, isDevelopment); if (!validationResult.valid) { const errorMessage = validationResult.error ?? "Unknown validation error"; - this.logger.error(`Invalid orchestrator URL: ${errorMessage}`); - // Log security event + this.logger.warn( + `Federation agent service disabled: ${errorMessage}. Set orchestrator.url to enable.` + ); this.auditService.logInvalidOrchestratorUrl(url, errorMessage); - throw new Error(errorMessage); + this.orchestratorUrl = ""; + this.enabled = false; + return; } this.orchestratorUrl = url; + this.enabled = true; this.logger.log( `FederationAgentService initialized with orchestrator URL: ${this.orchestratorUrl}` ); } + private assertEnabled(): void { + if (!this.enabled) { + throw new Error("Federation agent service is disabled: orchestrator URL not configured"); + } + } + /** * Spawn an agent on a remote federated instance * @param workspaceId Workspace ID @@ -84,6 +95,7 @@ export class FederationAgentService { connectionId: string, payload: SpawnAgentCommandPayload ): Promise { + this.assertEnabled(); this.logger.log( `Spawning agent on remote instance via connection ${connectionId} for task ${payload.taskId}` ); @@ -126,6 +138,7 @@ export class FederationAgentService { connectionId: string, agentId: string ): Promise { + this.assertEnabled(); this.logger.log(`Getting agent status for ${agentId} via connection ${connectionId}`); // Validate connection exists and is active @@ -167,6 +180,7 @@ export class FederationAgentService { connectionId: string, agentId: string ): Promise { + this.assertEnabled(); this.logger.log(`Killing agent ${agentId} via connection ${connectionId}`); // Validate connection exists and is active @@ -208,6 +222,7 @@ export class FederationAgentService { commandType: string, payload: Record ): Promise { + this.assertEnabled(); this.logger.log(`Handling agent command ${commandType} from ${remoteInstanceId}`); // Verify connection exists for remote instance diff --git a/apps/coordinator/Dockerfile b/apps/coordinator/Dockerfile index ad35f0e..5fee9ce 100644 --- a/apps/coordinator/Dockerfile +++ b/apps/coordinator/Dockerfile @@ -15,14 +15,9 @@ COPY pyproject.toml . # Create virtual environment and install dependencies RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" +COPY src/ ./src/ RUN pip install --no-cache-dir --upgrade pip && \ - pip install --no-cache-dir hatchling && \ - pip install --no-cache-dir \ - fastapi>=0.109.0 \ - uvicorn[standard]>=0.27.0 \ - pydantic>=2.5.0 \ - pydantic-settings>=2.1.0 \ - python-dotenv>=1.0.0 + pip install --no-cache-dir . # Production stage FROM python:3.11-slim