From ff8b7b172ff7d6070e7458fa82fa46bd44cab6de Mon Sep 17 00:00:00 2001 From: Dizzle <112548150+maxmad64bis@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:27:26 +0200 Subject: [PATCH] chore(startup): remove server-init.ts, a module nothing imports (#10780) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged — validated together with a batch of related maxmad64bis PRs in one combined worktree (typecheck:core clean, complexity/cognitive-complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution! --- .env.example | 2 +- .../10780-server-init-dead-code.md | 1 + docs/architecture/CODEBASE_DOCUMENTATION.md | 1 - docs/architecture/REPOSITORY_MAP.md | 1 - docs/guides/FREE_PROVIDER_RANKINGS.md | 2 +- docs/reference/ENVIRONMENT.md | 2 +- docs/security/COMPLIANCE.md | 2 +- open-sse/services/reasoningCache.ts | 10 +- src/lib/arenaEloSync.ts | 2 +- src/lib/catalog/openrouterProviderStats.ts | 2 +- src/lib/modelsDevSync.ts | 2 +- src/lib/pricingSync.ts | 2 +- src/server-init.ts | 181 ------------------ tests/integration/integration-wiring.test.ts | 32 +--- tests/unit/cleanup-column-fix.test.mjs | 17 +- .../unit/lib/jobRegistry/boot-wiring.test.ts | 36 ++-- .../thinking-budget-hydration-5312.test.ts | 2 +- 17 files changed, 43 insertions(+), 254 deletions(-) create mode 100644 changelog.d/maintenance/10780-server-init-dead-code.md delete mode 100644 src/server-init.ts diff --git a/.env.example b/.env.example index d5d61a1f99..940ef094a3 100644 --- a/.env.example +++ b/.env.example @@ -891,7 +891,7 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true # MODEL_SYNC_INTERVAL_HOURS=24 # Provider limits sync interval in minutes (rate limit windows, quotas). -# Used by: src/server-init.ts — polls provider health endpoints. +# Used by: src/lib/usage/providerLimits.ts — polls provider health endpoints. # Default: 70 PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES=70 diff --git a/changelog.d/maintenance/10780-server-init-dead-code.md b/changelog.d/maintenance/10780-server-init-dead-code.md new file mode 100644 index 0000000000..ffe204a233 --- /dev/null +++ b/changelog.d/maintenance/10780-server-init-dead-code.md @@ -0,0 +1 @@ +- chore(startup): remove `src/server-init.ts` (183 lines, never imported — the boot path is `src/instrumentation-node.ts`) and correct four `"called from server-init.ts"` comments left pointing at the dead entry point (#10780) diff --git a/docs/architecture/CODEBASE_DOCUMENTATION.md b/docs/architecture/CODEBASE_DOCUMENTATION.md index dacf0d6f58..23099237db 100644 --- a/docs/architecture/CODEBASE_DOCUMENTATION.md +++ b/docs/architecture/CODEBASE_DOCUMENTATION.md @@ -89,7 +89,6 @@ src/ ├── i18n/ Locale bundles ├── instrumentation.ts Next.js instrumentation hook ├── instrumentation-node.ts -├── server-init.ts Process-level bootstrap (env, DB, jobs, sync) └── proxy.ts Top-level proxy bootstrap helper ``` diff --git a/docs/architecture/REPOSITORY_MAP.md b/docs/architecture/REPOSITORY_MAP.md index f61131d594..4d59418054 100644 --- a/docs/architecture/REPOSITORY_MAP.md +++ b/docs/architecture/REPOSITORY_MAP.md @@ -133,7 +133,6 @@ src/ ├── types/ # Shared TS type files ├── instrumentation.ts # Next.js telemetry hook (browser + edge) ├── instrumentation-node.ts # Node-only instrumentation -├── server-init.ts # Server bootstrap (DB migrations, jobs, cleanup) └── proxy.ts # HTTP-proxy entry shim ``` diff --git a/docs/guides/FREE_PROVIDER_RANKINGS.md b/docs/guides/FREE_PROVIDER_RANKINGS.md index 7eb49f4660..79d2ba6ed8 100644 --- a/docs/guides/FREE_PROVIDER_RANKINGS.md +++ b/docs/guides/FREE_PROVIDER_RANKINGS.md @@ -169,7 +169,7 @@ stale data. The sync runs **on by default**: - It runs once at server startup and then on a periodic timer - (`src/lib/arenaEloSync.ts`, wired from `src/server-init.ts`). + (`src/lib/arenaEloSync.ts`, wired from `src/instrumentation-node.ts`). - It is **non-blocking and never fatal** — if the upstream fetch fails, OmniRoute keeps running and the rankings simply show the last good data (or an empty state). diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index a6823b086b..e1308c8782 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -504,7 +504,7 @@ detection above). | `OMNIROUTE_MCP_COMPRESS_DESCRIPTIONS` | `false` | `open-sse/mcp-server/descriptionCompressor.ts` | Compress MCP tool descriptions before serializing the manifest. Enable values: `1`, `true`, `on`. | | `OMNIROUTE_MCP_DESCRIPTION_COMPRESSION` | `rtk` | `open-sse/mcp-server/descriptionCompressor.ts` | Compression algorithm/profile. Disable values: `0`, `false`, `off`. | | `MODEL_SYNC_INTERVAL_HOURS` | `24` | `src/shared/services/modelSyncScheduler.ts` | Model catalog sync interval in hours. | -| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/server-init.ts` | Provider rate-limit and quota polling interval. | +| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/lib/usage/providerLimits.ts` | Provider rate-limit and quota polling interval. | | `PROVIDER_LIMITS_SYNC_SPACING_MS` | `1500` | `src/lib/usage/providerLimits.ts` | Gap (ms) between consecutive OAuth quota fetches in a bulk sync; OAuth connections are fetched one at a time to avoid bursting an upstream. `0` opts out (concurrent). | | `OMNIROUTE_QUOTA_FETCH_MIN_INTERVAL_MS` | `250` | `open-sse/services/quotaFetchThrottle.ts` | Min interval (ms) between consecutive upstream quota fetches on the per-request preflight/monitor path; spaces concurrent network calls so many accounts on one IP don't burst the upstream. Wired into the Codex (`/wham/usage`), DeepSeek, Bailian (both fetch sites), OpenCode, and Crof quota fetchers (#6009, #6911). The generic `usage.ts::getUsageForProvider` dispatch path (github/glm/minimax/nanogpt/xai/etc.) is not yet covered — tracked separately. Cache hits unaffected. `0` disables; clamped `0..5000`. | | `PROVIDER_LIMITS_POST_USAGE_REFRESH_DELAY_MS` | `5000` | `src/lib/usage/providerLimits.ts` | Delay (ms) before refreshing provider limits after a real usage event, giving the upstream quota API time to register consumption. | diff --git a/docs/security/COMPLIANCE.md b/docs/security/COMPLIANCE.md index 738c6277ba..30ef65a15d 100644 --- a/docs/security/COMPLIANCE.md +++ b/docs/security/COMPLIANCE.md @@ -114,7 +114,7 @@ Two separate retention windows are honoured: | `PROXY_LOGS_TABLE_MAX_ROWS` | `100000` | Row-cap trim for `proxy_logs` | `cleanupExpiredLogs()` runs the retention pass. It is invoked on server startup -from `src/server-init.ts` and `src/instrumentation-node.ts`. Each run logs a +from `src/instrumentation-node.ts`. Each run logs a `compliance.cleanup` audit event with the per-table delete counts. Proxy/call log trimming is batched (`BATCH_SIZE = 5000`) to avoid long write locks. diff --git a/open-sse/services/reasoningCache.ts b/open-sse/services/reasoningCache.ts index bdf870e3fb..23fcf09364 100644 --- a/open-sse/services/reasoningCache.ts +++ b/open-sse/services/reasoningCache.ts @@ -573,16 +573,16 @@ export function cleanupReasoningCache(): number { // ──────────────── Auto-start periodic cleanup ──────────────── // -// server-init.ts was supposed to start the cleanup job, but that module is -// never imported anywhere (it is stranded/dead code). As a result, the -// reasoning_cache SQLite table accumulates expired entries indefinitely. +// server-init.ts was supposed to start the cleanup job, but that module was +// never imported anywhere (it was stranded dead code, since removed). As a +// result, the reasoning_cache SQLite table accumulates expired entries +// indefinitely. // // Fix: start the periodic cleanup directly from this module so it runs // regardless of how the server boots. On first import we run one // immediate sweep, then schedule a 30-minute interval. // -// See: src/lib/jobs/reasoningCacheCleanupJob.ts (the original job module, -// which also remains valid if server-init.ts ever gets wired in). +// See: src/lib/jobs/reasoningCacheCleanupJob.ts (the original job module). const DEFAULT_CLEANUP_INTERVAL_MS = 30 * 60 * 1000; // 30 min diff --git a/src/lib/arenaEloSync.ts b/src/lib/arenaEloSync.ts index 75584296b0..fa4284b2c5 100644 --- a/src/lib/arenaEloSync.ts +++ b/src/lib/arenaEloSync.ts @@ -539,7 +539,7 @@ export function getArenaEloSyncStatus(): SyncStatus { }; } -// ─── Init (called from server-init.ts) ─────────────────── +// ─── Init (called from instrumentation-node.ts) ─────────────────── /** * Initialize Arena ELO sync if enabled via feature flag configuration. diff --git a/src/lib/catalog/openrouterProviderStats.ts b/src/lib/catalog/openrouterProviderStats.ts index 1f3d8472ca..5c1d836842 100644 --- a/src/lib/catalog/openrouterProviderStats.ts +++ b/src/lib/catalog/openrouterProviderStats.ts @@ -332,7 +332,7 @@ function startPeriodicSync(intervalMs?: number): void { } /** - * Boot entry point — call once from server-init.ts. + * Boot entry point — called once from instrumentation-node.ts. * On by default; opt out via OPENROUTER_PROVIDER_STATS_ENABLED=false. */ export function initOpenRouterProviderStatsSync(): boolean { diff --git a/src/lib/modelsDevSync.ts b/src/lib/modelsDevSync.ts index b8d16ffbad..c4c0f2f273 100644 --- a/src/lib/modelsDevSync.ts +++ b/src/lib/modelsDevSync.ts @@ -759,7 +759,7 @@ export function getSyncStatus(): SyncStatus { }; } -// ─── Init (called from server-init.ts) ─────────────────── +// ─── Init (called from instrumentation-node.ts) ─────────────────── /** * Initialize models.dev sync if enabled. diff --git a/src/lib/pricingSync.ts b/src/lib/pricingSync.ts index e331439eb6..a334a9f096 100644 --- a/src/lib/pricingSync.ts +++ b/src/lib/pricingSync.ts @@ -515,7 +515,7 @@ export function getSyncStatus(): SyncStatus { }; } -// ─── Init (called from server-init.ts) ─────────────────── +// ─── Init (called from instrumentation-node.ts) ─────────────────── /** * Initialize pricing sync if enabled. diff --git a/src/server-init.ts b/src/server-init.ts deleted file mode 100644 index a630f93ea2..0000000000 --- a/src/server-init.ts +++ /dev/null @@ -1,181 +0,0 @@ -// Server startup script -import initializeCloudSync from "./shared/services/initializeCloudSync"; -import { enforceWebRuntimeEnv } from "./lib/env/runtimeEnv"; -import { initAuditLog, cleanupExpiredLogs, logAuditEvent } from "./lib/compliance/index"; -import { initConsoleInterceptor } from "./lib/consoleInterceptor"; -import { registerBudgetResetJob } from "./lib/jobs/budgetResetJob"; -import { registerTokenHealthCheck } from "./lib/jobs/tokenHealthCheckJob"; -import { startReasoningCacheCleanupJob } from "./lib/jobs/reasoningCacheCleanupJob"; -import { startCleanupScheduler } from "./lib/db/cleanup"; -import { getSettings } from "./lib/db/settings"; -import { applyRuntimeSettings } from "./lib/config/runtimeSettings"; -import { setSystemPromptConfig } from "@omniroute/open-sse/services/systemPrompt.ts"; -import { hydrateThinkingBudgetConfig } from "@omniroute/open-sse/services/thinkingBudget.ts"; -import { startRuntimeConfigHotReload } from "./lib/config/hotReload"; -import { startSpendBatchWriter } from "./lib/spend/batchWriter"; -import { registerDefaultGuardrails } from "./lib/guardrails"; -import { ensurePersistentManagementPasswordHash } from "./lib/auth/managementPassword"; -import { skillExecutor } from "./lib/skills/executor"; -import { registerBuiltinSkills } from "./lib/skills/builtins"; -import { createLogger } from "./shared/utils/logger"; - -const startupLog = createLogger("server-init"); - -function getErrorMessage(error: unknown) { - return error instanceof Error ? error.message : String(error); -} - -async function startServer() { - // Trigger request-log layout migration during startup, before serving requests. - await import("./lib/usage/migrations"); - - // Console interceptor: capture all console output to log file (must be first) - initConsoleInterceptor(); - - // FASE-01: Validate required secrets and runtime env before anything else (fail-fast) - enforceWebRuntimeEnv(); - - // Compliance: Initialize audit_log table - try { - initAuditLog(); - startupLog.info("Audit log table initialized"); - } catch (err) { - startupLog.warn({ err }, "Could not initialize audit log"); - } - - // Compliance: One-time cleanup of expired logs - try { - const cleanup = await cleanupExpiredLogs(); - if ( - cleanup.deletedUsage || - cleanup.deletedCallLogs || - cleanup.deletedProxyLogs || - cleanup.deletedRequestDetailLogs || - cleanup.deletedAuditLogs || - cleanup.deletedMcpAuditLogs - ) { - startupLog.info({ cleanup }, "Expired log cleanup completed"); - } - } catch (err) { - startupLog.warn({ err }, "Log cleanup failed"); - } - - startupLog.info("Starting server with cloud sync"); - - try { - let settings = await getSettings(); - const passwordState = await ensurePersistentManagementPasswordHash({ - logger: { log: (message: string) => startupLog.info(message) }, - settings, - source: "startup", - }); - settings = passwordState.settings; - const runtimeChanges = await applyRuntimeSettings(settings, { force: true, source: "startup" }); - if (runtimeChanges.length > 0) { - startupLog.info( - { sections: runtimeChanges.map((entry) => entry.section) }, - "Runtime settings hydrated" - ); - } - - // Restore the Global System Prompt into the in-memory config. It lives in the - // `settings.systemPrompt` key but is NOT covered by applyRuntimeSettings, so without - // this the toggle/prompt revert to defaults on every restart (#2470). - if (settings.systemPrompt) { - setSystemPromptConfig(settings.systemPrompt); - startupLog.info("Global System Prompt restored from settings"); - } - - // Restore the proxy-level Thinking-Budget config (#5312). It lives in - // `settings.thinkingBudget` and is NOT covered by applyRuntimeSettings, so - // without this the dashboard mode (auto/custom/adaptive) silently reverts to - // the passthrough default on every restart. - if (hydrateThinkingBudgetConfig(settings)) { - startupLog.info("Thinking-Budget config restored from settings"); - } - - // Initialize cloud sync - startSpendBatchWriter(); - registerDefaultGuardrails(); - registerBuiltinSkills(skillExecutor); - startupLog.info("Spend batch writer started"); - startupLog.info("Guardrail registry initialized"); - startupLog.info("Builtin skill handlers registered"); - - // Load active plugins on startup so they survive restarts - try { - const { pluginManager } = await import("./lib/plugins/manager"); - await pluginManager.loadAll(); - startupLog.info("Plugin manager loaded active plugins"); - } catch (err) { - startupLog.warn({ err }, "Plugin manager loadAll failed (non-fatal)"); - } - - await initializeCloudSync(); - // register() only persists the definition; startAll() is what arms the timers. - // This path does not call ensureCloudSyncInitialized(), so nothing else here - // would start the jobs on our behalf. It registers the same set as that path: - // starting one job and not the other is how a background job goes missing - // without anything failing. - const { getJobRegistry } = await import("./lib/jobRegistry"); - const jobRegistry = getJobRegistry(); - registerBudgetResetJob(jobRegistry); - registerTokenHealthCheck(jobRegistry); - await jobRegistry.startAll(); - startReasoningCacheCleanupJob(); - startCleanupScheduler(); - startRuntimeConfigHotReload(); - startupLog.info("Server started with cloud sync initialized"); - - // Log server start event to audit log - logAuditEvent({ - action: "server.start", - actor: "system", - target: "server-runtime", - resourceType: "maintenance", - status: "success", - details: { timestamp: new Date().toISOString() }, - }); - } catch (error) { - startupLog.error({ err: error }, "Error initializing cloud sync"); - process.exit(1); - } - - // Pricing sync: opt-in external pricing data (non-blocking, never fatal) - if (process.env.PRICING_SYNC_ENABLED === "true") { - try { - const { initPricingSync } = await import("./lib/pricingSync"); - await initPricingSync(); - } catch (err) { - startupLog.warn({ error: getErrorMessage(err) }, "Pricing sync could not initialize"); - } - } - - // Arena ELO sync: model intelligence from leaderboard data (non-blocking, never fatal). - // On by default; opt out with Dashboard Feature Flags or ARENA_ELO_SYNC_ENABLED=false. - try { - const { initArenaEloSync } = await import("./lib/arenaEloSync"); - await initArenaEloSync(); - } catch (err) { - startupLog.warn({ error: getErrorMessage(err) }, "Arena ELO sync could not initialize"); - } - - // Radar daily feed sync: only arms itself when RADAR_ENABLED AND the user - // opt-in are already on (a flag-off boot stays timer-free — Radar inertia - // contract). Non-blocking, never fatal. - try { - const { initRadarSyncScheduler } = await import("./lib/radar/scheduler"); - initRadarSyncScheduler(); - } catch (err) { - startupLog.warn({ error: getErrorMessage(err) }, "Radar sync scheduler could not initialize"); - } -} - -// Start the server initialization -startServer().catch((err) => { - startupLog.error({ err }, "Server initialization failed"); - process.exit(1); -}); - -// Export for use as module if needed -export default startServer; diff --git a/tests/integration/integration-wiring.test.ts b/tests/integration/integration-wiring.test.ts index 757b7ce926..624386fffb 100644 --- a/tests/integration/integration-wiring.test.ts +++ b/tests/integration/integration-wiring.test.ts @@ -46,32 +46,12 @@ function listProjectFiles(relPath: string): string[] { } // ─── Pipeline Wiring ───────────────────────────────── - -describe("Pipeline Wiring — server-init.ts", () => { - const src = readProjectFile("src/server-init.ts"); - - it("should initialize compliance audit log", () => { - assert.ok(src, "src/server-init.ts should exist"); - assert.match(src, /initAuditLog/); - }); - - it("should cleanup expired logs", () => { - assert.match(src, /cleanupExpiredLogs/); - }); - - it("should enforce web runtime env before startup", () => { - assert.match(src, /enforceWebRuntimeEnv/); - }); - - it("should log server.start audit event", () => { - assert.match(src, /server\.start/); - }); - - it("should use the structured startup logger instead of direct console calls", () => { - assert.match(src, /createLogger\("server-init"\)/); - assert.doesNotMatch(src, /console\.(log|warn|error|info|debug)\(/); - }); -}); +// +// src/server-init.ts was removed: it was never imported anywhere and duplicated +// the wiring below, which is the boot path that actually runs (Next.js +// instrumentation hook). See tests/unit/credential-health-boot-wiring.test.ts and +// tests/unit/thinking-budget-boot-wiring-5312.test.ts for the incidents that +// wiring into the dead module caused. describe("Pipeline Wiring — instrumentation-node.ts", () => { const src = readProjectFile("src/instrumentation-node.ts"); diff --git a/tests/unit/cleanup-column-fix.test.mjs b/tests/unit/cleanup-column-fix.test.mjs index 13e48d5bac..060743021a 100644 --- a/tests/unit/cleanup-column-fix.test.mjs +++ b/tests/unit/cleanup-column-fix.test.mjs @@ -67,16 +67,19 @@ test("cleanup: has background scheduler (startCleanupScheduler)", () => { ); }); -test("cleanup: scheduler is wired into server-init.ts", () => { - const serverInitPath = path.resolve(import.meta.dirname, "../../src/server-init.ts"); - const serverInit = fs.readFileSync(serverInitPath, "utf-8"); +test("cleanup: scheduler is wired into instrumentation-node.ts", () => { + const instrumentationPath = path.resolve( + import.meta.dirname, + "../../src/instrumentation-node.ts" + ); + const instrumentation = fs.readFileSync(instrumentationPath, "utf-8"); assert.ok( - serverInit.includes('import { startCleanupScheduler } from "./lib/db/cleanup"'), - "server-init.ts must import startCleanupScheduler" + instrumentation.includes("startCleanupScheduler"), + "instrumentation-node.ts must import startCleanupScheduler" ); assert.ok( - serverInit.includes("startCleanupScheduler()"), - "server-init.ts must call startCleanupScheduler() at startup" + instrumentation.includes("startCleanupScheduler()"), + "instrumentation-node.ts must call startCleanupScheduler() at startup" ); }); diff --git a/tests/unit/lib/jobRegistry/boot-wiring.test.ts b/tests/unit/lib/jobRegistry/boot-wiring.test.ts index 4aa09dada4..387e19c2fc 100644 --- a/tests/unit/lib/jobRegistry/boot-wiring.test.ts +++ b/tests/unit/lib/jobRegistry/boot-wiring.test.ts @@ -34,28 +34,16 @@ test("initCloudSync: cloud sync is initialised before the registry starts any jo ); }); -test("server-init: cloud sync is initialised before the registry starts any job", () => { - const source = readSource("src/server-init.ts"); - const initCall = source.indexOf("await initializeCloudSync("); - const startAllCall = source.indexOf("jobRegistry.startAll("); - - assert.notEqual(initCall, -1, "initializeCloudSync() call not found"); - assert.notEqual(startAllCall, -1, "jobRegistry.startAll() call not found"); - assert.ok(initCall < startAllCall, "startAll() must come after initializeCloudSync()"); -}); - -test("both boot paths register the same jobs", () => { - for (const relativePath of ["src/lib/initCloudSync.ts", "src/server-init.ts"]) { - const source = readSource(relativePath); - assert.match( - source, - /registerBudgetResetJob\s*\(/, - `${relativePath} must register the budget reset job` - ); - assert.match( - source, - /registerTokenHealthCheck\s*\(/, - `${relativePath} must register the token health check job` - ); - } +test("initCloudSync: both budget and token-health jobs are registered", () => { + const source = readSource("src/lib/initCloudSync.ts"); + assert.match( + source, + /registerBudgetResetJob\s*\(/, + "src/lib/initCloudSync.ts must register the budget reset job" + ); + assert.match( + source, + /registerTokenHealthCheck\s*\(/, + "src/lib/initCloudSync.ts must register the token health check job" + ); }); diff --git a/tests/unit/thinking-budget-hydration-5312.test.ts b/tests/unit/thinking-budget-hydration-5312.test.ts index 1e260c0419..2eca499271 100644 --- a/tests/unit/thinking-budget-hydration-5312.test.ts +++ b/tests/unit/thinking-budget-hydration-5312.test.ts @@ -4,7 +4,7 @@ * boot — `_config` resets to DEFAULT (passthrough) on every process start. * * Fix: `hydrateThinkingBudgetConfig(settings)` (open-sse/services/thinkingBudget.ts), - * called once during server bootstrap (src/server-init.ts), restores the persisted + * called once during server bootstrap (src/instrumentation-node.ts), restores the * mode. This test seeds the setting through the real settings DB round-trip, runs * the hydrator, and asserts the in-memory config reflects the operator's choice. */