{"version":3,"file":"legs.mjs","names":[],"sources":["../../../src/services/deploy/legs.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport type { DeployLegOutcome } from \"../../contract\";\nimport { colors, icons } from \"../../utils/theme\";\nimport {\n  buildAndPushImage,\n  deployImageToRailway,\n  hasDocker,\n  imageRefWithDigest,\n  type ResolvedImageRef,\n  repointServiceSource,\n  resolveImageRef,\n  resolveRegistryDigest,\n} from \"./image\";\nimport { deriveImageRefFromPlatformManifest } from \"./platform-manifest\";\nimport { rollbackToPreviousSnapshot } from \"./rollback-flow\";\nimport { runSmoke } from \"./smoke\";\n\nexport type { DeployLegOutcome };\nexport type DeployLegStatus = DeployLegOutcome[\"status\"];\n\nexport interface DeployLegs {\n  image?: DeployLegOutcome;\n  smoke?: DeployLegOutcome;\n  railway?: DeployLegOutcome;\n}\n\n/**\n * Runtime tier (ADR 0020/0021): a \"root\" train owns its runtime image —\n * `BOS_IMAGE` names one (with a pre-pushed digest) or a Dockerfile exists at\n * the config root, so the train can produce a digest and pin Railway to\n * exactly the bytes it validated. A \"child\" runtime inherits the platform's\n * universal image (identity-driven boot); it has no image bytes to build,\n * pin, or boot — its image ref derives from the platform release manifest\n * (ADR 0034).\n */\nexport type RuntimeTier = \"root\" | \"child\";\n\nexport function resolveRuntimeTier(input: {\n  imageEnv?: string;\n  hasDockerfile: boolean;\n}): RuntimeTier {\n  return input.imageEnv || input.hasDockerfile ? \"root\" : \"child\";\n}\n\n/** The child image pin (ADR 0034): `ref:v<version>` from the resolved\n * platform release manifest, with the tag's digest resolved from the\n * registry. The Railway service source repoints to the ref and the smoke\n * gate boots the digest. */\nexport interface ChildImagePin {\n  image: string;\n  tag: string;\n  digest: string;\n}\n\n/**\n * The child image pin: the platform release manifest resolves through the\n * extends chain (authored `platform` pin, else nearest-wins) to `ref:tag`,\n * and the registry resolves the tag's digest. Undefined when no manifest\n * resolves — the additive fallback (ADR 0034) is today's float redeploy.\n */\nexport async function resolveChildImagePin(input: {\n  configDir: string;\n  localConfig: Record<string, unknown>;\n  fetchManifest?: Parameters<typeof deriveImageRefFromPlatformManifest>[0][\"fetchManifest\"];\n  fetchDigest?: typeof resolveRegistryDigest;\n}): Promise<ChildImagePin | undefined> {\n  const derived = await deriveImageRefFromPlatformManifest({\n    configDir: input.configDir,\n    localConfig: input.localConfig,\n    fetchManifest: input.fetchManifest,\n  });\n  if (!derived) return undefined;\n  const digest = await (input.fetchDigest ?? resolveRegistryDigest)({\n    ref: `${derived.image}:${derived.tag}`,\n  });\n  return { image: derived.image, tag: derived.tag, digest };\n}\n\n/**\n * The post-publish decision table (ADR 0020/0021/0034) — pure data, one\n * place. Precedence for the image leg: an explicit digest handover\n * (`BOS_IMAGE_DIGEST`, any tier) wins; a child pins the platform manifest's\n * ref or skips with the inheritance reason; a root runs the\n * build/prebuilt/skip chain. Smoke boots only pinned/known-digest refs.\n * Every step is executable without further decisions; the railway step is\n * decided separately (`resolveRailwayStep`) because it legitimately depends\n * on the image leg's execution outcome (the captured digest).\n */\n\nexport type ImageStep =\n  | { action: \"pinned\"; image: string; tag: string; digest: string }\n  | { action: \"prebuilt\"; image: string; digest: string }\n  | { action: \"build\"; image: string }\n  | { action: \"skip\"; reason: string };\n\nexport type SmokeStep =\n  /** `ref` is precomputed when the digest is known at plan time; a build\n   * boots `image` and the interpreter appends the captured digest. */\n  { action: \"boot\"; image: string; ref?: string } | { action: \"skip\"; reason: string };\n\nexport interface DeployPlan {\n  tier: RuntimeTier;\n  image: ImageStep;\n  /** Absent when `--smoke` was not requested. */\n  smoke?: SmokeStep;\n}\n\nexport function resolveDeployPlan(input: {\n  tier: RuntimeTier;\n  childPin?: ChildImagePin;\n  imageRef?: ResolvedImageRef;\n  digestHandover?: string;\n  hasDocker: boolean;\n  hasDockerfile: boolean;\n  smokeRequested: boolean;\n}): DeployPlan {\n  let image: ImageStep;\n  if (input.digestHandover && input.imageRef) {\n    image = {\n      action: \"prebuilt\",\n      image: input.imageRef.image,\n      digest: input.digestHandover,\n    };\n  } else if (input.tier === \"child\") {\n    image = input.childPin\n      ? {\n          action: \"pinned\",\n          image: input.childPin.image,\n          tag: input.childPin.tag,\n          digest: input.childPin.digest,\n        }\n      : {\n          action: \"skip\",\n          reason:\n            \"child runtime inherits the root's universal image (ADR 0020) — no image leg in this train\",\n        };\n  } else if (!input.imageRef) {\n    image = {\n      action: \"skip\",\n      reason:\n        \"set BOS_IMAGE (or repository in bos.config.json) to build and push the runtime image\",\n    };\n  } else if (!input.hasDocker) {\n    image = { action: \"skip\", reason: \"docker is not available\" };\n  } else if (!input.hasDockerfile) {\n    image = { action: \"skip\", reason: \"no Dockerfile at the config root\" };\n  } else {\n    image = { action: \"build\", image: input.imageRef.image };\n  }\n\n  let smoke: SmokeStep | undefined;\n  if (input.smokeRequested) {\n    if (image.action === \"pinned\" || image.action === \"prebuilt\") {\n      smoke = {\n        action: \"boot\",\n        image: image.image,\n        ref: imageRefWithDigest(image.image, image.digest),\n      };\n    } else if (image.action === \"build\") {\n      smoke = { action: \"boot\", image: image.image };\n    } else {\n      smoke = {\n        action: \"skip\",\n        reason:\n          input.tier === \"child\"\n            ? \"child runtime inherits the root's universal image — no image digest to boot in this train\"\n            : \"no runtime image digest — pass BOS_IMAGE_DIGEST for a pre-pushed image\",\n      };\n    }\n  }\n\n  return { tier: input.tier, image, ...(smoke ? { smoke } : {}) };\n}\n\nexport type RailwayStep =\n  | { action: \"repoint-and-redeploy\"; service: string; image: string }\n  | { action: \"redeploy\"; service: string }\n  | { action: \"fail\"; detail: string }\n  | { action: \"skip\"; detail: string };\n\n/**\n * The railway step, decided after the image leg ran: a root runtime must\n * have pinned bytes (`pinnedDigest` — handover, pin, or build capture);\n * without them the \"pulled bytes are what this train validated\" guarantee\n * (ADR 0021) is unmeetable, and that is a failure, not a skip. A child\n * runtime never needs a digest: with a pin the service source repoints to\n * the pinned ref before the redeploy pulls it; without one, `redeploy\n * --from-source` is just a reload trigger for the freshly published config.\n * The token is project-scoped and cannot touch another project's service.\n */\nexport function resolveRailwayStep(input: {\n  tier: RuntimeTier;\n  token?: string;\n  service?: string;\n  pinnedDigest?: string;\n  childPin?: ChildImagePin;\n}): RailwayStep {\n  if (!input.token) {\n    return { action: \"skip\", detail: \"RAILWAY_TOKEN not set\" };\n  }\n  if (!input.service) {\n    return input.tier === \"root\"\n      ? {\n          action: \"fail\",\n          detail: \"ci.railway.service is not configured in bos.config.json\",\n        }\n      : {\n          action: \"skip\",\n          detail: \"set ci.railway.service in bos.config.json to trigger a Railway redeploy\",\n        };\n  }\n  if (input.tier === \"root\" && !input.pinnedDigest) {\n    return {\n      action: \"fail\",\n      detail:\n        \"Railway deploy requires a runtime image (pass BOS_IMAGE_DIGEST for a pre-pushed image)\",\n    };\n  }\n  if (input.childPin) {\n    return {\n      action: \"repoint-and-redeploy\",\n      service: input.service,\n      image: `${input.childPin.image}:${input.childPin.tag}`,\n    };\n  }\n  return { action: \"redeploy\", service: input.service };\n}\n\n/**\n * The post-publish legs (ticket #422): image → smoke boot gate → Railway,\n * executing the pure decision table (`resolveDeployPlan` +\n * `resolveRailwayStep`). The deploy handler hands over the published-config\n * context; leg outcomes derive from leg results — a red boot gate rolls the\n * config back here, and the handler maps the returned outcome onto the wire\n * result mechanically.\n */\n\nexport interface PostPublishLegsInput {\n  sessionRoot: string;\n  env: \"production\" | \"staging\";\n  smoke: boolean;\n  imageDigestInput?: string;\n  railwayService?: string;\n  registry?: string;\n  network?: \"mainnet\" | \"testnet\";\n  privateKey?: string;\n  wallet?: boolean;\n  verbose?: boolean;\n  /** post-publish session identity (the possibly-refreshed runtime) */\n  account?: string;\n  domain?: string;\n  runtimeConfig: Parameters<typeof rollbackToPreviousSnapshot>[0][\"runtimeConfig\"];\n  /** The authored leaf config — the platform pin + extends chain a child's\n   * image pin resolves from (ADR 0034). */\n  localConfig?: Record<string, unknown>;\n  repository?: string;\n}\n\nexport interface PostPublishLegsOutcome {\n  image?: string;\n  imageDigest?: string;\n  service?: string;\n  legs: DeployLegs;\n  /** terminal failure after a published config — the config stays published */\n  failure?: string;\n}\n\n/** The seams the legs need — injectable for tests, real modules by default. */\nexport interface PostPublishLegsDeps {\n  buildAndPushImage: typeof buildAndPushImage;\n  hasDocker: typeof hasDocker;\n  runSmoke: typeof runSmoke;\n  deployImageToRailway: typeof deployImageToRailway;\n  repointServiceSource: typeof repointServiceSource;\n  resolveChildImagePin: typeof resolveChildImagePin;\n  rollbackToPreviousSnapshot: typeof rollbackToPreviousSnapshot;\n}\n\nexport const realPostPublishLegsDeps: PostPublishLegsDeps = {\n  buildAndPushImage,\n  hasDocker,\n  runSmoke,\n  deployImageToRailway,\n  repointServiceSource,\n  resolveChildImagePin,\n  rollbackToPreviousSnapshot,\n};\n\nexport async function runPostPublishLegs(\n  input: PostPublishLegsInput,\n  deps: PostPublishLegsDeps = realPostPublishLegsDeps,\n): Promise<PostPublishLegsOutcome> {\n  const legs: DeployLegs = {};\n  let image: string | undefined;\n  let imageDigest: string | undefined;\n  let service: string | undefined;\n\n  const hasDockerfile = existsSync(join(input.sessionRoot, \"Dockerfile\"));\n  const tier = resolveRuntimeTier({\n    imageEnv: process.env.BOS_IMAGE,\n    hasDockerfile,\n  });\n\n  let childPin: ChildImagePin | undefined;\n  if (tier === \"child\") {\n    try {\n      childPin = await deps.resolveChildImagePin({\n        configDir: input.sessionRoot,\n        localConfig: input.localConfig ?? {},\n      });\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      const detail = `Image pin failed: ${message}`;\n      legs.image = { status: \"failed\", detail };\n      console.log(colors.yellow(`  ${detail}`));\n      return { legs, failure: `Config published but ${detail}` };\n    }\n  }\n\n  const plan = resolveDeployPlan({\n    tier,\n    childPin,\n    imageRef: resolveImageRef({\n      repository: input.repository,\n      env: process.env,\n    }),\n    digestHandover: input.imageDigestInput,\n    hasDocker: tier === \"root\" ? await deps.hasDocker() : false,\n    hasDockerfile,\n    smokeRequested: input.smoke,\n  });\n\n  switch (plan.image.action) {\n    case \"skip\": {\n      legs.image = { status: \"skipped\", detail: plan.image.reason };\n      console.log();\n      console.log(colors.yellow(`  Image skipped: ${plan.image.reason}`));\n      break;\n    }\n    case \"pinned\": {\n      image = plan.image.image;\n      imageDigest = plan.image.digest;\n      legs.image = {\n        status: \"ok\",\n        detail: `pinned ${plan.image.image}:${plan.image.tag} @ ${plan.image.digest.slice(0, 19)}…`,\n      };\n      console.log();\n      console.log(\n        colors.green(\n          `  ${icons.ok} Pinned ${plan.image.image}:${plan.image.tag} @ ${plan.image.digest.slice(0, 19)}… (platform manifest)`,\n        ),\n      );\n      break;\n    }\n    case \"prebuilt\": {\n      image = plan.image.image;\n      imageDigest = plan.image.digest;\n      legs.image = {\n        status: \"ok\",\n        detail: `pre-pushed ${plan.image.image}@${plan.image.digest.slice(0, 19)}…`,\n      };\n      console.log();\n      console.log(\n        colors.green(\n          `  ${icons.ok} Using pre-pushed image ${plan.image.image}@${plan.image.digest.slice(0, 19)}…`,\n        ),\n      );\n      break;\n    }\n    case \"build\": {\n      console.log();\n      try {\n        const imageResult = await deps.buildAndPushImage({\n          image: plan.image.image,\n          configDir: input.sessionRoot,\n          verbose: input.verbose,\n        });\n        image = imageResult.image;\n        imageDigest = imageResult.digest;\n        legs.image = {\n          status: \"ok\",\n          detail: `built and pushed ${imageResult.image}:${imageResult.tag}`,\n        };\n        console.log(\n          colors.green(\n            `  ${icons.ok} Image pushed ${imageResult.image}:${imageResult.tag}${imageResult.digest ? ` (${imageResult.digest.slice(0, 19)}…)` : \"\"}`,\n          ),\n        );\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        const imageError =\n          message.includes(\"not found\") || message.includes(\"ENOENT\")\n            ? \"Docker not found — install Docker to build the runtime image\"\n            : `Image build/push failed: ${message}`;\n        legs.image = { status: \"failed\", detail: imageError };\n        console.log(colors.yellow(`  ${imageError}`));\n        return {\n          legs,\n          failure: `Config published but ${imageError}`,\n        };\n      }\n      break;\n    }\n  }\n\n  // Post-publish boot gate (publish → smoke → Railway, ADR 0021): the\n  // just-published config is only promoted to Railway if the runtime image —\n  // the one this train pinned — boots against it. A red smoke rolls the\n  // config back to the previous snapshot, so the new-config/old-image window\n  // never survives the deploy run.\n  if (plan.smoke) {\n    if (plan.smoke.action === \"skip\") {\n      legs.smoke = { status: \"skipped\", detail: plan.smoke.reason };\n      console.log();\n      console.log(colors.yellow(`  Post-publish smoke skipped: ${plan.smoke.reason}`));\n    } else {\n      const ref =\n        plan.smoke.ref ??\n        (imageDigest ? imageRefWithDigest(plan.smoke.image, imageDigest) : undefined);\n      if (!ref || !imageDigest) {\n        const smokeSkip = \"no runtime image digest — pass BOS_IMAGE_DIGEST for a pre-pushed image\";\n        legs.smoke = { status: \"skipped\", detail: smokeSkip };\n        console.log();\n        console.log(colors.yellow(`  Post-publish smoke skipped: ${smokeSkip}`));\n      } else {\n        console.log();\n        console.log(colors.cyan(\"  ▶ Post-publish smoke (boot gate)\"));\n        const smokeResult = await deps.runSmoke({\n          image: ref,\n          account: input.account,\n          gateway: input.domain,\n        });\n        if (!smokeResult.ok) {\n          const cause = smokeResult.error ?? \"unknown failure\";\n          console.log();\n          console.log(colors.error(`  ${icons.err} Post-publish smoke failed: ${cause}`));\n          if (smokeResult.diagnosis) {\n            console.log(colors.yellow(`  ${smokeResult.diagnosis}`));\n          }\n          legs.smoke = { status: \"failed\", detail: cause };\n          if (!input.account || !input.domain) {\n            console.log(colors.yellow(\"  Rollback skipped: no registry identity in the session\"));\n            return {\n              legs,\n              failure: `Post-publish smoke failed (${cause}) — config NOT rolled back: no registry identity`,\n            };\n          }\n          console.log(colors.yellow(\"  Rolling the published config back…\"));\n          const rollback = await deps.rollbackToPreviousSnapshot({\n            account: input.account,\n            domain: input.domain,\n            env: input.env,\n            runtimeConfig: input.runtimeConfig,\n            configDir: input.sessionRoot,\n            registry: input.registry,\n            network: input.network,\n            privateKey: input.privateKey,\n            verbose: input.verbose,\n          });\n          const rollbackNote = rollback.ok\n            ? `config rolled back to block ${rollback.blockHeight}`\n            : `config NOT rolled back: ${rollback.error ?? \"unknown\"}`;\n          console.log(colors.yellow(`  ${rollbackNote}`));\n          return {\n            legs,\n            failure: `Post-publish smoke failed (${cause}) — ${rollbackNote}`,\n          };\n        }\n        legs.smoke = { status: \"ok\", detail: smokeResult.summary };\n        console.log(\n          colors.green(`  ${icons.ok} Post-publish smoke passed: ${smokeResult.summary ?? \"\"}`),\n        );\n      }\n    }\n  }\n\n  const railwayStep = resolveRailwayStep({\n    tier,\n    token: process.env.RAILWAY_TOKEN,\n    service: input.railwayService,\n    pinnedDigest: imageDigest,\n    childPin,\n  });\n\n  if (railwayStep.action === \"skip\") {\n    legs.railway = { status: \"skipped\", detail: railwayStep.detail };\n    console.log();\n    console.log(colors.yellow(`  Railway deploy skipped: ${railwayStep.detail}`));\n  } else if (railwayStep.action === \"fail\") {\n    legs.railway = { status: \"failed\", detail: railwayStep.detail };\n    console.log();\n    console.log(colors.yellow(`  Railway deploy failed: ${railwayStep.detail}`));\n    return {\n      legs,\n      failure: `Config published but ${railwayStep.detail}`,\n    };\n  } else {\n    service = railwayStep.service;\n    try {\n      // A pinned child's service source follows the platform manifest pin\n      // before the redeploy pulls from it (ADR 0034): the pulled bytes are\n      // the pin, not whatever the dashboard's floating ref moved to.\n      if (railwayStep.action === \"repoint-and-redeploy\") {\n        await deps.repointServiceSource({\n          service: railwayStep.service,\n          image: railwayStep.image,\n          configDir: input.sessionRoot,\n        });\n      }\n      await deps.deployImageToRailway({\n        service: railwayStep.service,\n        configDir: input.sessionRoot,\n      });\n      legs.railway = {\n        status: \"ok\",\n        detail:\n          railwayStep.action === \"repoint-and-redeploy\"\n            ? `pinned ${railwayStep.image}, redeployed ${service}`\n            : `redeployed ${service}`,\n      };\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      const railError =\n        message.includes(\"not found\") || message.includes(\"ENOENT\")\n          ? \"Railway CLI not found. Install it: npm i -g @railway/cli\"\n          : `Railway deploy failed: ${message}`;\n      legs.railway = { status: \"failed\", detail: railError };\n      console.log(colors.yellow(`  ${railError}`));\n      return {\n        legs,\n        image,\n        imageDigest,\n        service,\n        failure: `Config published but ${railError}`,\n      };\n    }\n  }\n\n  return { image, imageDigest, service, legs };\n}\n"],"mappings":"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"}