Commit Graph
366 Commits
Author SHA1 Message Date
jason.woltjeandClaude Opus 4.6 eca2c46e9d merge: resolve conflicts with develop (telemetry + lockfile)
Keep both Mosaic Telemetry section (from develop) and Matrix Dev
Environment section (from feature branch) in .env.example.
Regenerate pnpm-lock.yaml with both dependency trees merged.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 12:12:43 -06:00
jason.woltjeandClaude Opus 4.6 af9c5799af fix(#388): address PR review findings — fix WebSocket/REST bugs, improve error handling, fix types and comments
Critical fixes:
- Fix FormData field name mismatch (audio -> file) to match backend FileInterceptor
- Add /speech namespace to WebSocket connection URL
- Pass auth token in WebSocket handshake options
- Wrap audio.play() in try-catch for NotAllowedError and DOMException handling
- Replace bare catch block with named error parameter and descriptive message
- Add connect_error and disconnect event handlers to WebSocket
- Update JSDoc to accurately describe batch transcription (not real-time partial)

Important fixes:
- Emit transcription-error before disconnect in gateway auth failures
- Capture MediaRecorder error details and clean up media tracks on error
- Change TtsDefaultConfig.format type from string to AudioFormat
- Define canonical SPEECH_TIERS and AUDIO_FORMATS arrays as single source of truth
- Fix voice count from 54 to 53 in provider, AGENTS.md, and docs
- Fix inaccurate comments (Piper formats, tier prop, SpeachesProvider, TextValidationPipe)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 03:44:33 -06:00
jason.woltje d2c7602430 test(#405): add E2E integration tests for speech services
Adds comprehensive integration tests covering all 9 required scenarios:
1. REST transcription (POST /speech/transcribe)
2. REST synthesis (POST /speech/synthesize)
3. Provider fallback (premium -> default -> fallback chain)
4. WebSocket streaming transcription lifecycle
5. Audio MIME type validation (reject invalid formats)
6. File size limit enforcement (25 MB max)
7. Authentication on all endpoints (401 without token)
8. Voice listing with tier filtering (GET /speech/voices)
9. Health check status (GET /speech/health)

Uses NestJS testing module with mocked providers (CI-compatible).
30 test cases, all passing.

Fixes #405
2026-02-15 03:26:05 -06:00
jason.woltjeandClaude Opus 4.6 24065aa199 docs(#406): add speech services documentation
Comprehensive documentation for the speech services module:
- docs/SPEECH.md: Architecture, API reference, WebSocket protocol,
  environment variables, provider configuration, Docker setup,
  GPU VRAM budget, and frontend integration examples
- apps/api/src/speech/AGENTS.md: Module structure, provider pattern,
  how to add new providers, gotchas, and test patterns
- README.md: Speech capabilities section with quick start

Fixes #406

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 03:23:22 -06:00
jason.woltjeandClaude Opus 4.6 8d19ac1f4b fix(#377): remediate code review and security findings
- Fix sendThreadMessage room mismatch: use channelId from options instead of hardcoded controlRoomId
- Add .catch() to fire-and-forget handleRoomMessage to prevent silent error swallowing
- Wrap dispatchJob in try-catch for user-visible error reporting in handleFixCommand
- Add MATRIX_BOT_USER_ID validation in connect() to prevent infinite message loops
- Fix streamResponse error masking: wrap finally/catch side-effects in try-catch
- Replace unsafe type assertion with public getClient() in MatrixRoomService
- Add orphaned room warning in provisionRoom on DB failure
- Add provider identity to Herald error logs
- Add channelId to ThreadMessageOptions interface and all callers
- Add missing env var warnings in BridgeModule factory
- Fix JSON injection in setup-bot.sh: use jq for safe JSON construction

Fixes #377

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 03:00:53 -06:00
jason.woltjeandClaude Opus 4.6 28c9e6fe65 feat(#397): implement WebSocket streaming transcription gateway
Add SpeechGateway with Socket.IO namespace /speech for real-time
streaming transcription. Supports start-transcription, audio-chunk,
and stop-transcription events with session management, authentication,
and buffer size rate limiting. Includes 29 unit tests covering
authentication, session lifecycle, error handling, cleanup, and
client isolation.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:54:41 -06:00
jason.woltjeandClaude Opus 4.6 527262af38 feat(#392): create /api/speech/transcribe REST endpoint
Add SpeechController with POST /api/speech/transcribe for audio
transcription and GET /api/speech/health for provider status.
Uses AudioValidationPipe for file upload validation and returns
results in standard { data: T } envelope.

Includes 10 unit tests covering transcribe with options, error
propagation, and all health status combinations.

Fixes #392

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:47:52 -06:00
jason.woltjeandClaude Opus 4.6 9cc70dbe31 test(#385): Matrix bridge integration tests
- BridgeModule DI verification (conditional loading)
- Command flow: message -> parser -> dispatch
- Herald multi-provider broadcast
- Room-workspace mapping integration
- Streaming flow verification
- Multi-provider coexistence

Refs #385

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:39:59 -06:00
jason.woltjeandClaude Opus 4.6 6c465566f6 feat(#395): implement Piper TTS provider via OpenedAI Speech
Add fallback-tier TTS provider using Piper via OpenedAI Speech for
ultra-lightweight CPU-only synthesis. Maps 6 standard OpenAI voice
names (alloy, echo, fable, onyx, nova, shimmer) to Piper voices.
Update factory to use the new PiperTtsProvider class, replacing the
inline stub. Includes 37 unit tests covering provider identity,
voice mapping, and voice listing.

Fixes #395

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:39:20 -06:00
jason.woltje 7b4fda6011 feat(#398): add audio/text validation pipes and speech DTOs
Create AudioValidationPipe for MIME type and file size validation,
TextValidationPipe for TTS text input validation, and DTOs for
transcribe/synthesize endpoints. Includes 36 unit tests.

Fixes #398
2026-02-15 02:37:54 -06:00
jason.woltjeandClaude Opus 4.6 93cd31435b feat(#383): Streaming AI responses via Matrix message edits
- Add MatrixStreamingService with editMessage, setTypingIndicator, streamResponse
- Rate-limited edits (500ms) for incremental streaming output
- Typing indicator management during generation
- Graceful error handling and fallback for non-streaming scenarios
- Add optional editMessage to IChatProvider interface
- Add getClient() accessor to MatrixService for streaming service
- Register MatrixStreamingService in BridgeModule
- Tests: 20 tests pass

Refs #383

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:34:36 -06:00
jason.woltjeandClaude Opus 4.6 d37c78f503 feat(#394): implement Chatterbox TTS provider with voice cloning
Add ChatterboxSynthesizeOptions interface with referenceAudio and
emotionExaggeration fields, and comprehensive unit tests (26 tests)
covering voice cloning, emotion control, clamping, graceful degradation,
and cross-language support.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:29:38 -06:00
jason.woltjeandClaude Opus 4.6 79b1d81d27 feat(#393): implement Kokoro-FastAPI TTS provider with voice catalog
Extract KokoroTtsProvider from factory into its own module with:
- Full voice catalog of 54 built-in voices across 8 languages
- Voice metadata parsing from ID prefix (language, gender, accent)
- Exported constants for supported formats and speed range
- Comprehensive unit tests (48 tests)
- Fix lint/type errors in chatterbox provider (Prettier + unsafe cast)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:27:47 -06:00
jason.woltje ad24720616 feat(#382): Herald Service: broadcast to all active chat providers
- Replace direct DiscordService injection with CHAT_PROVIDERS array
- Herald broadcasts to ALL active chat providers (Discord, Matrix, future)
- Graceful error handling — one provider failure doesn't block others
- Skips disconnected providers automatically
- Tests verify multi-provider broadcasting behavior
- Fix lint: remove unnecessary conditional in matrix.service.ts

Refs #382
2026-02-15 02:25:55 -06:00
jason.woltje b5edb4f37e feat(#391): add base TTS provider and factory classes
Add the BaseTTSProvider abstract class and TTS provider factory that were
part of the tiered TTS architecture but missed from the previous commit.

- BaseTTSProvider: abstract base with synthesize(), listVoices(), isHealthy()
- tts-provider.factory: creates Kokoro/Chatterbox/Piper providers from config
- 30 tests (22 base provider + 8 factory)

Refs #391
2026-02-15 02:20:24 -06:00
jason.woltje 3ae9e53bcc feat(#391): implement tiered TTS provider architecture with base class
Add abstract BaseTTSProvider class that implements common OpenAI-compatible
TTS logic using the OpenAI SDK with configurable baseURL. Includes synthesize(),
listVoices(), and isHealthy() methods. Create TTS provider factory that
dynamically registers Kokoro (default), Chatterbox (premium), and Piper
(fallback) providers based on configuration. Update SpeechModule to use
the factory for TTS_PROVIDERS injection token.

Also fixes lint error in speaches-stt.provider.ts (Array<T> -> T[]).

30 tests added (22 base provider + 8 factory), all passing.

Fixes #391
2026-02-15 02:19:46 -06:00
jason.woltje 771ed484e4 feat(#379): Register MatrixService in BridgeModule with conditional loading
- Add CHAT_PROVIDERS injection token for bridge-agnostic access
- Conditional loading based on env vars (DISCORD_BOT_TOKEN, MATRIX_ACCESS_TOKEN)
- Both bridges can run simultaneously
- No crash if neither bridge is configured
- Tests verify all configuration combinations

Refs #379
2026-02-15 02:18:55 -06:00
jason.woltje 7d22c2490a feat(#380): Workspace-to-Matrix-Room mapping and provisioning
- 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
2026-02-15 02:16:29 -06:00
jason.woltjeandClaude Opus 4.6 306c2e5bd8 fix(#371): resolve TypeScript strictness errors in telemetry tracking
- llm-cost-table.ts: Add undefined guard for MODEL_COSTS lookup
- llm-telemetry-tracker.service.ts: Allow undefined in callingContext
  for exactOptionalPropertyTypes compatibility

Refs #371

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:10:22 -06:00
jason.woltjeandClaude Opus 4.6 ed23293e1a feat(#373): prediction integration for cost estimation
- Create PredictionService for pre-task cost/token estimates
- Refresh common predictions on startup
- Integrate predictions into LLM telemetry tracker
- Add GET /api/telemetry/estimate endpoint
- Graceful degradation when no prediction data available
- Add unit tests for prediction service

Refs #373

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:10:22 -06:00
jason.woltjeandClaude Opus 4.6 fcecf3654b feat(#371): track LLM task completions via Mosaic Telemetry
- Create LlmTelemetryTrackerService for non-blocking event emission
- Normalize token usage across Anthropic, OpenAI, Ollama providers
- Add cost table with per-token pricing in microdollars
- Instrument chat, chatStream, and embed methods
- Infer task type from calling context
- Aggregate streaming tokens after stream ends with fallback estimation
- Add 69 unit tests for tracker service, cost table, and LLM service

Refs #371

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:10:22 -06:00
jason.woltjeandClaude Opus 4.6 314dd24dce feat(#369): install @mosaicstack/telemetry-client in API
- Add .npmrc with scoped Gitea npm registry for @mosaicstack packages
- Create MosaicTelemetryModule (global, lifecycle-aware) at
  apps/api/src/mosaic-telemetry/
- Create MosaicTelemetryService wrapping TelemetryClient with
  convenience methods: trackTaskCompletion, getPrediction,
  refreshPredictions, eventBuilder
- Create mosaic-telemetry.config.ts for env var integration via
  NestJS ConfigService
- Register MosaicTelemetryModule in AppModule
- Add 32 unit tests covering module init, service methods, disabled
  mode, dry-run mode, and lifecycle management

Refs #369

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:10:22 -06:00
jason.woltjeandClaude Opus 4.6 c40373fa3b feat(#389): create SpeechModule with provider abstraction layer
Add SpeechModule with provider interfaces and service skeleton for
multi-tier TTS fallback (premium -> default -> fallback) and STT
transcription support. Includes 27 unit tests covering provider
selection, fallback logic, and availability checks.

- ISTTProvider interface with transcribe/isHealthy methods
- ITTSProvider interface with synthesize/listVoices/isHealthy methods
- Shared types: SpeechTier, TranscriptionResult, SynthesisResult, etc.
- SpeechService with graceful TTS fallback chain
- NestJS injection tokens (STT_PROVIDER, TTS_PROVIDERS)
- SpeechModule registered in AppModule
- ConfigModule integration via speechConfig registerAs factory

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:09:45 -06:00
jason.woltjeandClaude Opus 4.6 5b5d3811d6 feat(#378): Install matrix-bot-sdk and create MatrixService skeleton
- Add matrix-bot-sdk dependency to @mosaic/api
- Create MatrixService implementing IChatProvider interface
- Support connect/disconnect, message sending, thread management
- Parse @mosaic and !mosaic command prefixes
- Delegate commands to StitcherService (same flow as Discord)
- Add comprehensive unit tests with mocked MatrixClient (31 tests)
- Add Matrix env vars to .env.example

Refs #378

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 02:04:39 -06:00
jason.woltje 4cc43bece6 feat(#401): add speech services config and env vars
Add SpeechConfig with typed configuration and startup validation for
STT (Whisper/Speaches), TTS default (Kokoro), TTS premium (Chatterbox),
and TTS fallback (Piper/OpenedAI). Includes registerAs factory for
NestJS ConfigModule integration, .env.example documentation, and 51
unit tests covering all validation paths.

Refs #401
2026-02-15 02:03:21 -06:00
jason.woltjeandClaude Opus 4.6 8ce6843af2 fix(database,api): add 6 missing table migrations and fix CORS health checks
Database: 6 models in the Prisma schema had no CREATE TABLE migration:
cron_schedules, workspace_llm_settings, quality_gates, task_rejections,
token_budgets, llm_usage_logs. Same root cause as the federation tables.

CORS: Health check requests (Docker, load balancers) don't send Origin
headers. The CORS config was rejecting these in production, causing
/health to return 500 and Docker to mark the container as unhealthy.
Requests without Origin headers are not cross-origin per the CORS spec
and should be allowed through.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 01:49:13 -06:00
jason.woltjeandClaude Opus 4.6 d2003a7b03 fix(api): make federation config validation non-fatal at startup
Federation is optional and should not prevent the app from starting
when DEFAULT_WORKSPACE_ID is not set. Changed from throwing (crash)
to logging a warning. The endpoint-level validation in the controller
still rejects requests when federation is unconfigured.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 01:08:09 -06:00
jason.woltjeandClaude Opus 4.6 8733a643bf fix(api): remove "type": "module" conflicting with CommonJS build output
The NestJS tsconfig compiles to CommonJS (module: "CommonJS") but
package.json had "type": "module", causing Node.js v24 to treat the
CJS output as ESM and fail with "exports is not defined in ES module
scope" at startup.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 00:53:43 -06:00
jason.woltjeandClaude Opus 4.6 91307c87cc fix(database): add missing federation table migrations
Federation models (FederationConnection, FederatedIdentity,
FederationMessage) and their enums were defined in the Prisma schema
but never had CREATE TABLE migrations. This caused the
20260203_add_federation_event_subscriptions migration to fail with
"relation federation_messages does not exist".

Adds new migration 20260202200000 to create the 3 missing enums,
3 missing tables, all indexes, and foreign keys. Removes the
now-redundant ALTER TABLE from the 20260203 migration since
event_type is created with the table.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 00:29:37 -06:00
jason.woltjeandClaude Opus 4.6 14162b9213 fix(api): use node_modules prisma binary in entrypoint
npx is unavailable in production image since npm is removed.
Use ./node_modules/.bin/prisma directly instead.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 00:05:46 -06:00
jason.woltjeandClaude Opus 4.6 bcee4fa601 fix(api): auto-run migrations on container start and fix ESM warning
- Add docker-entrypoint.sh that runs prisma migrate deploy before
  starting the app, ensuring all tables exist on deployment
- Add "type": "module" to package.json to eliminate Node.js ESM
  reparsing warning for eslint.config.js

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-14 16:47:57 -06:00
jason.woltjeandClaude Opus 4.6 0ca3945061 fix(api): resolve Docker startup failures (secrets, Redis, Prisma)
- Pass BETTER_AUTH_SECRET through all 6 docker-compose files to API container
- Fix BullModule to parse VALKEY_URL instead of VALKEY_HOST/VALKEY_PORT,
  matching all other Redis consumers in the codebase
- Migrate Prisma encryption from removed $use() middleware to $extends()
  client extensions (Prisma 6.x compatibility), keeping extends PrismaClient
  pattern with only account and llmProviderInstance getters overridden

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-14 11:04:04 -06:00
jason.woltjeandClaude Opus 4.6 7b892d5197 fix(api): import AuthModule in FederationModule for DI resolution
AuthGuard used across federation controllers depends on AuthService,
which requires AuthModule to be imported. Matches pattern used by
TasksModule, ProjectsModule, and CredentialsModule.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-13 22:36:11 -06:00
jason.woltjeandClaude Opus 4.6 e23490a5f7 fix(api): remove redundant CsrfGuard from FederationController
CsrfGuard is already applied globally via APP_GUARD in AppModule.
The explicit @UseGuards(CsrfGuard) on FederationController caused a
DI error because CsrfService is not provided in FederationModule.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-13 22:14:03 -06:00
Jason WoltjeandClaude Opus 4.6 0363a14098 fix(#367): migrate Node.js 20 → 24 LTS
Node.js 24 (Krypton) entered Active LTS on 2026-02-09. Update all
Dockerfiles, CI pipelines, and engine constraint from node:20-alpine
to node:24-alpine. Corrected .trivyignore: tar CVEs come from Next.js
16.1.6 bundled [email protected] (not npm). Orchestrator and API images are
clean; web image needs Next.js upstream fix.

Fixes #367

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-13 15:20:01 -06:00
Jason WoltjeandClaude Opus 4.6 3833805a93 fix(ci): mitigate 11 upstream CVEs at source instead of suppressing
- docker/postgres/Dockerfile: build gosu from source with Go 1.26 via
  multi-stage build (eliminates 1 CRITICAL + 5 HIGH Go stdlib CVEs)
- apps/{api,web,orchestrator}/Dockerfile: remove npm from production
  images (eliminates 5 HIGH CVEs in npm's bundled cross-spawn/glob/tar)
- .trivyignore: trimmed from 16 to 5 CVEs (OpenBao only — 4 false
  positives from Go pseudo-version + 1 real Go stdlib waiting on upstream)

Fixes #363

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-12 17:10:44 -06:00
jason.woltjeandClaude Opus 4.6 e368083e84 fix(api): import AuthModule in CredentialsModule for DI resolution
CredentialsController uses AuthGuard which depends on AuthService.
NestJS resolves guard dependencies in the module context, so
CredentialsModule needs to import AuthModule directly.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-11 21:14:20 -06:00
jason.woltjeandClaude Opus 4.6 9ff1e69860 chore(api): remove debug statements from Dockerfile
Remove temporary debug RUN layers that were added during initial
build troubleshooting. These add build time and leak directory
structure into build logs unnecessarily.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-11 20:54:37 -06:00
jason.woltjeandClaude Opus 4.6 ab64583951 fix: resolve deployment crashes in coordinator and API services
Coordinator: install all dependencies from pyproject.toml instead of
hardcoded subset (missing slowapi, anthropic, opentelemetry-*).

API: FederationAgentService now gracefully disables when orchestrator
URL is not configured instead of throwing and crashing the app.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-10 09:41:54 -06:00
jason.woltjeandClaude Opus 4.6 c4f6552e12 docs(agents): add AGENTS.md context files for all modules
Adds directory-specific agent context templates for AI-assisted
development across all apps and packages.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-09 22:04:43 -06:00
Jason WoltjeandClaude Opus 4.6 946d84442a fix(deps): patch axios DoS and transitive prototype pollution/decompression vulns
Bump axios ^1.13.4→^1.13.5 (GHSA-43fc-jf86-j433). Add pnpm overrides for
lodash/lodash-es >=4.17.23 and undici >=6.23.0 to resolve transitive
vulnerabilities via chevrotain and discord.js.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-09 13:07:10 -06:00
jason.woltje 709499c167 fix(api,orchestrator): fix remaining dependency injection issues
API:
- Add AuthModule import to JobEventsModule
- Add AuthModule import to JobStepsModule
- Fixes: AuthGuard dependency resolution in job modules

Orchestrator:
- Add @Optional() decorator to docker parameter in DockerSandboxService
- Fixes: NestJS trying to inject Docker class as dependency

All modules using AuthGuard must import AuthModule.
Docker parameter is optional for testing, needs @Optional() decorator.
2026-02-08 22:24:37 -06:00
jason.woltje ecfd02541f fix(test): add VaultService dependencies to job-events performance test
- Add ConfigService mock for encryption configuration
- Add VaultService and CryptoService to test module
- Fixes: PrismaService dependency injection error in test

PrismaService requires VaultService for credential encryption.
Performance tests now properly provide all required dependencies.

Refs #341 (pipeline test failure)
2026-02-08 22:04:24 -06:00
jason.woltje 4545c6dc7a fix(api,orchestrator): fix dependency injection and Docker build issues
API:
- Add AuthModule import to RunnerJobsModule
- Fixes: Nest can't resolve dependencies of AuthGuard

Orchestrator:
- Remove --prod flag from dependency installation
- Copy full node_modules tree to production stage
- Align Dockerfile with API pattern for monorepo builds
- Fixes: Cannot find module '@nestjs/core'

Both services now match the working API Dockerfile pattern.
2026-02-08 21:59:19 -06:00
jason.woltjeandClaude Opus 4.6 dc551f138a fix(test): Use correct CI detection for Woodpecker
Woodpecker sets CI=woodpecker and CI_PIPELINE_EVENT, not CI=true.
Updated the CI detection to check for both.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-07 21:47:53 -06:00
jason.woltjeandClaude Opus 4.6 75766a37b4 fix(test): Skip loading .env.test in CI environments
The .env.test file was being loaded in CI and overriding the CI-provided
DATABASE_URL, causing tests to try connecting to localhost:5432 instead of
the postgres:5432 service.

Fix: Only load .env.test when NOT in CI (check for CI or WOODPECKER env vars).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-07 21:44:02 -06:00
jason.woltjeandClaude Opus 4.6 0b0666558e fix(test): Fix DATABASE_URL environment setup for integration tests
Fixes integration test failures caused by missing DATABASE_URL environment variable.

Changes:
- Add dotenv as dev dependency to load .env.test in vitest setup
- Add .env.test to .gitignore to prevent committing test credentials
- Create .env.test.example with warning comments for documentation
- Add conditional test skipping when DATABASE_URL is not available
- Add DATABASE_URL format validation in vitest setup
- Add error handling to test cleanup to prevent silent failures
- Remove filesystem path disclosure from error messages

The fix allows integration tests to:
- Load DATABASE_URL from .env.test locally for developers with database setup
- Skip gracefully if DATABASE_URL is not available (no database running)
- Connect to postgres service in CI where DATABASE_URL is explicitly provided

Tests affected: auth-rls.integration.spec.ts and other integration tests
requiring real database connections.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-07 17:46:59 -06:00
jason.woltje 4552c2c460 fix(test): Add ENCRYPTION_KEY to bridge.module.spec.ts and fix API lint errors 2026-02-07 17:33:32 -06:00
jason.woltjeandClaude Opus 4.6 73074932f6 feat(#360): Add federation credential isolation
Implement explicit deny-lists in QueryService and CommandService to prevent
user credentials from leaking across federation boundaries.

## Changes

### Core Implementation
- QueryService: Block all credential-related queries with keyword detection
- CommandService: Block all credential operations (create/update/delete/read)
- Case-insensitive keyword matching for both queries and commands

### Security Features
- Deny-list includes: credential, api_key, secret, token, password, oauth
- Errors returned for blocked operations
- No impact on existing allowed operations (tasks, events, projects, agent commands)

### Testing
- Added 2 unit tests to query.service.spec.ts
- Added 3 unit tests to command.service.spec.ts
- Added 8 integration tests in credential-isolation.integration.spec.ts
- All 377 federation tests passing

### Documentation
- Created comprehensive security doc at docs/security/federation-credential-isolation.md
- Documents 4 security guarantees (G1-G4)
- Includes testing strategy and incident response procedures

## Security Guarantees

1. G1: Credential Confidentiality - Credentials never leave instance in plaintext
2. G2: Cross-Instance Isolation - Compromised key on one instance doesn't affect others
3. G3: Query/Command Isolation - Federated instances cannot query/modify credentials
4. G4: Accidental Exposure Prevention - Credentials cannot leak via messages

## Defense-in-Depth

This implementation adds application-layer protection on top of existing:
- Transit key separation (mosaic-credentials vs mosaic-federation)
- Per-instance OpenBao servers
- Workspace-scoped credential access

Fixes #360

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-07 16:55:49 -06:00
jason.woltje 46d0a06ef5 feat(#356): Build credential CRUD API endpoints
Implement comprehensive CRUD API for managing user credentials with encryption,
RLS, and audit logging following TDD methodology.

Features:
- POST /api/credentials - Create encrypted credential
- GET /api/credentials - List credentials (masked values only)
- GET /api/credentials/:id - Get single credential (masked)
- GET /api/credentials/:id/value - Decrypt plaintext (rate limited 10/min)
- PATCH /api/credentials/:id - Update metadata
- POST /api/credentials/:id/rotate - Rotate credential value
- DELETE /api/credentials/:id - Soft delete

Security:
- All values encrypted via VaultService (TransitKey.CREDENTIALS)
- List/Get endpoints NEVER return plaintext (only maskedValue)
- getValue endpoint rate limited to 10 requests/minute per user
- All operations audit-logged with CREDENTIAL_* ActivityAction
- RLS enforces per-user isolation via getRlsClient() pattern
- Input validation via class-validator DTOs

Testing:
- 26/26 unit tests passing
- 95.71% code coverage (exceeds 85% requirement)
  - Service: 95.16%
  - Controller: 100%
- TypeScript checks pass

Files created:
- apps/api/src/credentials/credentials.service.ts
- apps/api/src/credentials/credentials.service.spec.ts
- apps/api/src/credentials/credentials.controller.ts
- apps/api/src/credentials/credentials.controller.spec.ts
- apps/api/src/credentials/credentials.module.ts
- apps/api/src/credentials/dto/*.dto.ts (5 DTOs)

Files modified:
- apps/api/src/app.module.ts - imported CredentialsModule

Note: Admin credentials endpoints deferred to future issue. Current
implementation covers all user credential endpoints.

Refs #346
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-07 16:50:02 -06:00