Files
stack/apps/api/src/federation/dto/query.dto.ts
Jason Woltje 1159ca42a7 feat(#88): implement QUERY message type for federation
Implement complete QUERY message protocol for federated queries between
Mosaic Stack instances, building on existing connection infrastructure.

Database Changes:
- Add FederationMessageType enum (QUERY, COMMAND, EVENT)
- Add FederationMessageStatus enum (PENDING, DELIVERED, FAILED, TIMEOUT)
- Add FederationMessage model for tracking all federation messages
- Add workspace and connection relations

Types & DTOs:
- QueryMessage: Signed query request payload
- QueryResponse: Signed query response payload
- QueryMessageDetails: API response type
- SendQueryDto: Client request DTO
- IncomingQueryDto: Validated incoming query DTO

QueryService:
- sendQuery: Send signed query to remote instance via ACTIVE connection
- handleIncomingQuery: Process and validate incoming queries
- processQueryResponse: Handle and verify query responses
- getQueryMessages: List workspace queries with optional status filter
- getQueryMessage: Get single query message details
- Message deduplication via unique messageId
- Signature verification using SignatureService
- Timestamp validation (5-minute window)

QueryController:
- POST /api/v1/federation/query: Send query (authenticated)
- POST /api/v1/federation/incoming/query: Receive query (public, signature-verified)
- GET /api/v1/federation/queries: List queries (authenticated)
- GET /api/v1/federation/queries/🆔 Get query details (authenticated)

Security:
- All messages signed with instance private key
- All responses verified with remote public key
- Timestamp validation prevents replay attacks
- Connection status validation (must be ACTIVE)
- Workspace isolation enforced via RLS

Testing:
- 15 QueryService tests (100% coverage)
- 9 QueryController tests (100% coverage)
- All tests passing with proper mocking
- TypeScript strict mode compliance

Refs #88

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 13:12:12 -06:00

54 lines
915 B
TypeScript

/**
* Query DTOs
*
* Data Transfer Objects for query message operations.
*/
import { IsString, IsOptional, IsObject, IsNotEmpty } from "class-validator";
import type { QueryMessage } from "../types/message.types";
/**
* DTO for sending a query to a remote instance
*/
export class SendQueryDto {
@IsString()
@IsNotEmpty()
connectionId!: string;
@IsString()
@IsNotEmpty()
query!: string;
@IsOptional()
@IsObject()
context?: Record<string, unknown>;
}
/**
* DTO for incoming query request from remote instance
*/
export class IncomingQueryDto implements QueryMessage {
@IsString()
@IsNotEmpty()
messageId!: string;
@IsString()
@IsNotEmpty()
instanceId!: string;
@IsString()
@IsNotEmpty()
query!: string;
@IsOptional()
@IsObject()
context?: Record<string, unknown>;
@IsNotEmpty()
timestamp!: number;
@IsString()
@IsNotEmpty()
signature!: string;
}