Commit Graph

281 Commits

Author SHA1 Message Date
Jason Woltje
3b2356f5a0 feat(#413): add OIDC provider health check with 30s cache
All checks were successful
ci/woodpecker/push/api Pipeline was successful
- isOidcProviderReachable() fetches discovery URL with 2s timeout
- getAuthConfig() omits authentik when provider unreachable
- 30-second cache prevents repeated network calls

Refs #413

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:20:05 -06:00
Jason Woltje
d2605196ac test(#413): add secret-leakage prevention test for GET /auth/config
All checks were successful
ci/woodpecker/push/api Pipeline was successful
Verifies response body never contains CLIENT_SECRET, CLIENT_ID,
JWT_SECRET, BETTER_AUTH_SECRET, CSRF_SECRET, or issuer URLs.

Refs #413

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:16:59 -06:00
Jason Woltje
2d59c4b2e4 feat(#413): implement GET /auth/config discovery endpoint
All checks were successful
ci/woodpecker/push/api Pipeline was successful
- Add getAuthConfig() to AuthService (email always, OIDC when enabled)
- Add GET /auth/config public endpoint with Cache-Control: 5min
- Place endpoint before catch-all to avoid interception

Refs #413

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:14:51 -06:00
Jason Woltje
9ae21c4c15 fix(#412): wrap BetterAuth handler in try/catch with error logging
All checks were successful
ci/woodpecker/push/api Pipeline was successful
Refs #412

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:08:47 -06:00
Jason Woltje
976d14d94b fix(#412): enable PKCE, fix docker OIDC default, document @SkipCsrf
All checks were successful
ci/woodpecker/push/api Pipeline was successful
- AUTH-003: Add safe empty default for OIDC_REDIRECT_URI in swarm compose
- AUTH-004: Enable PKCE (pkce: true) in genericOAuth config (in prior commit)
- AUTH-005: Document @SkipCsrf() rationale (BetterAuth internal CSRF)

Refs #412

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:04:34 -06:00
Jason Woltje
b2eec3cf83 fix(#412): add OIDC_REDIRECT_URI to startup validation
All checks were successful
ci/woodpecker/push/api Pipeline was successful
Add OIDC_REDIRECT_URI to REQUIRED_OIDC_ENV_VARS with URL format and
path validation. The redirect URI must be a parseable URL with a path
starting with /auth/callback. Localhost usage in production triggers
a warning but does not block startup.

This prevents 500 errors when BetterAuth attempts to construct the
authorization URL without a configured redirect URI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:02:56 -06:00
3376d8162e fix(#410): skip CSRF guard on auth catch-all route
All checks were successful
ci/woodpecker/push/api Pipeline was successful
The global CsrfGuard blocks POST /auth/sign-in/oauth2 with 403 because
unauthenticated users have no session and therefore no CSRF token.
BetterAuth handles its own CSRF protection via toNodeHandler().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 03:41:50 -06:00
e2ffaa71b1 fix: exempt health endpoint from rate limiting
All checks were successful
ci/woodpecker/push/api Pipeline was successful
Docker/load-balancer health probes hit GET /health every ~5s from
127.0.0.1, exhausting the rate limit and causing all subsequent checks
to return 429 — making the service appear unhealthy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 03:21:46 -06:00
444fa1116a fix(#410): align BetterAuth basePath and auth client with NestJS routing
All checks were successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
BetterAuth defaulted basePath to /api/auth but NestJS controller routes
to /auth/* (no global prefix). The auth client also pointed at the web
frontend origin instead of the API server, and LoginButton used a
nonexistent GET /auth/signin/authentik endpoint.

- Set basePath: "/auth" in BetterAuth server config
- Point auth client baseURL to API_BASE_URL with matching basePath
- Add genericOAuthClient plugin to auth client
- Use signIn.oauth2({ providerId: "authentik" }) in LoginButton

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 19:41:08 -06:00
31ce9e920c fix: replace flaky timing-based test with deterministic assertion
All checks were successful
ci/woodpecker/push/api Pipeline was successful
The constant-time comparison test used Date.now() deltas with a 10ms
threshold which is unreliable in CI. Replace with deterministic tests
that verify both same-length and different-length key rejection paths
work correctly. The actual timing-safe behavior is guaranteed by
Node's crypto.timingSafeEqual which the guard uses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 19:11:15 -06:00
ba54de88fd fix(#410): use toNodeHandler for BetterAuth Express compatibility
Some checks failed
ci/woodpecker/push/api Pipeline failed
BetterAuth expects Web API Request objects (Fetch API standard) with
headers.get(), but NestJS/Express passes IncomingMessage objects with
headers[] property access. Use better-auth/node's toNodeHandler to
properly convert between Express req/res and BetterAuth's Web API handler.

Also fixes vitest SWC config to read the correct tsconfig for NestJS
decorator metadata emission, which was causing DI injection failures
in tests.

Fixes #410

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 19:06:49 -06:00
ca21416efc fix: switch Docker images from Alpine to Debian slim for native addon compatibility
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
Alpine (musl libc) is incompatible with matrix-sdk-crypto-nodejs native binary
which requires glibc's ld-linux-x86-64.so.2. Switched all Node.js Dockerfiles
to node:24-slim (Debian/glibc). Also fixed docker-compose.matrix.yml network
naming from undefined mosaic-network to mosaic-internal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:02:23 -06:00
6015ace1de fix: update @mosaicstack/telemetry-client to 0.1.1 for CJS compatibility
All checks were successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
The 0.1.0 package was ESM-only, causing ERR_PACKAGE_PATH_NOT_EXPORTED
when loaded by NestJS (which compiles to CommonJS). Version 0.1.1 ships
dual ESM/CJS builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 15:09:02 -06:00
92de2f282f fix(database): resolve migration failures and schema drift
All checks were successful
ci/woodpecker/push/api Pipeline was successful
Root cause: migration 20260129235248_add_link_storage_fields dropped the
personalities table and FormalityLevel enum, but migration
20260208000000_add_missing_tables later references personalities in a FK
constraint, causing ERROR: relation "personalities" does not exist on any
fresh database deployment.

Fix 1 — 20260208000000_add_missing_tables:
  Recreate FormalityLevel enum and personalities table (with current schema
  structure) at the top of the migration, before the FK constraint.

Fix 2 — New migration 20260215100000_fix_schema_drift:
  - Create missing instances table (Federation module, never migrated)
  - Recreate knowledge_links unique index (dropped, never recreated)
  - Add 7 missing @@unique([id, workspaceId]) composite indexes
  - Add missing agent_tasks.agent_type index

Verified: all 27 migrations apply cleanly on a fresh PostgreSQL 17 database
with pgvector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:42:06 -06:00
cf28efa880 merge: resolve conflicts with develop (M10-Telemetry + M12-MatrixBridge)
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/coordinator Pipeline was successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
Merge origin/develop into feature/m13-speech-services to incorporate
M10-Telemetry and M12-MatrixBridge changes. Resolved 4 conflicts:
- .env.example: Added speech config alongside telemetry + matrix config
- Makefile: Added speech targets alongside matrix targets
- app.module.ts: Import both MosaicTelemetryModule and SpeechModule
- docs/tasks.md: Combined all milestone task tracking sections

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:31:08 -06:00
eca2c46e9d merge: resolve conflicts with develop (telemetry + lockfile)
Some checks failed
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/api Pipeline failed
ci/woodpecker/push/web Pipeline failed
ci/woodpecker/push/orchestrator Pipeline failed
ci/woodpecker/push/coordinator Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 12:12:43 -06:00
af9c5799af fix(#388): address PR review findings — fix WebSocket/REST bugs, improve error handling, fix types and comments
All checks were successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 03:44:33 -06:00
d2c7602430 test(#405): add E2E integration tests for speech services
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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
24065aa199 docs(#406): add speech services documentation
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 03:23:22 -06:00
8d19ac1f4b fix(#377): remediate code review and security findings
Some checks failed
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/api Pipeline failed
- 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 <noreply@anthropic.com>
2026-02-15 03:00:53 -06:00
28c9e6fe65 feat(#397): implement WebSocket streaming transcription gateway
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 02:54:41 -06:00
527262af38 feat(#392): create /api/speech/transcribe REST endpoint
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 02:47:52 -06:00
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 <noreply@anthropic.com>
2026-02-15 02:39:59 -06:00
6c465566f6 feat(#395): implement Piper TTS provider via OpenedAI Speech
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 02:39:20 -06:00
7b4fda6011 feat(#398): add audio/text validation pipes and speech DTOs
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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
93cd31435b feat(#383): Streaming AI responses via Matrix message edits
Some checks failed
ci/woodpecker/push/api Pipeline failed
- 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 <noreply@anthropic.com>
2026-02-15 02:34:36 -06:00
d37c78f503 feat(#394): implement Chatterbox TTS provider with voice cloning
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 02:29:38 -06:00
79b1d81d27 feat(#393): implement Kokoro-FastAPI TTS provider with voice catalog
Some checks failed
ci/woodpecker/push/api Pipeline failed
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 <noreply@anthropic.com>
2026-02-15 02:27:47 -06:00
ad24720616 feat(#382): Herald Service: broadcast to all active chat providers
Some checks failed
ci/woodpecker/push/api Pipeline failed
- 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
b5edb4f37e feat(#391): add base TTS provider and factory classes
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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
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
771ed484e4 feat(#379): Register MatrixService in BridgeModule with conditional loading
Some checks failed
ci/woodpecker/push/api Pipeline failed
- 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
7d22c2490a feat(#380): Workspace-to-Matrix-Room mapping and provisioning
Some checks failed
ci/woodpecker/push/api Pipeline failed
- 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
306c2e5bd8 fix(#371): resolve TypeScript strictness errors in telemetry tracking
Some checks failed
ci/woodpecker/push/coordinator Pipeline failed
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
ci/woodpecker/push/web Pipeline failed
- 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 <noreply@anthropic.com>
2026-02-15 02:10:22 -06:00
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 <noreply@anthropic.com>
2026-02-15 02:10:22 -06:00
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 <noreply@anthropic.com>
2026-02-15 02:10:22 -06:00
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 <noreply@anthropic.com>
2026-02-15 02:10:22 -06:00
c40373fa3b feat(#389): create SpeechModule with provider abstraction layer
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 02:09:45 -06:00
5b5d3811d6 feat(#378): Install matrix-bot-sdk and create MatrixService skeleton
Some checks failed
ci/woodpecker/push/api Pipeline failed
ci/woodpecker/push/orchestrator Pipeline failed
ci/woodpecker/push/web Pipeline failed
- 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 <noreply@anthropic.com>
2026-02-15 02:04:39 -06:00
4cc43bece6 feat(#401): add speech services config and env vars
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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
8ce6843af2 fix(database,api): add 6 missing table migrations and fix CORS health checks
Some checks failed
ci/woodpecker/push/api Pipeline failed
ci/woodpecker/manual/infra Pipeline was successful
ci/woodpecker/manual/orchestrator Pipeline was successful
ci/woodpecker/manual/coordinator Pipeline was successful
ci/woodpecker/manual/api Pipeline was successful
ci/woodpecker/manual/web Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 01:49:13 -06:00
d2003a7b03 fix(api): make federation config validation non-fatal at startup
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 01:08:09 -06:00
8733a643bf fix(api): remove "type": "module" conflicting with CommonJS build output
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 00:53:43 -06:00
91307c87cc fix(database): add missing federation table migrations
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-15 00:29:37 -06:00
14162b9213 fix(api): use node_modules prisma binary in entrypoint
All checks were successful
ci/woodpecker/push/api Pipeline was successful
npx is unavailable in production image since npm is removed.
Use ./node_modules/.bin/prisma directly instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:05:46 -06:00
bcee4fa601 fix(api): auto-run migrations on container start and fix ESM warning
All checks were successful
ci/woodpecker/push/api Pipeline was successful
- 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 <noreply@anthropic.com>
2026-02-14 16:47:57 -06:00
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 <noreply@anthropic.com>
2026-02-14 11:04:04 -06:00
7b892d5197 fix(api): import AuthModule in FederationModule for DI resolution
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-13 22:36:11 -06:00
e23490a5f7 fix(api): remove redundant CsrfGuard from FederationController
All checks were successful
ci/woodpecker/push/api Pipeline was successful
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 <noreply@anthropic.com>
2026-02-13 22:14:03 -06:00
Jason Woltje
0363a14098 fix(#367): migrate Node.js 20 → 24 LTS
All checks were successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
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 tar@7.5.2 (not npm). Orchestrator and API images are
clean; web image needs Next.js upstream fix.

Fixes #367

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:20:01 -06:00