debug(auth): log session cookie source
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { ConfigModule, ConfigService } from "@nestjs/config";
|
||||
import { BullModule } from "@nestjs/bullmq";
|
||||
import { ThrottlerModule } from "@nestjs/throttler";
|
||||
import { HealthModule } from "./api/health/health.module";
|
||||
@@ -22,11 +22,15 @@ import { orchestratorConfig } from "./config/orchestrator.config";
|
||||
isGlobal: true,
|
||||
load: [orchestratorConfig],
|
||||
}),
|
||||
BullModule.forRoot({
|
||||
connection: {
|
||||
host: process.env.VALKEY_HOST ?? "localhost",
|
||||
port: parseInt(process.env.VALKEY_PORT ?? "6379"),
|
||||
},
|
||||
BullModule.forRootAsync({
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
connection: {
|
||||
host: configService.get<string>("orchestrator.valkey.host", "localhost"),
|
||||
port: configService.get<number>("orchestrator.valkey.port", 6379),
|
||||
password: configService.get<string>("orchestrator.valkey.password"),
|
||||
},
|
||||
}),
|
||||
}),
|
||||
ThrottlerModule.forRoot([
|
||||
{
|
||||
|
||||
@@ -120,6 +120,42 @@ describe("orchestratorConfig", () => {
|
||||
expect(config.valkey.port).toBe(6379);
|
||||
expect(config.valkey.url).toBe("redis://localhost:6379");
|
||||
});
|
||||
|
||||
it("should derive valkey host and port from VALKEY_URL when VALKEY_HOST/VALKEY_PORT are not set", () => {
|
||||
delete process.env.VALKEY_HOST;
|
||||
delete process.env.VALKEY_PORT;
|
||||
process.env.VALKEY_URL = "redis://valkey:6380";
|
||||
|
||||
const config = orchestratorConfig();
|
||||
|
||||
expect(config.valkey.host).toBe("valkey");
|
||||
expect(config.valkey.port).toBe(6380);
|
||||
expect(config.valkey.url).toBe("redis://valkey:6380");
|
||||
});
|
||||
|
||||
it("should derive valkey password from VALKEY_URL when VALKEY_PASSWORD is not set", () => {
|
||||
delete process.env.VALKEY_PASSWORD;
|
||||
delete process.env.VALKEY_HOST;
|
||||
delete process.env.VALKEY_PORT;
|
||||
process.env.VALKEY_URL = "redis://:url-secret@valkey:6379";
|
||||
|
||||
const config = orchestratorConfig();
|
||||
|
||||
expect(config.valkey.password).toBe("url-secret");
|
||||
});
|
||||
|
||||
it("should prefer explicit valkey env vars over VALKEY_URL values", () => {
|
||||
process.env.VALKEY_HOST = "explicit-host";
|
||||
process.env.VALKEY_PORT = "6390";
|
||||
process.env.VALKEY_PASSWORD = "explicit-password";
|
||||
process.env.VALKEY_URL = "redis://:url-secret@valkey:6380";
|
||||
|
||||
const config = orchestratorConfig();
|
||||
|
||||
expect(config.valkey.host).toBe("explicit-host");
|
||||
expect(config.valkey.port).toBe(6390);
|
||||
expect(config.valkey.password).toBe("explicit-password");
|
||||
});
|
||||
});
|
||||
|
||||
describe("valkey timeout config (SEC-ORCH-28)", () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { registerAs } from "@nestjs/config";
|
||||
|
||||
const normalizeAiProvider = (): "ollama" | "claude" | "openai" => {
|
||||
const provider = process.env.AI_PROVIDER?.trim().toLowerCase();
|
||||
|
||||
@@ -13,63 +14,83 @@ const normalizeAiProvider = (): "ollama" | "claude" | "openai" => {
|
||||
return provider;
|
||||
};
|
||||
|
||||
export const orchestratorConfig = registerAs("orchestrator", () => ({
|
||||
host: process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1",
|
||||
port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10),
|
||||
valkey: {
|
||||
host: process.env.VALKEY_HOST ?? "localhost",
|
||||
port: parseInt(process.env.VALKEY_PORT ?? "6379", 10),
|
||||
password: process.env.VALKEY_PASSWORD,
|
||||
url: process.env.VALKEY_URL ?? "redis://localhost:6379",
|
||||
connectTimeout: parseInt(process.env.VALKEY_CONNECT_TIMEOUT_MS ?? "5000", 10),
|
||||
commandTimeout: parseInt(process.env.VALKEY_COMMAND_TIMEOUT_MS ?? "3000", 10),
|
||||
},
|
||||
claude: {
|
||||
apiKey: process.env.CLAUDE_API_KEY,
|
||||
},
|
||||
aiProvider: normalizeAiProvider(),
|
||||
docker: {
|
||||
socketPath: process.env.DOCKER_SOCKET ?? "/var/run/docker.sock",
|
||||
},
|
||||
git: {
|
||||
userName: process.env.GIT_USER_NAME ?? "Mosaic Orchestrator",
|
||||
userEmail: process.env.GIT_USER_EMAIL ?? "orchestrator@mosaicstack.dev",
|
||||
},
|
||||
killswitch: {
|
||||
enabled: process.env.KILLSWITCH_ENABLED === "true",
|
||||
},
|
||||
sandbox: {
|
||||
enabled: process.env.SANDBOX_ENABLED !== "false",
|
||||
defaultImage: process.env.SANDBOX_DEFAULT_IMAGE ?? "node:20-alpine",
|
||||
defaultMemoryMB: parseInt(process.env.SANDBOX_DEFAULT_MEMORY_MB ?? "256", 10),
|
||||
defaultCpuLimit: parseFloat(process.env.SANDBOX_DEFAULT_CPU_LIMIT ?? "1.0"),
|
||||
networkMode: process.env.SANDBOX_NETWORK_MODE ?? "none",
|
||||
},
|
||||
coordinator: {
|
||||
url: process.env.COORDINATOR_URL ?? "http://localhost:8000",
|
||||
timeout: parseInt(process.env.COORDINATOR_TIMEOUT_MS ?? "30000", 10),
|
||||
retries: parseInt(process.env.COORDINATOR_RETRIES ?? "3", 10),
|
||||
apiKey: process.env.COORDINATOR_API_KEY,
|
||||
},
|
||||
yolo: {
|
||||
enabled: process.env.YOLO_MODE === "true",
|
||||
},
|
||||
spawner: {
|
||||
maxConcurrentAgents: parseInt(process.env.MAX_CONCURRENT_AGENTS ?? "2", 10),
|
||||
sessionCleanupDelayMs: parseInt(process.env.SESSION_CLEANUP_DELAY_MS ?? "30000", 10),
|
||||
},
|
||||
queue: {
|
||||
name: process.env.ORCHESTRATOR_QUEUE_NAME ?? "orchestrator-tasks",
|
||||
maxRetries: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_RETRIES ?? "3", 10),
|
||||
baseDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_BASE_DELAY_MS ?? "1000", 10),
|
||||
maxDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_DELAY_MS ?? "60000", 10),
|
||||
concurrency: parseInt(process.env.ORCHESTRATOR_QUEUE_CONCURRENCY ?? "1", 10),
|
||||
completedRetentionCount: parseInt(process.env.QUEUE_COMPLETED_RETENTION_COUNT ?? "100", 10),
|
||||
completedRetentionAgeSeconds: parseInt(
|
||||
process.env.QUEUE_COMPLETED_RETENTION_AGE_S ?? "3600",
|
||||
10
|
||||
),
|
||||
failedRetentionCount: parseInt(process.env.QUEUE_FAILED_RETENTION_COUNT ?? "1000", 10),
|
||||
failedRetentionAgeSeconds: parseInt(process.env.QUEUE_FAILED_RETENTION_AGE_S ?? "86400", 10),
|
||||
},
|
||||
}));
|
||||
const parseValkeyUrl = (url: string): { host?: string; port?: number; password?: string } => {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
const port = parsed.port ? parseInt(parsed.port, 10) : undefined;
|
||||
|
||||
return {
|
||||
host: parsed.hostname || undefined,
|
||||
port: Number.isNaN(port) ? undefined : port,
|
||||
password: parsed.password ? decodeURIComponent(parsed.password) : undefined,
|
||||
};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
export const orchestratorConfig = registerAs("orchestrator", () => {
|
||||
const valkeyUrl = process.env.VALKEY_URL ?? "redis://localhost:6379";
|
||||
const parsedValkeyUrl = parseValkeyUrl(valkeyUrl);
|
||||
|
||||
return {
|
||||
host: process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1",
|
||||
port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10),
|
||||
valkey: {
|
||||
host: process.env.VALKEY_HOST ?? parsedValkeyUrl.host ?? "localhost",
|
||||
port: parseInt(process.env.VALKEY_PORT ?? String(parsedValkeyUrl.port ?? 6379), 10),
|
||||
password: process.env.VALKEY_PASSWORD ?? parsedValkeyUrl.password,
|
||||
url: valkeyUrl,
|
||||
connectTimeout: parseInt(process.env.VALKEY_CONNECT_TIMEOUT_MS ?? "5000", 10),
|
||||
commandTimeout: parseInt(process.env.VALKEY_COMMAND_TIMEOUT_MS ?? "3000", 10),
|
||||
},
|
||||
claude: {
|
||||
apiKey: process.env.CLAUDE_API_KEY,
|
||||
},
|
||||
aiProvider: normalizeAiProvider(),
|
||||
docker: {
|
||||
socketPath: process.env.DOCKER_SOCKET ?? "/var/run/docker.sock",
|
||||
},
|
||||
git: {
|
||||
userName: process.env.GIT_USER_NAME ?? "Mosaic Orchestrator",
|
||||
userEmail: process.env.GIT_USER_EMAIL ?? "orchestrator@mosaicstack.dev",
|
||||
},
|
||||
killswitch: {
|
||||
enabled: process.env.KILLSWITCH_ENABLED === "true",
|
||||
},
|
||||
sandbox: {
|
||||
enabled: process.env.SANDBOX_ENABLED !== "false",
|
||||
defaultImage: process.env.SANDBOX_DEFAULT_IMAGE ?? "node:20-alpine",
|
||||
defaultMemoryMB: parseInt(process.env.SANDBOX_DEFAULT_MEMORY_MB ?? "256", 10),
|
||||
defaultCpuLimit: parseFloat(process.env.SANDBOX_DEFAULT_CPU_LIMIT ?? "1.0"),
|
||||
networkMode: process.env.SANDBOX_NETWORK_MODE ?? "none",
|
||||
},
|
||||
coordinator: {
|
||||
url: process.env.COORDINATOR_URL ?? "http://localhost:8000",
|
||||
timeout: parseInt(process.env.COORDINATOR_TIMEOUT_MS ?? "30000", 10),
|
||||
retries: parseInt(process.env.COORDINATOR_RETRIES ?? "3", 10),
|
||||
apiKey: process.env.COORDINATOR_API_KEY,
|
||||
},
|
||||
yolo: {
|
||||
enabled: process.env.YOLO_MODE === "true",
|
||||
},
|
||||
spawner: {
|
||||
maxConcurrentAgents: parseInt(process.env.MAX_CONCURRENT_AGENTS ?? "2", 10),
|
||||
sessionCleanupDelayMs: parseInt(process.env.SESSION_CLEANUP_DELAY_MS ?? "30000", 10),
|
||||
},
|
||||
queue: {
|
||||
name: process.env.ORCHESTRATOR_QUEUE_NAME ?? "orchestrator-tasks",
|
||||
maxRetries: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_RETRIES ?? "3", 10),
|
||||
baseDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_BASE_DELAY_MS ?? "1000", 10),
|
||||
maxDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_DELAY_MS ?? "60000", 10),
|
||||
concurrency: parseInt(process.env.ORCHESTRATOR_QUEUE_CONCURRENCY ?? "1", 10),
|
||||
completedRetentionCount: parseInt(process.env.QUEUE_COMPLETED_RETENTION_COUNT ?? "100", 10),
|
||||
completedRetentionAgeSeconds: parseInt(
|
||||
process.env.QUEUE_COMPLETED_RETENTION_AGE_S ?? "3600",
|
||||
10
|
||||
),
|
||||
failedRetentionCount: parseInt(process.env.QUEUE_FAILED_RETENTION_COUNT ?? "1000", 10),
|
||||
failedRetentionAgeSeconds: parseInt(process.env.QUEUE_FAILED_RETENTION_AGE_S ?? "86400", 10),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user