{"version":3,"file":"planner.mjs","names":[],"sources":["../../src/infra/planner.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport { Clock, Effect } from \"effect\";\nimport { PortAllocator, type PortBlockEntry } from \"../app\";\nimport {\n  buildConventionalDatabases,\n  buildConventionalRedis,\n  getSecretGroups,\n  loadPortState,\n  savePortState,\n} from \"../cli/infra\";\nimport {\n  type AuthSlotShape,\n  buildDescription,\n  isAuthMirrorPluginEntry,\n} from \"../service-descriptor\";\nimport type { RuntimeConfig } from \"../types\";\nimport { shouldPersistPortState } from \"./materializer\";\nimport { ownerOfPort } from \"./port-ownership\";\nimport type {\n  ClaimRecord,\n  CliPorts,\n  DatabasePlan,\n  InfraInput,\n  InfraPlan,\n  RedisPlan,\n  ResolvedPorts,\n  RuntimeLaunchSpec,\n  ServiceDescriptorPlan,\n} from \"./types\";\nimport { InfraError } from \"./types\";\n\nconst DEFAULT_HOST_PORT = 3000;\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\n\nexport function workspaceKey(configDir: string): string {\n  const hash = createHash(\"sha256\").update(resolve(configDir)).digest(\"hex\");\n  return hash.slice(0, 12);\n}\n\nfunction normalizeCliPorts(input: InfraInput[\"cli\"]): CliPorts {\n  return {\n    host: input.port,\n    api: input.apiPort,\n    auth: input.authPort,\n    ui: input.uiPort,\n    pluginsStart: input.pluginPortStart,\n    plugins: input.plugins,\n  };\n}\n\ninterface AllocateServicesResult {\n  ports: ResolvedPorts;\n  claims: ClaimRecord[];\n  devPortsState: {\n    host?: number;\n    api?: number;\n    auth?: number;\n    ui?: number;\n    pluginPortStart?: number;\n  };\n}\n\nexport interface ServiceSources {\n  host?: \"local\" | \"remote\";\n  api?: \"local\" | \"remote\";\n  auth?: \"local\" | \"remote\";\n  ui?: \"local\" | \"remote\";\n}\n\nconst PLUGIN_START_OFFSET = 10;\nconst BLOCK_STEP = 100;\n\nfunction allocateServices(\n  cliPorts: CliPorts,\n  plugins: Record<\n    string,\n    { source: string; localPath?: string; ui?: { source: string; localPath?: string } }\n  >,\n  configDir: string,\n  auth?: AuthSlotShape,\n  sources?: ServiceSources,\n): Effect.Effect<AllocateServicesResult, InfraError, PortAllocator> {\n  return Effect.gen(function* () {\n    const wKey = workspaceKey(configDir);\n    const persisted = loadPortState(configDir).devPorts;\n    const allocator = yield* PortAllocator;\n\n    const base = cliPorts.host ?? persisted?.host ?? DEFAULT_HOST_PORT;\n    const pluginStartPreferred =\n      cliPorts.pluginsStart ?? persisted?.pluginPortStart ?? base + PLUGIN_START_OFFSET;\n    const pluginStartPinned =\n      cliPorts.pluginsStart !== undefined || persisted?.pluginPortStart !== undefined;\n\n    const entries: PortBlockEntry[] = [];\n    const addEntry = (\n      key: string,\n      flag: number | undefined,\n      persistedValue: number | undefined,\n      derived: number,\n    ) => {\n      if (flag !== undefined) {\n        entries.push({ key, preferred: flag, pinned: true });\n      } else if (persistedValue !== undefined) {\n        entries.push({ key, preferred: persistedValue, pinned: true });\n      } else {\n        entries.push({ key, preferred: derived, pinned: false });\n      }\n    };\n\n    // Remote-source services spawn nothing locally (ADR 0009 start stack:\n    // remotes load over MF from their published origins) — no port is\n    // allocated for them. The host is the exception: even when loaded as a\n    // remote module, runServer binds its own port.\n    addEntry(\"host\", cliPorts.host, undefined, base);\n    if (sources?.api !== \"remote\") {\n      addEntry(\"api\", cliPorts.api, persisted?.api, base + 1);\n    }\n    if (sources?.auth !== \"remote\") {\n      addEntry(\"auth\", cliPorts.auth, persisted?.auth, base + 2);\n    }\n    if (sources?.ui !== \"remote\") {\n      addEntry(\"ui\", cliPorts.ui, persisted?.ui, base + 3);\n    }\n\n    const pluginKeys = Object.keys(plugins).sort();\n    const isAuthMirrorFor = (\n      pluginId: string,\n      pluginCfg: { source: string; localPath?: string } | undefined,\n    ) => pluginCfg !== undefined && isAuthMirrorPluginEntry(auth, pluginId, pluginCfg);\n\n    let pluginSlot = 0;\n    for (const pluginId of pluginKeys) {\n      const pluginCfg = plugins[pluginId];\n      const pluginIsLocal = pluginCfg?.source === \"local\";\n      const slotBase = pluginStartPinned ? pluginStartPreferred : base + PLUGIN_START_OFFSET;\n      // The auth mirror's backend is owned by the `auth` app slot — no api\n      // port. Its ui surface is still real: without a port the runtime config\n      // advertises an empty ui.url and the browser can never load the remote\n      // (the /login page never renders).\n      if (!isAuthMirrorFor(pluginId, pluginCfg) && pluginIsLocal) {\n        addEntry(\n          `plugin:${pluginId}`,\n          cliPorts.plugins?.[pluginId]?.api,\n          undefined,\n          slotBase + pluginSlot,\n        );\n        pluginSlot += 1;\n      }\n      if (\n        pluginCfg?.source === \"local\" &&\n        pluginCfg?.localPath &&\n        pluginCfg?.ui?.source === \"local\"\n      ) {\n        addEntry(\n          `plugin-ui:${pluginId}`,\n          cliPorts.plugins?.[pluginId]?.ui,\n          undefined,\n          slotBase + pluginSlot,\n        );\n        pluginSlot += 1;\n      }\n    }\n\n    const allocation = yield* allocator.acquireBlock({ base, step: BLOCK_STEP, entries });\n\n    if (allocation.base !== base) {\n      yield* Effect.logError(\n        `[Dev] Preferred port block starting at ${base} is occupied — using ${allocation.base} (this run only; restarts will retry ${base})`,\n      );\n      for (const conflict of allocation.conflicts.slice(0, 6)) {\n        if (conflict.claimed) {\n          yield* Effect.logError(\n            `[Dev]   port ${conflict.port} (${conflict.key}) — live bos session (registry claim)`,\n          );\n        } else {\n          const owner = yield* ownerOfPort(conflict.port);\n          yield* Effect.logError(\n            `[Dev]   port ${conflict.port} (${conflict.key}) — ${\n              owner ? `pid ${owner.pid} (${owner.command})` : \"foreign holder (lsof unavailable)\"\n            }`,\n          );\n        }\n      }\n    }\n\n    const pluginApiPorts: Record<string, number> = {};\n    const pluginUiPorts: Record<string, number> = {};\n    for (const pluginId of pluginKeys) {\n      const api = allocation.ports[`plugin:${pluginId}`];\n      if (api !== undefined) pluginApiPorts[pluginId] = api;\n      const ui = allocation.ports[`plugin-ui:${pluginId}`];\n      if (ui !== undefined) pluginUiPorts[pluginId] = ui;\n    }\n\n    const resolved: ResolvedPorts = {\n      host: allocation.ports.host,\n      api: allocation.ports.api,\n      auth: allocation.ports.auth,\n      ui: allocation.ports.ui,\n      plugins: Object.fromEntries(\n        pluginKeys.map((k) => [k, { api: pluginApiPorts[k], ui: pluginUiPorts[k] }]),\n      ),\n    };\n\n    const devPortsState = {\n      host: cliPorts.host,\n      api: cliPorts.api,\n      auth: cliPorts.auth,\n      ui: cliPorts.ui,\n      pluginPortStart: cliPorts.pluginsStart,\n    };\n\n    const claimPorts: Record<string, number> = {};\n    for (const [key, port] of Object.entries(allocation.ports)) {\n      claimPorts[key] = port;\n    }\n\n    const claim: ClaimRecord = {\n      resourceKey: `workspace:${wKey}`,\n      pid: process.pid,\n      configDir,\n      ports: claimPorts,\n      startedAt: yield* Clock.currentTimeMillis,\n    };\n\n    return { ports: resolved, claims: [claim], devPortsState };\n  }).pipe(\n    Effect.mapError(\n      (portErr) =>\n        new InfraError({\n          phase: \"allocate-services\",\n          message: `Port allocation failed: ${String(portErr)}`,\n          cause: portErr,\n        }),\n    ),\n  );\n}\n\nfunction allocateDatabases(runtimeConfig: RuntimeConfig): Effect.Effect<\n  {\n    dbs: DatabasePlan[];\n    redisPlans: RedisPlan[];\n  },\n  InfraError,\n  PortAllocator\n> {\n  return Effect.gen(function* () {\n    const groups = getSecretGroups(runtimeConfig);\n    const allSecrets = groups.flatMap((group) => group.secrets);\n    const allocator = yield* PortAllocator;\n\n    const conventionalDatabases = buildConventionalDatabases(allSecrets);\n    const conventionalRedis = buildConventionalRedis(allSecrets);\n\n    const dbs: DatabasePlan[] = [];\n    const allocatedByDesired = new Map<number, number>();\n    for (const db of conventionalDatabases) {\n      let port: number;\n      if (allocatedByDesired.has(db.port)) {\n        port = allocatedByDesired.get(db.port)!;\n      } else {\n        port = yield* allocator.pickAvailable(db.port);\n        allocatedByDesired.set(db.port, port);\n      }\n      dbs.push({\n        secret: db.secret,\n        slug: db.slug,\n        port,\n        dbName: db.databaseName,\n        url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${db.databaseName}`,\n      });\n    }\n\n    const redisPlans: RedisPlan[] = [];\n    for (const r of conventionalRedis) {\n      const port = yield* allocator.pickAvailable(r.port);\n      redisPlans.push({\n        secret: r.secret,\n        slug: r.slug,\n        port,\n        url: `redis://localhost:${port}`,\n      });\n    }\n\n    return { dbs, redisPlans };\n  }).pipe(\n    Effect.mapError(\n      (portErr) =>\n        new InfraError({\n          phase: \"allocate-databases\",\n          message: `Database port allocation failed: ${String(portErr)}`,\n          cause: portErr,\n        }),\n    ),\n  );\n}\n\nexport function buildServiceDescriptors(\n  runtimeConfig: RuntimeConfig,\n  resolvedPorts: ResolvedPorts,\n): ServiceDescriptorPlan[] {\n  const descriptors: ServiceDescriptorPlan[] = [];\n\n  if (runtimeConfig.host) {\n    const isLocal = runtimeConfig.host.source === \"local\";\n    descriptors.push({\n      key: \"host\",\n      source: runtimeConfig.host.source,\n      url: isLocal ? `http://localhost:${resolvedPorts.host}` : runtimeConfig.host.url,\n      port: isLocal ? resolvedPorts.host : undefined,\n      localPath: isLocal ? runtimeConfig.host.localPath : undefined,\n    });\n  }\n\n  if (runtimeConfig.api) {\n    const isLocal = runtimeConfig.api.source === \"local\";\n    descriptors.push({\n      key: \"api\",\n      source: runtimeConfig.api.source,\n      url: isLocal ? `http://localhost:${resolvedPorts.api}` : runtimeConfig.api.url,\n      port: isLocal ? resolvedPorts.api : undefined,\n      localPath: isLocal ? runtimeConfig.api.localPath : undefined,\n    });\n  }\n\n  if (runtimeConfig.auth) {\n    const isLocal = runtimeConfig.auth.source === \"local\";\n    descriptors.push({\n      key: \"auth\",\n      source: runtimeConfig.auth.source,\n      url: isLocal ? `http://localhost:${resolvedPorts.auth}` : runtimeConfig.auth.url,\n      port: isLocal ? resolvedPorts.auth : undefined,\n      localPath: isLocal ? runtimeConfig.auth.localPath : undefined,\n    });\n  }\n\n  if (runtimeConfig.ui) {\n    const isLocal = runtimeConfig.ui.source === \"local\";\n    descriptors.push({\n      key: \"ui\",\n      source: runtimeConfig.ui.source,\n      url: isLocal ? `http://localhost:${resolvedPorts.ui}` : runtimeConfig.ui.url,\n      port: isLocal ? resolvedPorts.ui : undefined,\n      localPath: isLocal ? runtimeConfig.ui.localPath : undefined,\n    });\n  }\n\n  if (runtimeConfig.plugins) {\n    for (const [pluginId, pluginCfg] of Object.entries(runtimeConfig.plugins)) {\n      const pluginIsLocal = pluginCfg.source === \"local\";\n      const p = resolvedPorts.plugins[pluginId];\n      const isAuthMirror = isAuthMirrorPluginEntry(runtimeConfig.auth, pluginId, pluginCfg);\n      if (pluginIsLocal && p?.api && !isAuthMirror) {\n        descriptors.push({\n          key: `plugin:${pluginId}`,\n          source: \"local\",\n          url: `http://localhost:${p.api}`,\n          port: p.api,\n          localPath: pluginCfg.localPath,\n        });\n      }\n      if (!pluginIsLocal && pluginCfg.url && !isAuthMirror) {\n        descriptors.push({\n          key: `plugin:${pluginId}`,\n          source: \"remote\",\n          url: pluginCfg.url,\n          port: undefined,\n          localPath: undefined,\n        });\n      }\n      if (pluginIsLocal && p?.ui && pluginCfg.ui?.source === \"local\") {\n        descriptors.push({\n          key: `plugin-ui:${pluginId}`,\n          source: \"local\",\n          url: `http://localhost:${p.ui}`,\n          port: p.ui,\n          localPath: pluginCfg.ui?.localPath,\n        });\n      }\n    }\n  }\n\n  return descriptors;\n}\n\nexport function buildLaunchSpec(\n  runtimeConfig: RuntimeConfig,\n  resolvedPorts: ResolvedPorts,\n): RuntimeLaunchSpec {\n  const hostPort =\n    runtimeConfig.host?.source === \"local\" ? resolvedPorts.host : runtimeConfig.host?.port;\n  const corsOrigin = hostPort ? `http://localhost:${hostPort}` : `http://localhost:3000`;\n\n  return {\n    port: resolvedPorts.host,\n    hostUrl: runtimeConfig.host?.url,\n    corsOrigin,\n    env: {\n      ...(resolvedPorts.host ? { PORT: String(resolvedPorts.host) } : {}),\n      ...(resolvedPorts.api ? { API_PORT: String(resolvedPorts.api) } : {}),\n      ...(resolvedPorts.ui ? { UI_PORT: String(resolvedPorts.ui) } : {}),\n      ...(resolvedPorts.auth ? { AUTH_PORT: String(resolvedPorts.auth) } : {}),\n    },\n    runtimeConfig,\n  };\n}\n\nexport function buildEnvGenerated(\n  resolvedPorts: ResolvedPorts,\n  dbs: DatabasePlan[],\n  redisPlans: RedisPlan[],\n): Record<string, string> {\n  const env: Record<string, string> = {};\n\n  if (resolvedPorts.host) {\n    env.CORS_ORIGIN = `http://localhost:${resolvedPorts.host}`;\n    // The host origin for plugins that derive absolute URLs from it (e.g. the\n    // auth plugin's Better Auth baseURL — email links, passkey RP id).\n    env.BASE_URL = `http://localhost:${resolvedPorts.host}`;\n  }\n\n  for (const db of dbs) {\n    env[db.secret] = db.url;\n  }\n  for (const r of redisPlans) {\n    env[r.secret] = r.url;\n  }\n\n  return env;\n}\n\nexport function planInfra(input: InfraInput): Effect.Effect<InfraPlan, InfraError, PortAllocator> {\n  return Effect.gen(function* () {\n    const cliPorts = normalizeCliPorts(input.cli);\n    const wKey = workspaceKey(input.configDir);\n\n    const plugins = (input.bosConfig.plugins ?? {}) as Record<\n      string,\n      { source: string; localPath?: string; ui?: { source: string; localPath?: string } }\n    >;\n\n    const {\n      ports: svcPorts,\n      claims,\n      devPortsState,\n    } = yield* allocateServices(cliPorts, plugins, input.configDir, input.bosConfig.auth, {\n      host: input.bosConfig.host?.source,\n      api: input.bosConfig.api?.source,\n      auth: input.bosConfig.auth?.source,\n      ui: input.bosConfig.ui?.source,\n    });\n\n    const { dbs, redisPlans } = yield* allocateDatabases(input.bosConfig);\n\n    const resolvedPorts: ResolvedPorts = { ...svcPorts };\n\n    // Write merged state once after all allocations succeed\n    // Skip persistence for regression tests / ephemeral runs\n    // devPorts pins are explicit choices only (ADR 0012 §4): this run's flags,\n    // falling back to previously-persisted explicit choices — never drift.\n    const previousDevPorts = loadPortState(input.configDir).devPorts ?? {};\n    const devPorts = {\n      host: devPortsState.host ?? previousDevPorts.host,\n      api: devPortsState.api ?? previousDevPorts.api,\n      auth: devPortsState.auth ?? previousDevPorts.auth,\n      ui: devPortsState.ui ?? previousDevPorts.ui,\n      pluginPortStart: devPortsState.pluginPortStart ?? previousDevPorts.pluginPortStart,\n    };\n    if (shouldPersistPortState()) {\n      savePortState(input.configDir, { devPorts });\n    }\n\n    const hostIsLocal = input.bosConfig.host?.source === \"local\";\n    const apiIsLocal = input.bosConfig.api?.source === \"local\";\n    const uiIsLocal = input.bosConfig.ui?.source === \"local\";\n    const authIsLocal = input.bosConfig.auth?.source === \"local\";\n    const assignedRuntimeConfig: RuntimeConfig = {\n      ...input.bosConfig,\n      host: resolvedPorts.host\n        ? {\n            ...input.bosConfig.host,\n            port: resolvedPorts.host,\n            url: `http://localhost:${resolvedPorts.host}`,\n            remoteUrl: !hostIsLocal\n              ? (input.bosConfig.host.remoteUrl ?? input.bosConfig.host.url)\n              : undefined,\n          }\n        : input.bosConfig.host,\n      api:\n        apiIsLocal && resolvedPorts.api\n          ? {\n              ...input.bosConfig.api,\n              port: resolvedPorts.api,\n              url: `http://localhost:${resolvedPorts.api}`,\n            }\n          : input.bosConfig.api,\n      ui:\n        uiIsLocal && resolvedPorts.ui\n          ? {\n              ...input.bosConfig.ui,\n              port: resolvedPorts.ui,\n              url: `http://localhost:${resolvedPorts.ui}`,\n              ssrUrl: undefined,\n            }\n          : input.bosConfig.ui,\n      auth:\n        authIsLocal && resolvedPorts.auth && input.bosConfig.auth\n          ? {\n              ...input.bosConfig.auth,\n              port: resolvedPorts.auth,\n              url: `http://localhost:${resolvedPorts.auth}`,\n            }\n          : input.bosConfig.auth,\n      plugins: input.bosConfig.plugins\n        ? Object.fromEntries(\n            Object.entries(input.bosConfig.plugins).map(([id, p]) => {\n              const isAuthMirror = isAuthMirrorPluginEntry(input.bosConfig.auth, id, p);\n              const pluginPort = resolvedPorts.plugins[id];\n              const patchedUi = (() => {\n                if (p.ui?.source !== \"local\" || !p.ui?.localPath || !pluginPort?.ui) return p.ui;\n                return {\n                  ...p.ui,\n                  port: pluginPort.ui,\n                  url: `http://localhost:${pluginPort.ui}`,\n                  ssrUrl: undefined,\n                };\n              })();\n              if (isAuthMirror) {\n                return [id, { ...p, ui: patchedUi }];\n              }\n              if (p.source === \"local\" && pluginPort?.api) {\n                return [\n                  id,\n                  {\n                    ...p,\n                    port: pluginPort.api,\n                    url: `http://localhost:${pluginPort.api}`,\n                    ui: patchedUi,\n                  },\n                ];\n              }\n              return [id, p];\n            }),\n          )\n        : undefined,\n    };\n\n    const serviceDescriptors = buildServiceDescriptors(assignedRuntimeConfig, resolvedPorts);\n\n    const launch = buildLaunchSpec(input.bosConfig, resolvedPorts);\n    const envGenerated = buildEnvGenerated(resolvedPorts, dbs, redisPlans);\n\n    const packages = serviceDescriptors.map((d) => d.key);\n    const descriptionMap = new Map(serviceDescriptors.map((d) => [d.key, d]));\n    const description = buildDescription(descriptionMap);\n\n    const orchestrator = {\n      packages,\n      env: {},\n      description,\n      port: resolvedPorts.host,\n      interactive: input.cli.interactive,\n    };\n\n    return {\n      workspaceKey: wKey,\n      cliPorts,\n      resolvedPorts,\n      runtimeConfig: assignedRuntimeConfig,\n      launch,\n      description,\n      serviceDescriptors: new Map(serviceDescriptors.map((d) => [d.key, d])),\n      envGenerated,\n      claims,\n      orchestrator,\n    };\n  });\n}\n"],"mappings":"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"}