{"version":3,"file":"tenant.mjs","names":["UI_REMOTE_ENTRY_FILENAME","UI_REMOTE_SERVER_ENTRY_FILENAME"],"sources":["../../src/ui/tenant.ts"],"sourcesContent":["/**\n * Tenant helpers shared by every ui workspace.\n *\n * Two halves of the tenant surface live here:\n * - origin construction (`buildTenantUrl`, `tenantLabel`, `gatewayForAccount`)\n * - the pure helpers for the org node-config editor: a validated draft of the\n *   fields a tenant may customize in its published bos.config.json, prefilled\n *   from the currently published config, diffed against it, and an in-browser\n *   sha384 preflight so a wrong UI bundle cannot brick the tenant site.\n */\n\nimport { z } from \"zod\";\nimport type { ClientRuntimeConfig } from \"../types\";\nimport { UI_REMOTE_ENTRY_FILENAME, UI_REMOTE_SERVER_ENTRY_FILENAME } from \"./manifest\";\nimport { getRuntimeConfig } from \"./runtime\";\n\nconst LOCALHOST_SUFFIX = \".localhost\";\n\nexport function isLocalHostname(hostname: string): boolean {\n  const normalized = hostname.toLowerCase();\n  return (\n    normalized === \"localhost\" ||\n    normalized === \"127.0.0.1\" ||\n    normalized === \"[::1]\" ||\n    normalized.endsWith(LOCALHOST_SUFFIX)\n  );\n}\n\n/** Strips a `<label>.<gatewayId>` hostname (or a bare label) down to its label. */\nexport function tenantLabel(hostnameOrLabel: string, gatewayId?: string): string {\n  const normalized = hostnameOrLabel.trim().toLowerCase().replace(/\\/+$/, \"\");\n  if (!normalized) return \"\";\n  const gateway = gatewayId?.trim().toLowerCase();\n  if (gateway && normalized.endsWith(`.${gateway}`)) {\n    return normalized.slice(0, -(gateway.length + 1));\n  }\n  if (normalized.endsWith(LOCALHOST_SUFFIX)) {\n    return normalized.slice(0, -LOCALHOST_SUFFIX.length);\n  }\n  return normalized.split(\".\")[0] ?? \"\";\n}\n\nexport interface BuildTenantUrlOptions {\n  /** Current browser origin hostname. Defaults to `window.location.hostname`. */\n  currentHostname?: string;\n  /** Current browser origin port. Defaults to `window.location.port`. */\n  currentPort?: string;\n  /** Appended to the origin, e.g. `/stake`. */\n  path?: string;\n}\n\n/**\n * Builds the absolute origin for a tenant, dev-aware.\n *\n * `buildTenantUrl(\"chicago\", \"citynode.app\")`\n *   -> `https://chicago.citynode.app` in production\n *   -> `http://chicago.localhost:3000` when served from localhost\n */\nexport function buildTenantUrl(\n  hostnameOrLabel: string,\n  gatewayId: string,\n  options: BuildTenantUrlOptions = {},\n): string | null {\n  const label = tenantLabel(hostnameOrLabel, gatewayId);\n  if (!label) return null;\n\n  const path = options.path ?? \"\";\n  const currentHostname =\n    options.currentHostname ??\n    (typeof window === \"undefined\" ? undefined : window.location.hostname);\n\n  if (currentHostname && isLocalHostname(currentHostname)) {\n    const currentPort =\n      options.currentPort ?? (typeof window === \"undefined\" ? \"\" : window.location.port);\n    const port = currentPort ? `:${currentPort}` : \"\";\n    return `http://${label}${LOCALHOST_SUFFIX}${port}${path}`;\n  }\n\n  const gateway = gatewayId.trim().toLowerCase();\n  if (!gateway) return null;\n  return `https://${label}.${gateway}${path}`;\n}\n\n/**\n * The gateway a slug should publish under for the given owner account,\n * derived from the runtime config instead of hardcoded per-network domains.\n *\n * When the account lives on the same network as the runtime, the current\n * runtime's gateway id is the answer. When the networks differ, the runtime\n * config carries no gateway for that other network, so null is returned and\n * the caller surfaces it rather than guessing a domain.\n */\nexport function gatewayForAccount(\n  accountId: string,\n  config: Pick<ClientRuntimeConfig, \"networkId\" | \"runtime\"> = getRuntimeConfig(),\n): string | null {\n  const gatewayId = config.runtime?.gatewayId;\n  if (!gatewayId) return null;\n  const testnetAccount = accountId.trim().toLowerCase().endsWith(\".testnet\");\n  return testnetAccount === (config.networkId === \"testnet\") ? gatewayId : null;\n}\n\nexport interface TenantUiOverride {\n  production: string;\n  /** direct entry SRI — only for genuinely fixed-name bundles without a pin */\n  integrity?: string;\n  /** version-manifest pin — the deploy unit for hashed, atomic deploys */\n  pin?: { manifest: string; integrity: string };\n  ssr?: string;\n  ssrIntegrity?: string;\n}\n\nexport const INTEGRITY_PATTERN = /^sha384-[A-Za-z0-9+/=]+$/;\n\nexport const defaultTenantConfigDraftMessages = {\n  url: \"must be a valid URL\",\n  integrity: \"must look like sha384-… (base64)\",\n  manifest: \"must look like versions/<version-id>.json\",\n  title: \"title is required\",\n  description: \"description is required\",\n  uiPair: \"a UI bundle needs both its URL and its integrity (direct hash or manifest pin)\",\n  integrityMode:\n    \"choose one integrity mode — a direct entry hash or a version-manifest pin, not both\",\n  pinPair: \"a version-manifest pin needs both the manifest filename and its integrity\",\n  ssrPair: \"an SSR bundle needs both its URL and its integrity hash\",\n};\n\nexport function createTenantConfigDraftSchema(\n  messages: Partial<typeof defaultTenantConfigDraftMessages> = {},\n) {\n  const copy = { ...defaultTenantConfigDraftMessages, ...messages };\n  const optionalUrl = z\n    .string()\n    .trim()\n    .url(copy.url)\n    .or(z.literal(\"\"))\n    .transform((value) => value.trim());\n  const optionalIntegrity = z\n    .string()\n    .trim()\n    .regex(INTEGRITY_PATTERN, copy.integrity)\n    .or(z.literal(\"\"));\n  const optionalManifestName = z\n    .string()\n    .trim()\n    .regex(/^versions\\/[0-9a-f]{16}\\.json$/, copy.manifest)\n    .or(z.literal(\"\"));\n  return z\n    .object({\n      title: z.string().trim().min(1, copy.title),\n      description: z.string().trim().min(1, copy.description),\n      repository: optionalUrl,\n      uiProduction: optionalUrl,\n      uiIntegrity: optionalIntegrity,\n      uiManifest: optionalManifestName,\n      uiPinIntegrity: optionalIntegrity,\n      ssrUrl: optionalUrl,\n      ssrIntegrity: optionalIntegrity,\n    })\n    .refine((draft) => !!draft.uiProduction === !!(draft.uiIntegrity || draft.uiManifest), {\n      message: copy.uiPair,\n      path: [\"uiIntegrity\"],\n    })\n    .refine((draft) => !draft.uiIntegrity || !draft.uiManifest, {\n      message: copy.integrityMode,\n      path: [\"uiManifest\"],\n    })\n    .refine((draft) => !!draft.uiManifest === !!draft.uiPinIntegrity, {\n      message: copy.pinPair,\n      path: [\"uiPinIntegrity\"],\n    })\n    .refine((draft) => !!draft.ssrUrl === !!draft.ssrIntegrity, {\n      message: copy.ssrPair,\n      path: [\"ssrIntegrity\"],\n    });\n}\nexport const tenantConfigDraftSchema = createTenantConfigDraftSchema();\n\nexport type TenantConfigDraft = z.infer<typeof tenantConfigDraftSchema>;\n\nexport const emptyTenantConfigDraft: TenantConfigDraft = {\n  title: \"\",\n  description: \"\",\n  repository: \"\",\n  uiProduction: \"\",\n  uiIntegrity: \"\",\n  uiManifest: \"\",\n  uiPinIntegrity: \"\",\n  ssrUrl: \"\",\n  ssrIntegrity: \"\",\n};\n\ninterface ResolvedUiConfig {\n  production?: unknown;\n  integrity?: unknown;\n  pin?: { manifest?: unknown; integrity?: unknown };\n  ssr?: unknown;\n  ssrIntegrity?: unknown;\n}\n\nfunction readUi(resolvedConfig: Record<string, unknown> | null | undefined): ResolvedUiConfig {\n  const app = resolvedConfig?.app as { ui?: ResolvedUiConfig } | undefined;\n  return app?.ui ?? {};\n}\n\nconst asString = (value: unknown) => (typeof value === \"string\" ? value : \"\");\n\nexport function buildDraftFromResolvedConfig(\n  resolvedConfig: Record<string, unknown> | null | undefined,\n  fallback: { title: string },\n): TenantConfigDraft {\n  const ui = readUi(resolvedConfig);\n  const title = asString(resolvedConfig?.title) || fallback.title;\n  return {\n    title,\n    description: asString(resolvedConfig?.description) || title,\n    repository: asString(resolvedConfig?.repository),\n    uiProduction: asString(ui.production),\n    uiIntegrity: asString(ui.integrity),\n    uiManifest: asString(ui.pin?.manifest),\n    uiPinIntegrity: asString(ui.pin?.integrity),\n    ssrUrl: asString(ui.ssr),\n    ssrIntegrity: asString(ui.ssrIntegrity),\n  };\n}\n\nexport interface DraftDiffEntry {\n  field: string;\n  from: string;\n  to: string;\n}\n\nexport function diffDraft(\n  draft: TenantConfigDraft,\n  resolvedConfig: Record<string, unknown> | null | undefined,\n): DraftDiffEntry[] {\n  const ui = readUi(resolvedConfig);\n  const pairs: [string, string, string][] = [\n    [\"title\", asString(resolvedConfig?.title), draft.title],\n    [\"description\", asString(resolvedConfig?.description), draft.description],\n    [\"repository\", asString(resolvedConfig?.repository), draft.repository],\n    [\"ui bundle\", asString(ui.production), draft.uiProduction],\n    [\"ui integrity\", asString(ui.integrity), draft.uiIntegrity],\n    [\"ui manifest pin\", asString(ui.pin?.manifest), draft.uiManifest],\n    [\"ui pin integrity\", asString(ui.pin?.integrity), draft.uiPinIntegrity],\n    [\"ssr bundle\", asString(ui.ssr), draft.ssrUrl],\n    [\"ssr integrity\", asString(ui.ssrIntegrity), draft.ssrIntegrity],\n  ];\n  return pairs\n    .filter(([, from, to]) => from !== to)\n    .map(([field, from, to]) => ({ field, from: from || \"—\", to: to || \"—\" }));\n}\n\n/** The `app` block for the published config, or undefined when no UI override is set. */\nexport function draftUiOverride(draft: TenantConfigDraft): { ui: TenantUiOverride } | undefined {\n  if (!draft.uiProduction) return undefined;\n  if (draft.uiManifest && draft.uiPinIntegrity) {\n    return {\n      ui: {\n        production: normalizeBundleBaseUrl(draft.uiProduction),\n        pin: { manifest: draft.uiManifest, integrity: draft.uiPinIntegrity },\n        ...(draft.ssrUrl && draft.ssrIntegrity\n          ? { ssr: normalizeBundleBaseUrl(draft.ssrUrl), ssrIntegrity: draft.ssrIntegrity }\n          : {}),\n      },\n    };\n  }\n  if (!draft.uiIntegrity) return undefined;\n  return {\n    ui: {\n      production: normalizeBundleBaseUrl(draft.uiProduction),\n      integrity: draft.uiIntegrity,\n      ...(draft.ssrUrl && draft.ssrIntegrity\n        ? { ssr: normalizeBundleBaseUrl(draft.ssrUrl), ssrIntegrity: draft.ssrIntegrity }\n        : {}),\n    },\n  };\n}\n\nexport type IntegrityCheckResult =\n  | { status: \"match\" }\n  | { status: \"mismatch\"; computed: string }\n  | { status: \"unverified\"; reason: string };\n\nfunction toBase64(bytes: Uint8Array): string {\n  let binary = \"\";\n  const chunkSize = 0x8000;\n  for (let offset = 0; offset < bytes.length; offset += chunkSize) {\n    binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));\n  }\n  return btoa(binary);\n}\n\nexport async function computeSubresourceIntegrity(url: string): Promise<string> {\n  const response = await fetch(url, { cache: \"no-store\" });\n  if (!response.ok) {\n    throw new Error(`fetching the bundle returned ${response.status}`);\n  }\n  const buffer = await response.arrayBuffer();\n  const digest = await crypto.subtle.digest(\"SHA-384\", buffer);\n  return `sha384-${toBase64(new Uint8Array(digest))}`;\n}\n\nexport function resolveClientEntryUrl(url: string): string {\n  if (/\\/remoteEntry(\\.[a-f0-9]{8,})?\\.js$/.test(url)) return url;\n  if (url.endsWith(\"/mf-manifest.json\"))\n    return `${url.replace(/\\/mf-manifest\\.json$/, \"\")}/${UI_REMOTE_ENTRY_FILENAME}`;\n  return `${url.replace(/\\/$/, \"\")}/${UI_REMOTE_ENTRY_FILENAME}`;\n}\n\nexport function resolveServerEntryUrl(url: string): string {\n  return `${url.replace(/\\/$/, \"\")}/${UI_REMOTE_SERVER_ENTRY_FILENAME}`;\n}\n\nexport function normalizeBundleBaseUrl(url: string): string {\n  return url\n    .trim()\n    .replace(/\\/remoteEntry(\\.server)?(\\.[a-f0-9]{8,})?\\.js$/, \"\")\n    .replace(/\\/mf-manifest\\.json$/, \"\");\n}\n\nexport async function computeUiEntryIntegrity(baseUrl: string): Promise<string> {\n  return computeSubresourceIntegrity(resolveClientEntryUrl(baseUrl.trim()));\n}\n\nexport async function computeSsrEntryIntegrity(baseUrl: string): Promise<string> {\n  return computeSubresourceIntegrity(resolveServerEntryUrl(baseUrl.trim()));\n}\n\nasync function verifyEntryIntegrity(\n  entryUrl: string,\n  expected: string,\n): Promise<IntegrityCheckResult> {\n  try {\n    const computed = await computeSubresourceIntegrity(entryUrl);\n    return computed === expected ? { status: \"match\" } : { status: \"mismatch\", computed };\n  } catch (error) {\n    return {\n      status: \"unverified\",\n      reason: error instanceof Error ? error.message : String(error),\n    };\n  }\n}\n\nexport async function verifyUiIntegrity(\n  baseUrl: string,\n  expected: string,\n): Promise<IntegrityCheckResult> {\n  return verifyEntryIntegrity(resolveClientEntryUrl(baseUrl.trim()), expected);\n}\n\n/**\n * Pin preflight: fetch the pinned version-manifest document and SRI-compare it\n * against the pin — the manifest's own `entryIntegrity` covers the entry bytes\n * at serve time.\n */\nexport async function verifyUiPin(\n  baseUrl: string,\n  pin: { manifest: string; integrity: string },\n): Promise<IntegrityCheckResult> {\n  const manifestUrl = `${baseUrl.trim().replace(/\\/$/, \"\")}/${pin.manifest.replace(/^\\//, \"\")}`;\n  return verifyEntryIntegrity(manifestUrl, pin.integrity);\n}\n\nexport async function verifySsrIntegrity(\n  baseUrl: string,\n  expected: string,\n): Promise<IntegrityCheckResult> {\n  return verifyEntryIntegrity(resolveServerEntryUrl(baseUrl.trim()), expected);\n}\n"],"mappings":"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"}