{"version":3,"file":"rollback-flow.cjs","names":["fetchConfigHistory","fetchBosConfigFromFastKv","verifyRollbackSnapshot","buildRollbackPayload","BosConfigSchema","publishToFastKv"],"sources":["../../../src/services/deploy/rollback-flow.ts"],"sourcesContent":["import { type BosConfigInput, BosConfigSchema, type RuntimeConfig } from \"../../types\";\nimport {\n  type ConfigHistoryEntry,\n  fetchBosConfigFromFastKv,\n  fetchConfigHistory,\n} from \"../registry/fastkv\";\nimport { buildRollbackPayload, verifyRollbackSnapshot } from \"./rollback\";\nimport { publishToFastKv } from \"./train\";\n\n/**\n * The shared rollback flow (ticket #422): the post-publish smoke failure\n * protocol and the `bos rollback` command both stamp `rolledBackFrom` onto\n * the target snapshot and republish it verbatim (`exactPayload`) — one\n * implementation here; the callers differ only in how they pick and vet the\n * target (the command's two-stage verification with --force; the smoke\n * protocol's simple refusal).\n */\n\nexport interface RollbackSnapshotInput {\n  account: string;\n  domain: string;\n  env: \"production\" | \"staging\";\n  runtimeConfig: RuntimeConfig | null;\n  configDir: string;\n  registry?: string;\n  network?: \"mainnet\" | \"testnet\";\n  privateKey?: string;\n  wallet?: boolean;\n  verbose?: boolean;\n  dryRun?: boolean;\n}\n\nexport interface RollbackSnapshotOutcome {\n  ok: boolean;\n  registryUrl: string;\n  txHash?: string;\n  /** the caller passed dryRun — the snapshot was validated but not published */\n  dryRun?: boolean;\n  error?: string;\n}\n\nexport async function fetchRollbackHistory(input: {\n  account: string;\n  domain: string;\n  registry?: string;\n  limit: number;\n}): Promise<ConfigHistoryEntry[]> {\n  return fetchConfigHistory({\n    accountId: input.account,\n    gatewayId: input.domain,\n    registry: input.registry,\n    limit: input.limit,\n  });\n}\n\n/** The live config, or undefined when the registry read fails (an unknown\n * live state never blocks a rollback — the snapshot publish is idempotent). */\nexport async function fetchLiveConfig(input: {\n  account: string;\n  domain: string;\n  registry?: string;\n}): Promise<unknown | undefined> {\n  try {\n    return await fetchBosConfigFromFastKv<unknown>(\n      `bos://${input.account}/${input.domain}`,\n      input.registry,\n    );\n  } catch {\n    return undefined;\n  }\n}\n\nexport function isSnapshotLive(targetValue: unknown, liveValue: unknown): boolean {\n  return JSON.stringify(liveValue) === JSON.stringify(targetValue);\n}\n\n/** Stamp + republish the target snapshot verbatim. Callers own verification:\n * the smoke protocol refuses unverified targets via\n * `rollbackToPreviousSnapshot`; the command runs its two-stage check and\n * passes `skipVerify` once it has vetted (or --forced) the snapshot. */\nexport async function publishRollbackSnapshot(\n  targetValue: unknown,\n  input: RollbackSnapshotInput,\n  opts?: { skipVerify?: boolean },\n): Promise<RollbackSnapshotOutcome> {\n  if (!opts?.skipVerify) {\n    const verification = await verifyRollbackSnapshot(targetValue as BosConfigInput);\n    if (!verification.ok && verification.verifiable) {\n      return {\n        ok: false,\n        registryUrl: \"\",\n        error: \"rollback refused — a pinned slot's bytes are gone or no longer match their SRI\",\n      };\n    }\n  }\n\n  const payload = buildRollbackPayload(\n    BosConfigSchema.parse(targetValue),\n    new Date().toISOString(),\n  );\n  const result = await publishToFastKv({\n    bosConfig: payload,\n    runtimeConfig: input.runtimeConfig,\n    configDir: input.configDir,\n    env: input.env,\n    build: false,\n    dryRun: input.dryRun ?? false,\n    verbose: input.verbose ?? false,\n    packages: \"all\",\n    network: input.network,\n    privateKey: input.privateKey,\n    wallet: input.wallet ?? false,\n    registry: input.registry,\n    exactPayload: true,\n  });\n  if (result.status === \"dry-run\") {\n    return { ok: true, registryUrl: result.registryUrl, dryRun: true };\n  }\n  if (result.status === \"error\") {\n    return {\n      ok: false,\n      registryUrl: result.registryUrl,\n      error: `rollback publish failed: ${result.error ?? result.status}`,\n    };\n  }\n  return { ok: true, registryUrl: result.registryUrl, txHash: result.txHash };\n}\n\n/** The post-publish smoke failure protocol (ADR 0021): roll the registry\n * config back to the previous snapshot — a red boot gate must never leave a\n * new config live against an old image. */\nexport async function rollbackToPreviousSnapshot(input: RollbackSnapshotInput): Promise<{\n  ok: boolean;\n  txHash?: string;\n  blockHeight?: string;\n  registryUrl: string;\n  error?: string;\n}> {\n  let history: ConfigHistoryEntry[];\n  try {\n    history = await fetchRollbackHistory({\n      account: input.account,\n      domain: input.domain,\n      registry: input.registry,\n      limit: 20,\n    });\n  } catch (error) {\n    return {\n      ok: false,\n      registryUrl: \"\",\n      error: `fetching publish history failed: ${error instanceof Error ? error.message : String(error)}`,\n    };\n  }\n\n  const previous = history[1];\n  if (!previous) {\n    return {\n      ok: false,\n      registryUrl: \"\",\n      error: \"no previous snapshot in the publish history — nothing to roll back to\",\n    };\n  }\n\n  const result = await publishRollbackSnapshot(previous.value, input);\n  if (result.ok) {\n    return {\n      ok: true,\n      blockHeight: String(previous.blockHeight),\n      registryUrl: result.registryUrl,\n      txHash: result.txHash,\n    };\n  }\n  return result;\n}\n"],"mappings":";;;;;;AAyCA,eAAsB,qBAAqB,OAKT;CAChC,OAAOA,oDAAmB;EACxB,WAAW,MAAM;EACjB,WAAW,MAAM;EACjB,UAAU,MAAM;EAChB,OAAO,MAAM;CACf,CAAC;AACH;;;AAIA,eAAsB,gBAAgB,OAIL;CAC/B,IAAI;EACF,OAAO,MAAMC,0DACX,SAAS,MAAM,QAAQ,GAAG,MAAM,UAChC,MAAM,QACR;CACF,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,eAAe,aAAsB,WAA6B;CAChF,OAAO,KAAK,UAAU,SAAS,MAAM,KAAK,UAAU,WAAW;AACjE;;;;;AAMA,eAAsB,wBACpB,aACA,OACA,MACkC;CAClC,IAAI,CAAC,MAAM,YAAY;EACrB,MAAM,eAAe,MAAMC,wCAAuB,WAA6B;EAC/E,IAAI,CAAC,aAAa,MAAM,aAAa,YACnC,OAAO;GACL,IAAI;GACJ,aAAa;GACb,OAAO;EACT;CAEJ;CAEA,MAAM,UAAUC,sCACdC,8BAAgB,MAAM,WAAW,oBACjC,IAAI,KAAK,EAAC,CAAC,YAAY,CACzB;CACA,MAAM,SAAS,MAAMC,8BAAgB;EACnC,WAAW;EACX,eAAe,MAAM;EACrB,WAAW,MAAM;EACjB,KAAK,MAAM;EACX,OAAO;EACP,QAAQ,MAAM,UAAU;EACxB,SAAS,MAAM,WAAW;EAC1B,UAAU;EACV,SAAS,MAAM;EACf,YAAY,MAAM;EAClB,QAAQ,MAAM,UAAU;EACxB,UAAU,MAAM;EAChB,cAAc;CAChB,CAAC;CACD,IAAI,OAAO,WAAW,WACpB,OAAO;EAAE,IAAI;EAAM,aAAa,OAAO;EAAa,QAAQ;CAAK;CAEnE,IAAI,OAAO,WAAW,SACpB,OAAO;EACL,IAAI;EACJ,aAAa,OAAO;EACpB,OAAO,4BAA4B,OAAO,SAAS,OAAO;CAC5D;CAEF,OAAO;EAAE,IAAI;EAAM,aAAa,OAAO;EAAa,QAAQ,OAAO;CAAO;AAC5E;;;;AAKA,eAAsB,2BAA2B,OAM9C;CACD,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,qBAAqB;GACnC,SAAS,MAAM;GACf,QAAQ,MAAM;GACd,UAAU,MAAM;GAChB,OAAO;EACT,CAAC;CACH,SAAS,OAAO;EACd,OAAO;GACL,IAAI;GACJ,aAAa;GACb,OAAO,oCAAoC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAClG;CACF;CAEA,MAAM,WAAW,QAAQ;CACzB,IAAI,CAAC,UACH,OAAO;EACL,IAAI;EACJ,aAAa;EACb,OAAO;CACT;CAGF,MAAM,SAAS,MAAM,wBAAwB,SAAS,OAAO,KAAK;CAClE,IAAI,OAAO,IACT,OAAO;EACL,IAAI;EACJ,aAAa,OAAO,SAAS,WAAW;EACxC,aAAa,OAAO;EACpB,QAAQ,OAAO;CACjB;CAEF,OAAO;AACT"}