feat(#90): implement EVENT subscriptions for federation

Implement event pub/sub messaging for federation to enable real-time
event streaming between federated instances.

Features:
- Event subscription management (subscribe/unsubscribe)
- Event publishing to subscribed instances
- Event acknowledgment protocol
- Server-side event filtering based on subscriptions
- Full signature verification and connection validation

Implementation:
- FederationEventSubscription model for storing subscriptions
- EventService with complete event lifecycle management
- EventController with authenticated and public endpoints
- EventMessage, EventAck, and SubscriptionDetails types
- Comprehensive DTOs for all event operations

API Endpoints:
- POST /api/v1/federation/events/subscribe
- POST /api/v1/federation/events/unsubscribe
- POST /api/v1/federation/events/publish
- GET /api/v1/federation/events/subscriptions
- GET /api/v1/federation/events/messages
- POST /api/v1/federation/incoming/event (public)
- POST /api/v1/federation/incoming/event/ack (public)

Testing:
- 18 unit tests for EventService (89.09% coverage)
- 11 unit tests for EventController (83.87% coverage)
- All 29 tests passing
- Follows TDD red-green-refactor cycle

Technical Notes:
- Reuses existing FederationMessage model with eventType field
- Follows patterns from QueryService and CommandService
- Uses existing signature and connection infrastructure
- Supports hierarchical event type naming (e.g., "task.created")

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
This commit is contained in:
Jason Woltje
2026-02-03 13:45:00 -06:00
co-authored by Claude Sonnet 4.5
parent 9501aa3867
commit ca4f5ec011
10 changed files with 2395 additions and 5 deletions
@@ -12,6 +12,7 @@ import { FederationAuthController } from "./federation-auth.controller";
import { IdentityLinkingController } from "./identity-linking.controller";
import { QueryController } from "./query.controller";
import { CommandController } from "./command.controller";
import { EventController } from "./event.controller";
import { FederationService } from "./federation.service";
import { CryptoService } from "./crypto.service";
import { FederationAuditService } from "./audit.service";
@@ -22,6 +23,7 @@ import { IdentityLinkingService } from "./identity-linking.service";
import { IdentityResolutionService } from "./identity-resolution.service";
import { QueryService } from "./query.service";
import { CommandService } from "./command.service";
import { EventService } from "./event.service";
import { PrismaModule } from "../prisma/prisma.module";
@Module({
@@ -39,6 +41,7 @@ import { PrismaModule } from "../prisma/prisma.module";
IdentityLinkingController,
QueryController,
CommandController,
EventController,
],
providers: [
FederationService,
@@ -51,6 +54,7 @@ import { PrismaModule } from "../prisma/prisma.module";
IdentityResolutionService,
QueryService,
CommandService,
EventService,
],
exports: [
FederationService,
@@ -62,6 +66,7 @@ import { PrismaModule } from "../prisma/prisma.module";
IdentityResolutionService,
QueryService,
CommandService,
EventService,
],
})
export class FederationModule {}