# Issue #276: Add workspace authorization on incoming connections ## Objective Add proper workspace authorization and controls for incoming federation connections. ## Location `apps/api/src/federation/federation.controller.ts:211-233` ## Current Problem ```typescript @Post("incoming/connect") @Throttle({ short: { limit: 3, ttl: 1000 } }) async handleIncomingConnection( @Body() dto: IncomingConnectionRequestDto ): Promise<{ status: string; connectionId?: string }> { this.logger.log(`Received connection request from ${dto.instanceId}`); // LIMITATION: Incoming connections are created in a default workspace const workspaceId = process.env.DEFAULT_WORKSPACE_ID ?? "default"; const connection = await this.connectionService.handleIncomingConnectionRequest( workspaceId, dto ); return { status: "pending", connectionId: connection.id, }; } ``` Issues: - No authorization check - any remote instance can create connections - No admin approval workflow - Limited audit logging - No allowlist/denylist checking - Hardcoded default workspace ## Security Impact - **Authorization bypass**: Remote instances can force connections without permission - **Workspace pollution**: Unwanted connections clutter the default workspace - **No control**: Administrators have no way to pre-approve or block instances ## Solution Approach ### Phase 1: Audit Logging (This fix) Add comprehensive audit logging for all incoming connection attempts before implementing full authorization. Changes: 1. Log all incoming connection requests with full details 2. Log successful connection creations 3. Log any validation failures 4. Include remote instance details in logs ### Phase 2: Authorization Framework (Future) - Add workspace routing configuration - Implement allowlist/denylist at instance level - Add admin approval workflow - Implement automatic approval for trusted instances ## Implementation (Phase 1) Add comprehensive audit logging to connection.service.ts: ```typescript async handleIncomingConnectionRequest( workspaceId: string, request: ConnectionRequest ): Promise { // Audit log: Incoming connection attempt this.auditService.logIncomingConnectionAttempt({ workspaceId, remoteInstanceId: request.instanceId, remoteUrl: request.instanceUrl, timestamp: request.timestamp, }); // Verify signature const verification = this.signatureService.verifyConnectionRequest(request); if (!verification.valid) { // Audit log: Failed verification this.auditService.logConnectionRejected({ workspaceId, remoteInstanceId: request.instanceId, reason: 'Invalid signature', error: verification.error, }); throw new UnauthorizedException( `Invalid connection request signature: ${verification.error}` ); } // Create connection (existing logic) const connection = await this.prisma.federationConnection.create({...}); // Audit log: Connection created this.auditService.logIncomingConnectionCreated({ workspaceId, connectionId: connection.id, remoteInstanceId: request.instanceId, remoteUrl: request.instanceUrl, }); return this.mapToConnectionDetails(connection); } ``` ## Testing Test scenarios: 1. Incoming connection with valid signature → logged and created 2. Incoming connection with invalid signature → logged and rejected 3. Verify all audit logs contain required fields 4. Verify workspace isolation in logs ## Progress - [ ] Create scratchpad - [ ] Add audit logging methods to FederationAuditService - [ ] Update handleIncomingConnectionRequest with audit logging - [ ] Add tests for audit logging - [ ] Run quality gates - [ ] Commit changes - [ ] Create PR - [ ] Merge to develop - [ ] Close issue #276 - [ ] Create follow-up issue for Phase 2 (full authorization) ## Notes This implements the audit logging requirement from the issue. Full authorization (allowlist/denylist, admin approval) will be implemented in a follow-up issue as it requires: - Database schema changes (allowlist/denylist tables) - New configuration endpoints - Admin UI changes - More extensive testing Audit logging provides immediate visibility and security monitoring without requiring major architectural changes.