Skip to content

Commit 570d34e

Browse files
committed
feat: add debug endpoint for configuration inspection in development/test environments
1 parent cf748fd commit 570d34e

5 files changed

Lines changed: 60 additions & 44 deletions

File tree

src/app.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import { createApiRouter } from './routes/index.ts';
55
import type { SessionController } from './controllers/session-controller.ts';
66
import type { LocalAuthController } from './controllers/local-auth-controller.ts';
77
import type { LocalAuthService } from './services/local-auth-service.ts';
8+
import type { AppEnv } from './config/env.ts';
89
import { createAuthMiddleware } from './middleware/auth-middleware.ts';
10+
import { createDebugHandler } from './controllers/debug-controller.ts';
911

1012
interface AppDeps {
1113
sessionController: SessionController;
1214
authController?: LocalAuthController;
1315
authService?: LocalAuthService;
1416
corsOrigin?: string | string[];
17+
env?: AppEnv;
1518
}
1619

1720
export function createApp(deps: AppDeps) {
@@ -35,6 +38,11 @@ export function createApp(deps: AppDeps) {
3538

3639
app.get('/health', (_req, res) => res.json({ status: 'ok' }));
3740

41+
// Debug endpoint (only in dev/test)
42+
if (deps.env) {
43+
app.get('/debug/config', createDebugHandler(deps.env));
44+
}
45+
3846
app.use(
3947
'/api',
4048
createApiRouter({

src/clients/index.ts

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
/**
22
* Dependency injection factory for Auralyze Engine clients.
33
*
4-
* Builds AuralyzeEngineDeps object containing HTTP clients for microservices
5-
* (metadata, analysis, feedback) or stub clients for development/testing.
4+
* Builds AuralyzeEngineDeps object containing HTTP clients for microservices.
5+
* **STUBS DISABLED:** Always requires real service configuration or fails at startup.
66
*
77
* **Architecture:**
88
* Auralyze API orchestrates 3 microservices via HTTP:
99
* 1. **audio-metadata-service**: Extract file info with ffprobe
1010
* 2. **audio-analysis-service**: DSP processing (loudness, dynamics, spectrum, stereo)
11-
* 3. **audio-feedback-service**: LLM-based feedback generation
11+
* 3. **audio-feedback-service**: LLM-based feedback generation (optional - can use OpenAI direct)
1212
*
1313
* **Client Selection Strategy:**
1414
* Controlled by environment variables (AppEnv):
15-
* - `useStubClients=true`: Use stub clients for integration tests (no real services)
16-
* - `FEEDBACK_MODE='stub'`: Stub feedback (real metadata + analysis)
1715
* - `FEEDBACK_MODE='service'`: HTTP feedback client (remote feedback service)
1816
* - `FEEDBACK_MODE='openai'`: OpenAI direct client (API calls OpenAI, no feedback service)
1917
*
2018
* **Why Dependency Injection?**
21-
* - Testing: Swap real clients with stubs without modifying engine code
22-
* - Flexibility: Support multiple feedback implementations (OpenAI direct, service, stub)
23-
* - Development: Run API without spinning up all microservices (stub mode)
24-
* - Configuration: Environment-driven client selection (dev vs prod)
19+
* - Testing: Engine tests can still use stubs by passing createStubDeps() directly
20+
* - Flexibility: Support multiple feedback implementations (OpenAI direct vs service)
21+
* - Fail Fast: Missing configuration causes immediate startup failure (not runtime errors)
22+
* - Configuration: Environment-driven client selection (service vs OpenAI direct)
2523
*
2624
* **API Key Authentication:**
2725
* All HTTP clients use x-api-key header for simple symmetric auth.
@@ -46,25 +44,9 @@ import type { AppEnv } from '../config/env.ts';
4644
/**
4745
* Build AuralyzeEngineDeps from environment configuration.
4846
*
49-
* **Configuration Modes:**
47+
* **STUBS DISABLED - Configuration Modes:**
5048
*
51-
* **1. Full Stub Mode (Development/Testing):**
52-
* ```env
53-
* USE_STUB_CLIENTS=true
54-
* ```
55-
* Returns stub clients for all services (no HTTP calls).
56-
*
57-
* **2. Hybrid Mode (Real services + Stub feedback):**
58-
* ```env
59-
* METADATA_SERVICE_URL=http://localhost:3001
60-
* METADATA_SERVICE_API_KEY=...
61-
* ANALYSIS_SERVICE_URL=http://localhost:3002
62-
* ANALYSIS_SERVICE_API_KEY=...
63-
* FEEDBACK_MODE=stub
64-
* ```
65-
* Real metadata/analysis, stub feedback (for testing feedback logic).
66-
*
67-
* **3. Full Service Mode (Production):**
49+
* **1. Service Mode (Recommended for Production):**
6850
* ```env
6951
* METADATA_SERVICE_URL=http://metadata:3001
7052
* METADATA_SERVICE_API_KEY=...
@@ -76,7 +58,7 @@ import type { AppEnv } from '../config/env.ts';
7658
* ```
7759
* All clients use HTTP microservices.
7860
*
79-
* **4. OpenAI Direct Mode (Bypass feedback service):**
61+
* **2. OpenAI Direct Mode (Bypass feedback service):**
8062
* ```env
8163
* METADATA_SERVICE_URL=http://metadata:3001
8264
* METADATA_SERVICE_API_KEY=...
@@ -106,10 +88,7 @@ import type { AppEnv } from '../config/env.ts';
10688
* ```
10789
*/
10890
export function buildEngineDeps(env: AppEnv): AuralyzeEngineDeps {
109-
if (env.useStubClients) {
110-
return createStubDeps();
111-
}
112-
91+
// STUBS DISABLED: Always use real services or fail
11392
if (!env.METADATA_SERVICE_URL || !env.ANALYSIS_SERVICE_URL) {
11493
throw new Error('Both METADATA_SERVICE_URL and ANALYSIS_SERVICE_URL are required');
11594
}
@@ -128,9 +107,7 @@ export function buildEngineDeps(env: AppEnv): AuralyzeEngineDeps {
128107
});
129108

130109
let feedbackClient: AuralyzeEngineDeps['feedbackClient'];
131-
if (env.FEEDBACK_MODE === 'stub') {
132-
feedbackClient = createStubDeps().feedbackClient;
133-
} else if (env.FEEDBACK_MODE === 'service') {
110+
if (env.FEEDBACK_MODE === 'service') {
134111
if (!env.FEEDBACK_SERVICE_URL || !env.FEEDBACK_SERVICE_API_KEY) {
135112
throw new Error('FEEDBACK_SERVICE_URL and FEEDBACK_SERVICE_API_KEY are required');
136113
}

src/config/env.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ const EnvSchema = z.object({
1212
ANALYSIS_SERVICE_API_KEY: z.string().optional(),
1313
FEEDBACK_SERVICE_URL: z.string().url().optional(),
1414
FEEDBACK_SERVICE_API_KEY: z.string().optional(),
15-
FEEDBACK_MODE: z.enum(['openai', 'stub', 'service']).default('openai'),
16-
USE_STUB_CLIENTS: z.coerce.boolean().optional(),
15+
FEEDBACK_MODE: z.enum(['openai', 'service']).default('openai'),
1716
OPENAI_API_KEY: z.string().optional(),
1817
});
1918

2019
export type AppEnv = z.infer<typeof EnvSchema> & {
21-
useStubClients: boolean;
2220
corsOrigin: string | string[];
2321
};
2422

@@ -38,11 +36,5 @@ export function loadEnv(): AppEnv {
3836
return {
3937
...parsed.data,
4038
corsOrigin,
41-
useStubClients:
42-
parsed.data.USE_STUB_CLIENTS ??
43-
(!parsed.data.METADATA_SERVICE_URL ||
44-
!parsed.data.ANALYSIS_SERVICE_URL ||
45-
!parsed.data.METADATA_SERVICE_API_KEY ||
46-
!parsed.data.ANALYSIS_SERVICE_API_KEY),
4739
};
4840
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { Request, Response } from 'express';
2+
import type { AppEnv } from '../config/env.ts';
3+
4+
/**
5+
* Debug endpoint to show current configuration (sanitized).
6+
* Only available in development/test, not production.
7+
*/
8+
export function createDebugHandler(env: AppEnv) {
9+
return (_req: Request, res: Response) => {
10+
if (env.NODE_ENV === 'production') {
11+
return res.status(404).json({ message: 'Not found' });
12+
}
13+
14+
const config = {
15+
nodeEnv: env.NODE_ENV,
16+
stubsDisabled: true, // Hardcoded: stubs are permanently disabled
17+
feedbackMode: env.FEEDBACK_MODE,
18+
services: {
19+
metadata: {
20+
url: env.METADATA_SERVICE_URL,
21+
hasApiKey: !!env.METADATA_SERVICE_API_KEY,
22+
},
23+
analysis: {
24+
url: env.ANALYSIS_SERVICE_URL,
25+
hasApiKey: !!env.ANALYSIS_SERVICE_API_KEY,
26+
},
27+
feedback: {
28+
url: env.FEEDBACK_SERVICE_URL,
29+
hasApiKey: !!env.FEEDBACK_SERVICE_API_KEY,
30+
},
31+
},
32+
hasOpenAiKey: !!env.OPENAI_API_KEY,
33+
corsOrigin: env.corsOrigin,
34+
};
35+
36+
res.json(config);
37+
};
38+
}

src/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ async function bootstrap() {
3838
authController,
3939
authService,
4040
corsOrigin: env.corsOrigin,
41+
env,
4142
});
4243

4344
app.listen(env.PORT, () => {

0 commit comments

Comments
 (0)