# Issue #87: [FED-004] Cross-Instance Identity Linking

## Objective

Implement cross-instance identity linking to enable user identity verification and mapping across federated Mosaic Stack instances. This builds on the foundation from:

- Issue #84: Instance Identity Model (keypairs, Instance and FederationConnection models)
- Issue #85: CONNECT/DISCONNECT Protocol (signature verification, connection management)
- Issue #86: Authentik OIDC Integration (FederatedIdentity model, OIDC service)

## Requirements

Based on the existing infrastructure, FED-004 needs to provide:

1. **Identity Verification Service**: Verify user identities across federated instances using cryptographic signatures and OIDC tokens
2. **Identity Resolution Service**: Resolve user identities between local and remote instances
3. **Identity Mapping Management**: Create, update, and revoke identity mappings
4. **API Endpoints**: Expose identity linking operations via REST API
5. **Security**: Ensure proper authentication, signature verification, and workspace isolation

## Existing Infrastructure

From previous issues:

- **FederatedIdentity model** (Prisma): Stores identity mappings with localUserId, remoteUserId, remoteInstanceId, oidcSubject
- **OIDCService**: Has `linkFederatedIdentity()`, `getFederatedIdentity()`, `revokeFederatedIdentity()`, `validateToken()`
- **ConnectionService**: Manages federation connections with signature verification
- **SignatureService**: Signs and verifies messages using instance keypairs
- **FederationService**: Manages instance identity

## Approach

### 1. Create Identity Linking Types

Create `/apps/api/src/federation/types/identity-linking.types.ts`:

```typescript
// Identity verification request (remote -> local)
interface IdentityVerificationRequest {
  localUserId: string;
  remoteUserId: string;
  remoteInstanceId: string;
  oidcToken: string;
  timestamp: number;
  signature: string; // Signed by remote instance
}

// Identity verification response
interface IdentityVerificationResponse {
  verified: boolean;
  localUserId?: string;
  remoteUserId?: string;
  error?: string;
}

// Identity resolution request
interface IdentityResolutionRequest {
  remoteInstanceId: string;
  remoteUserId: string;
}

// Identity resolution response
interface IdentityResolutionResponse {
  found: boolean;
  localUserId?: string;
  email?: string;
  metadata?: Record<string, unknown>;
}
```

### 2. Create Identity Linking Service

Create `/apps/api/src/federation/identity-linking.service.ts`:

**Core Methods:**

- `verifyIdentity(request)` - Verify a user's identity from a remote instance
- `resolveLocalIdentity(remoteInstanceId, remoteUserId)` - Find local user from remote user
- `resolveRemoteIdentity(localUserId, remoteInstanceId)` - Find remote user from local user
- `createIdentityMapping(...)` - Create new identity mapping (wrapper around OIDCService)
- `updateIdentityMapping(...)` - Update existing mapping metadata
- `validateIdentityMapping(localUserId, remoteInstanceId)` - Check if mapping exists and is valid
- `listUserIdentities(localUserId)` - Get all identity mappings for a user

**Security Considerations:**

- Verify signatures from remote instances
- Validate OIDC tokens before creating mappings
- Enforce workspace isolation for identity operations
- Log all identity linking operations for audit

### 3. Create Identity Resolution Service

Create `/apps/api/src/federation/identity-resolution.service.ts`:

**Core Methods:**

- `resolveIdentity(remoteInstanceId, remoteUserId)` - Resolve remote user to local user
- `reverseResolveIdentity(localUserId, remoteInstanceId)` - Resolve local user to remote user
- `bulkResolveIdentities(identities)` - Batch resolution for multiple users
- `cacheResolution(...)` - Cache resolution results (optional, for performance)

### 4. Add API Endpoints

Extend or create Identity Linking Controller:

**Endpoints:**

- `POST /api/v1/federation/identity/verify` - Verify identity from remote instance
- `POST /api/v1/federation/identity/resolve` - Resolve remote user to local user
- `GET /api/v1/federation/identity/me` - Get current user's federated identities
- `POST /api/v1/federation/identity/link` - Create new identity mapping
- `PATCH /api/v1/federation/identity/:id` - Update identity mapping
- `DELETE /api/v1/federation/identity/:id` - Revoke identity mapping
- `GET /api/v1/federation/identity/:id` - Get specific identity mapping

**Authentication:**

- All endpoints require authenticated user session
- Workspace context for RLS enforcement
- Identity verification endpoint validates remote instance signature

### 5. Testing Strategy

**Unit Tests** (TDD - write first):

**IdentityLinkingService:**

- Should verify valid identity with correct signature and token
- Should reject identity with invalid signature
- Should reject identity with expired OIDC token
- Should resolve local identity from remote user ID
- Should resolve remote identity from local user ID
- Should return null when identity mapping not found
- Should create identity mapping with valid data
- Should update identity mapping metadata
- Should validate existing identity mapping
- Should list all identities for a user

