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>
54 lines
915 B
TypeScript
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;
|
|
}
|