Prisma client was generated for debian-openssl-1.1.x but the
node:24-slim Docker image runs Debian Bookworm with OpenSSL 3.0.x.
Adding explicit binaryTargets ensures the correct query engine is
always generated regardless of build host.
Also removes inline comments from .env.example rate limit values —
Portainer treats trailing comments as part of the value.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add matrix_room_id column to workspace table (migration)
- Create MatrixRoomService for room provisioning and mapping
- Auto-create Matrix room on workspace provisioning (when configured)
- Support manual room linking for existing workspaces
- Unit tests for all mapping operations
Refs #380
Implements comprehensive LLM usage tracking with analytics endpoints.
Implementation:
- Added LlmUsageLog model to Prisma schema
- Created llm-usage module with service, controller, and DTOs
- Added tracking for token usage, costs, and durations
- Implemented analytics aggregation by provider, model, and task type
- Added filtering by workspace, provider, model, user, and date range
Testing:
- 20 unit tests with 90.8% coverage (exceeds 85% requirement)
- Tests for service and controller with full error handling
- Tests use Vitest following project conventions
API Endpoints:
- GET /api/llm-usage/analytics - Aggregated usage analytics
- GET /api/llm-usage/by-workspace/:workspaceId - Workspace usage logs
- GET /api/llm-usage/by-workspace/:workspaceId/provider/:provider - Provider logs
- GET /api/llm-usage/by-workspace/:workspaceId/model/:model - Model logs
Database:
- LlmUsageLog table with indexes for efficient queries
- Relations to User, Workspace, and LlmProviderInstance
- Ready for migration with: pnpm prisma migrate dev
Refs #309
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Implements federated command messages following TDD principles and
mirroring the QueryService pattern for consistency.
## Implementation
### Schema Changes
- Added commandType and payload fields to FederationMessage model
- Supports COMMAND message type (already defined in enum)
- Applied schema changes with prisma db push
### Type Definitions
- CommandMessage: Request structure with commandType and payload
- CommandResponse: Response structure with correlation
- CommandMessageDetails: Full message details for API responses
### CommandService
- sendCommand(): Send command to remote instance with signature
- handleIncomingCommand(): Process incoming commands with verification
- processCommandResponse(): Handle command responses
- getCommandMessages(): List commands for workspace
- getCommandMessage(): Get single command details
- Full signature verification and timestamp validation
- Error handling and status tracking
### CommandController
- POST /api/v1/federation/command - Send command (authenticated)
- POST /api/v1/federation/incoming/command - Handle incoming (public)
- GET /api/v1/federation/commands - List commands (authenticated)
- GET /api/v1/federation/commands/:id - Get command (authenticated)
## Testing
- CommandService: 15 tests, 90.21% coverage
- CommandController: 8 tests, 100% coverage
- All 23 tests passing
- Exceeds 85% coverage requirement
- Total 47 tests passing (includes command tests)
## Security
- RSA signature verification for all incoming commands
- Timestamp validation to prevent replay attacks
- Connection status validation
- Authorization checks on command types
## Quality Checks
- TypeScript compilation: PASSED
- All tests: 47 PASSED
- Code coverage: >85% (90.21% for CommandService, 100% for CommandController)
- Linting: PASSED
Fixes#89
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements federated authentication infrastructure using OIDC:
- Add FederatedIdentity model to Prisma schema for identity mapping
- Create OIDCService with identity linking and token validation
- Add FederationAuthController with 5 endpoints:
* POST /auth/initiate - Start federated auth flow
* POST /auth/link - Link identity to remote instance
* GET /auth/identities - List user's federated identities
* DELETE /auth/identities/:id - Revoke identity
* POST /auth/validate - Validate federated token
- Create comprehensive type definitions for OIDC flows
- Add audit logging for security events
- Write 24 passing tests (14 service + 10 controller)
- Achieve 79% coverage for OIDCService, 100% for controller
Notes:
- Token validation and auth URL generation are placeholder implementations
- Full JWT validation will be added when federation OIDC is actively used
- Identity mappings enforce workspace isolation
- All endpoints require authentication except /validate
Refs #86
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implemented optimistic locking with version field and SELECT FOR UPDATE
transactions to prevent data corruption from concurrent job status updates.
Changes:
- Added version field to RunnerJob schema for optimistic locking
- Created migration 20260202_add_runner_job_version_for_concurrency
- Implemented ConcurrentUpdateException for conflict detection
- Updated RunnerJobsService methods with optimistic locking:
* updateStatus() - with version checking and retry logic
* updateProgress() - with version checking and retry logic
* cancel() - with version checking and retry logic
- Updated CoordinatorIntegrationService with SELECT FOR UPDATE:
* updateJobStatus() - transaction with row locking
* completeJob() - transaction with row locking
* failJob() - transaction with row locking
* updateJobProgress() - optimistic locking
- Added retry mechanism (3 attempts) with exponential backoff
- Added comprehensive concurrency tests (10 tests, all passing)
- Updated existing test mocks to support updateMany
Test Results:
- All 10 concurrency tests passing ✓
- Tests cover concurrent status updates, progress updates, completions,
cancellations, retry logic, and exponential backoff
This fix prevents race conditions that could cause:
- Lost job results (double completion)
- Lost progress updates
- Invalid status transitions
- Data corruption under concurrent access
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add composite index [jobId, timestamp] to improve query performance
for the most common job_events access patterns.
Changes:
- Add @@index([jobId, timestamp]) to JobEvent model in schema.prisma
- Create migration 20260202122655_add_job_events_composite_index
- Add performance tests to validate index effectiveness
- Document index design rationale in scratchpad
- Fix lint errors in api-key.guard, herald.service, runner-jobs.service
Rationale:
The composite index [jobId, timestamp] optimizes the dominant query
pattern used across all services:
- JobEventsService.getEventsByJobId (WHERE jobId, ORDER BY timestamp)
- RunnerJobsService.streamEvents (WHERE jobId + timestamp range)
- RunnerJobsService.findOne (implicit jobId filter + timestamp order)
This index provides:
- Fast filtering by jobId (highly selective)
- Efficient timestamp-based ordering
- Optimal support for timestamp range queries
- Backward compatibility with jobId-only queries
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add database-backed quality gate configuration for workspaces with
full CRUD operations and default gate seeding.
Schema:
- Add QualityGate model with workspace relation
- Support for custom commands and regex patterns
- Enable/disable and ordering support
Service:
- CRUD operations for quality gates
- findEnabled: Get ordered, enabled gates
- reorder: Bulk reorder with transaction
- seedDefaults: Seed 4 default gates
- toOrchestratorFormat: Convert to orchestrator interface
Endpoints:
- GET /workspaces/:id/quality-gates - List
- GET /workspaces/:id/quality-gates/:gateId - Get one
- POST /workspaces/:id/quality-gates - Create
- PATCH /workspaces/:id/quality-gates/:gateId - Update
- DELETE /workspaces/:id/quality-gates/:gateId - Delete
- POST /workspaces/:id/quality-gates/reorder
- POST /workspaces/:id/quality-gates/seed-defaults
Default gates: Build, Lint, Test, Coverage (85%)
Tests: 25 passing with 95.16% coverage
Fixes#135
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement Personality system backend with database schema, service,
controller, and comprehensive tests. Personalities define assistant
behavior with system prompts and LLM configuration.
Changes:
- Update Personality model in schema.prisma with LLM provider relation
- Create PersonalitiesService with CRUD and default management
- Create PersonalitiesController with REST endpoints
- Add DTOs with validation (create/update)
- Add entity for type safety
- Remove unused PromptFormatterService
- Achieve 26 tests with full coverage
Endpoints:
- GET /personality - List all
- GET /personality/default - Get default
- GET /personality/by-name/:name - Get by name
- GET /personality/:id - Get one
- POST /personality - Create
- PATCH /personality/:id - Update
- DELETE /personality/:id - Delete
- POST /personality/:id/set-default - Set default
Fixes#130
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added EntryVersion model with author relation
- Implemented automatic versioning on entry create/update
- Added API endpoints for version history:
- GET /api/knowledge/entries/:slug/versions - list versions
- GET /api/knowledge/entries/:slug/versions/:version - get specific
- POST /api/knowledge/entries/:slug/restore/:version - restore version
- Created VersionHistory.tsx component with timeline view
- Added History tab to entry detail page
- Supports version viewing and restoring
- Includes comprehensive tests for version operations
- All TypeScript types are explicit and type-safe
- Create workspace listing page at /settings/workspaces
- List all user workspaces with role badges
- Create new workspace functionality
- Display member count per workspace
- Create workspace detail page at /settings/workspaces/[id]
- Workspace settings (name, ID, created date)
- Member management with role editing
- Invite member functionality
- Delete workspace (owner only)
- Add workspace components:
- WorkspaceCard: Display workspace info with role badge
- WorkspaceSettings: Edit workspace settings and delete
- MemberList: Display and manage workspace members
- InviteMember: Send invitations with role selection
- Add WorkspaceMemberWithUser type to shared package
- Follow existing app patterns for styling and structure
- Use mock data (ready for API integration)
Implements #9, #10
- Team model with workspace membership
- TeamMember model with role-based access (OWNER, ADMIN, MEMBER)
- Row-Level Security policies for tenant isolation on 19 tables
- Helper functions: current_user_id(), is_workspace_member(), is_workspace_admin()
- Developer utilities in src/lib/db-context.ts for easy RLS integration
- Comprehensive documentation in docs/design/multi-tenant-rls.md
Database migrations:
- 20260129220941_add_team_model: Adds Team and TeamMember tables
- 20260129221004_add_rls_policies: Enables RLS and creates policies
Security features:
- Complete database-level tenant isolation
- Automatic query filtering based on workspace membership
- Defense-in-depth security with application and database layers
- Performance-optimized with indexes on workspace_id
- Add DomainsModule with full CRUD, search, and activity logging
- Add IdeasModule with quick capture endpoint
- Add LayoutsModule for user dashboard layouts
- Add WidgetsModule for widget definitions (read-only)
- Update ActivityService with domain/idea logging methods
- Register all new modules in AppModule
- Integrated BetterAuth library for modern authentication
- Added Session, Account, and Verification database tables
- Created complete auth module with service, controller, guards, and decorators
- Implemented shared authentication types in @mosaic/shared package
- Added comprehensive test coverage (26 tests passing)
- Documented type sharing strategy for monorepo
- Updated environment configuration with OIDC and JWT settings
Key architectural decisions:
- BetterAuth over Passport.js for better TypeScript support
- Separation of User (DB entity) vs AuthUser (client-safe subset)
- Shared types package to prevent FE/BE drift
- Factory pattern for auth config to use shared Prisma instance
Ready for frontend integration (Issue #6).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes#4