**IdentityResolutionService:**

- Should resolve remote identity to local user
- Should reverse resolve local user to remote identity
- Should handle bulk resolution efficiently
- Should return null for non-existent mappings
- Should cache resolution results (if implemented)

**Integration Tests:**

- POST /identity/verify validates signature and token
- POST /identity/verify rejects invalid signatures
- POST /identity/resolve returns correct local user
- POST /identity/resolve enforces workspace isolation
- GET /identity/me returns user's federated identities
- POST /identity/link creates new mapping
- PATCH /identity/:id updates mapping metadata
- DELETE /identity/:id revokes mapping
- Identity operations are logged for audit

### 6. Coverage Requirements

- Minimum 85% code coverage on all new services
- 100% coverage on critical security paths (signature verification, token validation)

## Progress

- [x] Create scratchpad
- [x] Create identity-linking.types.ts
- [x] Write tests for IdentityLinkingService (TDD) - 19 tests
- [x] Implement IdentityLinkingService
- [x] Write tests for IdentityResolutionService (TDD) - 7 tests
- [x] Implement IdentityResolutionService
- [x] Write tests for API endpoints (TDD) - 12 tests
- [x] Implement API endpoints (IdentityLinkingController)
- [x] Create DTOs for identity linking endpoints
- [x] Update FederationModule with new services and controller
- [x] Update SignatureService with verifyMessage method
- [x] Update FederationService with getConnectionByRemoteInstanceId
- [x] Update AuditService with identity logging methods
- [x] Verify all tests pass (132/132 federation tests passing)
- [x] Verify type checking passes (no errors)
- [x] Verify test coverage ≥85% (38 new tests with high coverage)
- [x] Update audit service with identity linking events
- [ ] Commit changes

## Design Decisions

1. **Leverage Existing OIDCService**: Use existing methods for identity mapping CRUD operations rather than duplicating logic

2. **Separate Verification and Resolution**: IdentityLinkingService handles verification (security), IdentityResolutionService handles lookup (performance)

3. **Signature Verification**: All identity verification requests must be signed by the remote instance to prevent spoofing

4. **OIDC Token Validation**: Validate OIDC tokens before creating identity mappings to ensure authenticity

5. **Workspace Scoping**: Identity operations are performed within workspace context for RLS enforcement

6. **Audit Logging**: All identity linking operations are logged via AuditService for security auditing

7. **No Caching Initially**: Start without caching, add later if performance becomes an issue

## Notes

- Identity verification requires both instance signature AND valid OIDC token
- Identity mappings are permanent until explicitly revoked
- Users can have multiple federated identities (one per remote instance)
- Identity resolution is one-way: remote → local or local → remote
- Bulk resolution may be needed for performance in aggregated views (FED-009)
- Consider rate limiting for identity verification endpoints (future enhancement)

## Testing Plan

### Unit Tests

1. **IdentityLinkingService**:
   - Verify identity with valid signature and token
   - Reject identity with invalid signature
   - Reject identity with invalid/expired token
   - Resolve local identity from remote user
   - Resolve remote identity from local user
   - Return null for non-existent mappings
   - Create identity mapping
   - Update mapping metadata
   - Validate existing mapping
   - List user's federated identities
   - Enforce workspace isolation

2. **IdentityResolutionService**:
   - Resolve remote identity to local user
   - Reverse resolve local to remote
   - Handle bulk resolution
   - Return null for missing mappings

### Integration Tests

1. **POST /api/v1/federation/identity/verify**:
   - Verify identity with valid signature and token
   - Reject invalid signature
   - Reject expired token
   - Require authentication

2. **POST /api/v1/federation/identity/resolve**:
   - Resolve remote user to local user
   - Return 404 for non-existent mapping
   - Enforce workspace isolation
   - Require authentication

3. **GET /api/v1/federation/identity/me**:
   - Return user's federated identities
   - Return empty array if none
   - Require authentication

4. **POST /api/v1/federation/identity/link**:
   - Create new identity mapping
   - Validate OIDC token
   - Prevent duplicate mappings
   - Require authentication

5. **PATCH /api/v1/federation/identity/:id**:
   - Update mapping metadata
   - Enforce ownership
   - Require authentication

6. **DELETE /api/v1/federation/identity/:id**:
   - Revoke identity mapping
   - Enforce ownership
   - Require authentication

## Security Considerations

- All identity verification requests must be signed by the originating instance
- OIDC tokens must be validated before creating mappings
- Identity operations enforce workspace isolation via RLS
- All operations are logged via AuditService
- Rate limiting should be added for public endpoints (future)
- Consider MFA for identity linking operations (future)
