import fs from 'node:fs' import path from 'node:path' function normalizeTrimmed(value) { return String(value || '').trim() } function normalizeDeploymentTier(value, fallback = 'launch') { const normalized = normalizeTrimmed(value).toLowerCase() if (normalized === 'preview' || normalized === 'launch') { return normalized } return fallback } function collapseWhitespace(value) { return normalizeTrimmed(value).replace(/\s+/g, ' ') } function stripOptionalQuotes(value) { const trimmed = normalizeTrimmed(value) if ( (trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'")) ) { return trimmed.slice(1, -1) } return trimmed } function tryParseUrl(value) { const trimmed = normalizeTrimmed(value) if (!trimmed) { return null } try { return new URL(trimmed) } catch { return null } } function isPlaceholderLike(value) { const trimmed = normalizeTrimmed(value).toLowerCase() if (!trimmed) { return false } return trimmed.includes('replace-me') || trimmed.includes('replace_me') || trimmed.includes('changeme') || trimmed.includes('change-me') || trimmed.includes('your-') || trimmed.includes('your_') || trimmed.includes('<') || trimmed.includes('todo') } function isLoopbackHostname(hostname) { const normalized = normalizeTrimmed(hostname).toLowerCase() return normalized === 'localhost' || normalized === '127.0.0.1' || normalized === '::1' || normalized === '[::1]' } function isHttpsUrl(url) { return url?.protocol === 'https:' } const RELEASE_MANIFEST_PLATFORM_EXPECTATIONS = [ { platformKey: 'windows', envPrefix: 'WINDOWS', legacyFrontendUrlKey: 'VITE_WINDOWS_DOWNLOAD_URL', label: 'Windows', }, { platformKey: 'macos', envPrefix: 'MACOS', legacyFrontendUrlKey: 'VITE_MAC_DOWNLOAD_URL', label: 'macOS', }, { platformKey: 'linux', envPrefix: 'LINUX', legacyFrontendUrlKey: 'VITE_LINUX_DOWNLOAD_URL', label: 'Linux', }, ] function createBucket() { return { failures: [], warnings: [], } } function summarizeResponseBody(value, maxLength = 160) { const normalized = collapseWhitespace(value) if (!normalized) { return '' } if (normalized.length <= maxLength) { return normalized } return `${normalized.slice(0, maxLength - 1)}…` } function looksLikeHtmlResponse(contentType, body) { const normalizedContentType = normalizeTrimmed(contentType).toLowerCase() const normalizedBody = normalizeTrimmed(body).toLowerCase() return normalizedContentType.includes('text/html') || normalizedBody.startsWith('(.*?)<\/title>/i) return match ? collapseWhitespace(match[1]) : '' } function detectPlaceholderRolloutPage(html) { const normalized = collapseWhitespace(html).toLowerCase() return normalized.includes('deployment target is live on the new vps') || normalized.includes('application rollout is pending') } function buildEndpointResponseError(label, response, body) { const snippet = summarizeResponseBody(body) const contentType = normalizeTrimmed(response.headers?.get?.('content-type') || '') if (looksLikeHtmlResponse(contentType, body)) { const placeholderSuffix = detectPlaceholderRolloutPage(body) ? ' The response still appears to be the placeholder rollout page.' : '' return new Error(`${label} returned HTML instead of JSON.${placeholderSuffix}${snippet ? ` Snippet: ${snippet}` : ''}`) } return new Error(`${label} returned invalid JSON.${snippet ? ` Snippet: ${snippet}` : ''}`) } async function fetchJsonEndpoint(baseUrl, routePath, label, fetchImpl = fetch) { const targetUrl = `${normalizeTrimmed(baseUrl).replace(/\/$/, '')}${routePath}` const response = await fetchImpl(targetUrl, { headers: { accept: 'application/json', }, }) const body = await response.text() if (!response.ok) { throw new Error(`${label} failed with HTTP ${response.status}.${body ? ` Snippet: ${summarizeResponseBody(body)}` : ''}`) } try { return JSON.parse(body) } catch { throw buildEndpointResponseError(label, response, body) } } function pushFailure(bucket, message) { bucket.failures.push(message) } function pushWarning(bucket, message) { bucket.warnings.push(message) } function requireNonEmpty(bucket, label, value) { if (!normalizeTrimmed(value)) { pushFailure(bucket, `${label} is missing.`) return false } return true } function requireAbsoluteUrl(bucket, label, value) { if (!requireNonEmpty(bucket, label, value)) { return null } const parsed = tryParseUrl(value) if (!parsed) { pushFailure(bucket, `${label} must be an absolute URL.`) return null } return parsed } function rejectPlaceholderValue(bucket, label, value) { if (isPlaceholderLike(value)) { pushFailure(bucket, `${label} still contains a placeholder value.`) } } function resolveEnvCandidate(frontendEnv, serverEnv, frontendKey, serverKey) { const frontendValue = normalizeTrimmed(frontendEnv[frontendKey]) if (frontendValue) { return { label: frontendKey, value: frontendValue, } } const serverValue = normalizeTrimmed(serverEnv[serverKey]) if (serverValue) { return { label: serverKey, value: serverValue, } } return { label: `${frontendKey} or ${serverKey}`, value: '', } } function readEnvFirst(frontendEnv, serverEnv, frontendKey, serverKey = frontendKey) { return normalizeTrimmed(frontendEnv[frontendKey] || serverEnv[serverKey]) } function readServerOnly(serverEnv, key) { return normalizeTrimmed(serverEnv[key]) } function readOptionalInteger(serverEnv, key) { const rawValue = readServerOnly(serverEnv, key) if (!rawValue) { return null } const value = Number(rawValue) if (!Number.isFinite(value) || value < 0) { return null } return Math.trunc(value) } function formatRuntimeComparableValue(value) { if (value === null || value === undefined) { return '(blank)' } if (typeof value === 'boolean') { return value ? 'true' : 'false' } if (typeof value === 'number') { return Number.isFinite(value) ? String(value) : '(blank)' } const trimmed = normalizeTrimmed(value) return trimmed || '(blank)' } function compareRuntimeComparableValues(expected, actual) { return formatRuntimeComparableValue(expected) === formatRuntimeComparableValue(actual) } function pushLiveManifestDriftFailure(failures, label, expected, actual) { failures.push( `${label} drifted from configured launch authority (expected ${formatRuntimeComparableValue(expected)}, got ${formatRuntimeComparableValue(actual)}).`, ) } function appendLiveReleaseManifestDriftChecks({ failures, frontendEnv, serverEnv, liveReleaseManifest, }) { const manifest = liveReleaseManifest?.manifest if (!manifest) { return } const topLevelExpectations = [ { label: 'Live release manifest support email', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_SUPPORT_EMAIL', 'SUPPORT_EMAIL') || 'hello@hypertwist.app', actual: manifest.support_email, }, { label: 'Live release manifest public docs URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_PUBLIC_DOCS_URL', 'PUBLIC_DOCS_URL'), actual: manifest.public_docs_url, }, { label: 'Live release manifest release-notes URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_RELEASE_NOTES_URL', 'RELEASE_NOTES_URL'), actual: manifest.release_notes_url, }, { label: 'Live release manifest corresponding-source URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_MPL_SOURCE_URL', 'MPL_SOURCE_URL'), actual: manifest.corresponding_source_url, }, { label: 'Live release manifest open-source repo URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_OPEN_SOURCE_REPO_URL', 'OPEN_SOURCE_REPO_URL'), actual: manifest.open_source_repo_url, }, { label: 'Live release manifest operator checkout URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_PADDLE_CHECKOUT_URL_OPERATOR'), actual: manifest.commerce?.operator_checkout_url, }, { label: 'Live release manifest studio checkout URL', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_PADDLE_CHECKOUT_URL_STUDIO'), actual: manifest.commerce?.studio_checkout_url, }, { label: 'Live release manifest operator price string', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_PLAN_PRICE_OPERATOR') || 'Launch pricing via Paddle', actual: manifest.commerce?.plan_price_operator, }, { label: 'Live release manifest studio price string', expected: readEnvFirst(frontendEnv, serverEnv, 'VITE_PLAN_PRICE_STUDIO') || 'Contact for launch readiness', actual: manifest.commerce?.plan_price_studio, }, ] for (const expectation of topLevelExpectations) { if (!compareRuntimeComparableValues(expectation.expected, expectation.actual)) { pushLiveManifestDriftFailure(failures, expectation.label, expectation.expected, expectation.actual) } } const platforms = Array.isArray(manifest.platforms) ? manifest.platforms : [] const globalVersion = readServerOnly(serverEnv, 'RELEASE_MANIFEST_VERSION') const globalChannel = readServerOnly(serverEnv, 'RELEASE_MANIFEST_CHANNEL') || 'preview' for (const definition of RELEASE_MANIFEST_PLATFORM_EXPECTATIONS) { const platform = platforms.find((entry) => entry?.platform_key === definition.platformKey) if (!platform) { failures.push(`Live release manifest is missing the ${definition.label} platform entry.`) continue } const configuredCandidate = resolveEnvCandidate( frontendEnv, serverEnv, definition.legacyFrontendUrlKey, `${definition.envPrefix}_DOWNLOAD_URL`, ) const expectedConfigured = Boolean(normalizeTrimmed(configuredCandidate.value)) const platformExpectations = [ { label: `Live release manifest ${definition.label} configured posture`, expected: expectedConfigured, actual: platform.configured === true, }, { label: `Live release manifest ${definition.label} release channel`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_CHANNEL`) || globalChannel, actual: platform.channel, }, { label: `Live release manifest ${definition.label} release version`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_VERSION`) || globalVersion, actual: platform.version, }, { label: `Live release manifest ${definition.label} release build ID`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_BUILD_ID`), actual: platform.build_id, }, { label: `Live release manifest ${definition.label} published-at timestamp`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_PUBLISHED_AT`), actual: platform.published_at, }, { label: `Live release manifest ${definition.label} release file name`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_FILE_NAME`), actual: platform.file_name, }, { label: `Live release manifest ${definition.label} release file size`, expected: readOptionalInteger(serverEnv, `${definition.envPrefix}_RELEASE_FILE_SIZE_BYTES`), actual: platform.file_size_bytes, }, { label: `Live release manifest ${definition.label} release checksum`, expected: readServerOnly(serverEnv, `${definition.envPrefix}_RELEASE_SHA256`), actual: platform.checksum_sha256, }, ] for (const expectation of platformExpectations) { if (!compareRuntimeComparableValues(expectation.expected, expectation.actual)) { pushLiveManifestDriftFailure(failures, expectation.label, expectation.expected, expectation.actual) } } } } function requireAbsoluteUrlCandidate(bucket, label, value) { if (!requireNonEmpty(bucket, label, value)) { return null } const parsed = tryParseUrl(value) if (!parsed) { pushFailure(bucket, `${label} must be an absolute URL.`) return null } rejectPlaceholderValue(bucket, label, value) return parsed } function evaluateFrontendConfig(frontendEnv, serverEnv, deploymentTier = 'launch') { const bucket = createBucket() const superTokensApiDomain = requireAbsoluteUrl(bucket, 'VITE_SUPERTOKENS_API_DOMAIN', frontendEnv.VITE_SUPERTOKENS_API_DOMAIN) const superTokensWebsiteDomain = requireAbsoluteUrl(bucket, 'VITE_SUPERTOKENS_WEBSITE_DOMAIN', frontendEnv.VITE_SUPERTOKENS_WEBSITE_DOMAIN) const authApiBaseUrl = requireAbsoluteUrl(bucket, 'VITE_AUTH_API_BASE_URL', frontendEnv.VITE_AUTH_API_BASE_URL) const windowsDownloadCandidate = resolveEnvCandidate(frontendEnv, serverEnv, 'VITE_WINDOWS_DOWNLOAD_URL', 'WINDOWS_DOWNLOAD_URL') if (!normalizeTrimmed(windowsDownloadCandidate.value)) { if (deploymentTier === 'preview') { pushWarning(bucket, `${windowsDownloadCandidate.label} is not set; Windows download will remain in preview posture until the release lane is configured.`) } else { requireAbsoluteUrlCandidate(bucket, windowsDownloadCandidate.label, windowsDownloadCandidate.value) } } else { requireAbsoluteUrlCandidate(bucket, windowsDownloadCandidate.label, windowsDownloadCandidate.value) } if (!normalizeTrimmed(frontendEnv.VITE_PADDLE_CHECKOUT_URL_OPERATOR)) { if (deploymentTier === 'preview') { pushWarning(bucket, 'VITE_PADDLE_CHECKOUT_URL_OPERATOR is not set; Operator pricing will stay on the support fallback until checkout is configured.') } else { pushFailure(bucket, 'VITE_PADDLE_CHECKOUT_URL_OPERATOR is missing.') } } else if (!tryParseUrl(frontendEnv.VITE_PADDLE_CHECKOUT_URL_OPERATOR)) { pushFailure(bucket, 'VITE_PADDLE_CHECKOUT_URL_OPERATOR must be an absolute URL.') } else { rejectPlaceholderValue(bucket, 'VITE_PADDLE_CHECKOUT_URL_OPERATOR', frontendEnv.VITE_PADDLE_CHECKOUT_URL_OPERATOR) } const correspondingSourceCandidate = resolveEnvCandidate(frontendEnv, serverEnv, 'VITE_MPL_SOURCE_URL', 'MPL_SOURCE_URL') requireAbsoluteUrlCandidate(bucket, correspondingSourceCandidate.label, correspondingSourceCandidate.value) const openSourceRepoCandidate = resolveEnvCandidate(frontendEnv, serverEnv, 'VITE_OPEN_SOURCE_REPO_URL', 'OPEN_SOURCE_REPO_URL') requireAbsoluteUrlCandidate(bucket, openSourceRepoCandidate.label, openSourceRepoCandidate.value) for (const [label, url] of [ ['VITE_SUPERTOKENS_API_DOMAIN', superTokensApiDomain], ['VITE_SUPERTOKENS_WEBSITE_DOMAIN', superTokensWebsiteDomain], ['VITE_AUTH_API_BASE_URL', authApiBaseUrl], ]) { if (!url) continue if (isLoopbackHostname(url.hostname)) { pushFailure(bucket, `${label} still targets a loopback/local-development origin.`) } else if (!isHttpsUrl(url)) { pushFailure(bucket, `${label} uses HTTP on a non-loopback origin; use HTTPS before public launch.`) } } if ( superTokensApiDomain && authApiBaseUrl && normalizeTrimmed(superTokensApiDomain.origin) !== normalizeTrimmed(authApiBaseUrl.origin) ) { pushWarning(bucket, 'VITE_AUTH_API_BASE_URL differs from VITE_SUPERTOKENS_API_DOMAIN; verify both point at the same auth backend.') } if ( superTokensApiDomain && superTokensWebsiteDomain && superTokensApiDomain.origin !== superTokensWebsiteDomain.origin ) { pushWarning(bucket, 'Frontend auth API and website origins differ; same-origin public posture is the clean default.') } if (!normalizeTrimmed(frontendEnv.VITE_PADDLE_CHECKOUT_URL_STUDIO)) { pushWarning(bucket, 'VITE_PADDLE_CHECKOUT_URL_STUDIO is not set; Studio pricing will stay on the contact/support fallback.') } else { rejectPlaceholderValue(bucket, 'VITE_PADDLE_CHECKOUT_URL_STUDIO', frontendEnv.VITE_PADDLE_CHECKOUT_URL_STUDIO) } return { ...bucket, authApiOrigin: authApiBaseUrl?.origin || '', websiteOrigin: superTokensWebsiteDomain?.origin || '', } } function evaluateServerConfig(serverEnv, deploymentTier = 'launch') { const bucket = createBucket() const apiDomain = requireAbsoluteUrl(bucket, 'API_DOMAIN', serverEnv.API_DOMAIN) const websiteDomain = requireAbsoluteUrl(bucket, 'WEBSITE_DOMAIN', serverEnv.WEBSITE_DOMAIN) const superTokensCoreUri = requireAbsoluteUrl(bucket, 'SUPERTOKENS_CORE_URI', serverEnv.SUPERTOKENS_CORE_URI) const cookieSecure = normalizeTrimmed(serverEnv.COOKIE_SECURE).toLowerCase() === 'true' if (!cookieSecure) { pushFailure(bucket, 'COOKIE_SECURE must be true before public launch.') } if (!normalizeTrimmed(serverEnv.PADDLE_WEBHOOK_SECRET)) { if (deploymentTier === 'preview') { pushWarning(bucket, 'PADDLE_WEBHOOK_SECRET is not set; billing webhook handling will remain in preview posture until the live secret is configured.') } else { pushFailure(bucket, 'PADDLE_WEBHOOK_SECRET is missing.') } } else { rejectPlaceholderValue(bucket, 'PADDLE_WEBHOOK_SECRET', serverEnv.PADDLE_WEBHOOK_SECRET) } for (const [label, url] of [ ['API_DOMAIN', apiDomain], ['WEBSITE_DOMAIN', websiteDomain], ]) { if (!url) continue if (isLoopbackHostname(url.hostname)) { pushFailure(bucket, `${label} still targets a loopback/local-development origin.`) } else if (!isHttpsUrl(url)) { pushFailure(bucket, `${label} uses HTTP on a non-loopback origin; use HTTPS before public launch.`) } } if (superTokensCoreUri && isLoopbackHostname(superTokensCoreUri.hostname)) { pushWarning(bucket, 'SUPERTOKENS_CORE_URI still targets a loopback/local-development host.') } if ( apiDomain && websiteDomain && apiDomain.origin !== websiteDomain.origin ) { pushWarning(bucket, 'API_DOMAIN and WEBSITE_DOMAIN differ; same-origin public posture is the clean default.') } const serveStaticWebsite = normalizeTrimmed(serverEnv.SERVE_STATIC_WEBSITE).toLowerCase() const websiteDistPath = normalizeTrimmed(serverEnv.WEBSITE_DIST_PATH) || '../dist' const sameOriginPublicPosture = Boolean( apiDomain && websiteDomain && apiDomain.origin === websiteDomain.origin && !isLoopbackHostname(apiDomain.hostname) && !isLoopbackHostname(websiteDomain.hostname), ) if (sameOriginPublicPosture) { if (serveStaticWebsite === 'false' || serveStaticWebsite === '0' || serveStaticWebsite === 'no') { pushWarning(bucket, 'SERVE_STATIC_WEBSITE=false; ensure a separate same-origin web server serves the built website bundle.') } else if (serveStaticWebsite !== 'true' && serveStaticWebsite !== '1' && serveStaticWebsite !== 'yes') { pushWarning(bucket, `SERVE_STATIC_WEBSITE is not explicitly set; confirm ${websiteDistPath} is present for first-party same-origin serving or that an external same-origin web server serves the frontend.`) } } if ( Boolean(normalizeTrimmed(serverEnv.GITHUB_CLIENT_ID)) !== Boolean(normalizeTrimmed(serverEnv.GITHUB_CLIENT_SECRET)) ) { pushWarning(bucket, 'GitHub OAuth is only partially configured on the server.') } if ( Boolean(normalizeTrimmed(serverEnv.GOOGLE_CLIENT_ID)) !== Boolean(normalizeTrimmed(serverEnv.GOOGLE_CLIENT_SECRET)) ) { pushWarning(bucket, 'Google OAuth is only partially configured on the server.') } if ( !normalizeTrimmed(serverEnv.PADDLE_PRODUCT_PLAN_MAP) && !normalizeTrimmed(serverEnv.PADDLE_PRICE_PLAN_MAP) ) { pushWarning(bucket, 'Neither PADDLE_PRODUCT_PLAN_MAP nor PADDLE_PRICE_PLAN_MAP is configured; billing plan resolution will rely on webhook custom_data only.') } if (normalizeTrimmed(serverEnv.PADDLE_PRODUCT_PLAN_MAP)) { rejectPlaceholderValue(bucket, 'PADDLE_PRODUCT_PLAN_MAP', serverEnv.PADDLE_PRODUCT_PLAN_MAP) } if (normalizeTrimmed(serverEnv.PADDLE_PRICE_PLAN_MAP)) { rejectPlaceholderValue(bucket, 'PADDLE_PRICE_PLAN_MAP', serverEnv.PADDLE_PRICE_PLAN_MAP) } return { ...bucket, apiOrigin: apiDomain?.origin || '', websiteOrigin: websiteDomain?.origin || '', } } export function parseEnvFile(contents) { const values = {} for (const line of String(contents || '').split(/\r?\n/)) { const trimmed = line.trim() if (!trimmed || trimmed.startsWith('#')) { continue } const candidate = trimmed.startsWith('export ') ? trimmed.slice(7).trim() : trimmed const separatorIndex = candidate.indexOf('=') if (separatorIndex <= 0) { continue } const key = candidate.slice(0, separatorIndex).trim() const rawValue = candidate.slice(separatorIndex + 1) values[key] = stripOptionalQuotes(rawValue) } return values } export function loadEnvFile(filePath) { const absolutePath = path.resolve(filePath) if (!fs.existsSync(absolutePath)) { return { path: absolutePath, exists: false, values: {}, } } return { path: absolutePath, exists: true, values: parseEnvFile(fs.readFileSync(absolutePath, 'utf8')), } } export function deriveHealthBaseUrl({ explicitHealthUrl, frontendEnv, serverEnv }) { const explicit = normalizeTrimmed(explicitHealthUrl) if (explicit) { return explicit.replace(/\/$/, '') } const frontendAuthBase = normalizeTrimmed(frontendEnv.VITE_AUTH_API_BASE_URL) if (frontendAuthBase) { return frontendAuthBase.replace(/\/$/, '') } const serverApiDomain = normalizeTrimmed(serverEnv.API_DOMAIN) if (serverApiDomain) { return serverApiDomain.replace(/\/$/, '') } return '' } export async function fetchLiveAuthHealth(baseUrl, fetchImpl = fetch) { return fetchJsonEndpoint(baseUrl, '/api/auth/health', 'Live auth health endpoint', fetchImpl) } export async function fetchLiveReleaseManifest(baseUrl, fetchImpl = fetch) { return fetchJsonEndpoint(baseUrl, '/api/releases/manifest', 'Live release manifest endpoint', fetchImpl) } export async function fetchLiveWebsiteShell(baseUrl, fetchImpl = fetch) { const targetUrl = `${normalizeTrimmed(baseUrl).replace(/\/$/, '')}/` const response = await fetchImpl(targetUrl, { headers: { accept: 'text/html,application/xhtml+xml', }, }) const html = await response.text() const contentType = normalizeTrimmed(response.headers?.get?.('content-type') || '') if (!response.ok) { throw new Error(`Live website root failed with HTTP ${response.status}.${html ? ` Snippet: ${summarizeResponseBody(html)}` : ''}`) } if (!looksLikeHtmlResponse(contentType, html)) { throw new Error(`Live website root did not return HTML.${html ? ` Snippet: ${summarizeResponseBody(html)}` : ''}`) } return { title: extractHtmlTitle(html), hasShellMarker: html.includes('name="hypertwist-site-shell"') || html.includes("name='hypertwist-site-shell'"), hasRootMount: /id=["']root["']/i.test(html), placeholderDetected: detectPlaceholderRolloutPage(html), bodySnippet: summarizeResponseBody(html), } } export function buildRuntimeReadinessReport({ frontendEnv, serverEnv, liveHealth, liveReleaseManifest, liveWebsiteShell, liveHealthAttempted = false, liveReleaseManifestAttempted = false, liveWebsiteShellAttempted = false, frontendEnvPath = '', serverEnvPath = '', healthBaseUrl = '', deploymentTier = '', }) { const resolvedDeploymentTier = normalizeDeploymentTier( deploymentTier || frontendEnv.VITE_PUBLIC_DEPLOYMENT_TIER || serverEnv.DEPLOYMENT_TIER, 'launch', ) const frontend = evaluateFrontendConfig(frontendEnv, serverEnv, resolvedDeploymentTier) const server = evaluateServerConfig(serverEnv, resolvedDeploymentTier) const failures = [...frontend.failures, ...server.failures] const warnings = [...frontend.warnings, ...server.warnings] if (frontend.authApiOrigin && server.apiOrigin && frontend.authApiOrigin !== server.apiOrigin) { warnings.push('Frontend auth base URL and server API domain differ; verify they represent the same public auth backend.') } if (liveHealth) { if (liveHealth.supertokens?.ready !== true) { failures.push('Live auth health reports SuperTokens not ready.') } if (liveHealth.fallback?.active === true) { failures.push(`Live auth health reports fallback active${liveHealth.fallback?.reason ? ` (${liveHealth.fallback.reason})` : ''}.`) } if (liveHealth.runtime?.public_origin_ready !== true) { failures.push('Live auth health reports public auth origin not ready.') } if (liveHealth.runtime?.mode !== 'public' && liveHealth.runtime?.mode !== 'mixed') { failures.push(`Live auth health reports runtime mode '${liveHealth.runtime?.mode || 'unknown'}' instead of 'public' or 'mixed'.`) } for (const message of liveHealth.runtime?.errors || []) { failures.push(`Live runtime error: ${message}`) } for (const message of liveHealth.runtime?.warnings || []) { warnings.push(`Live runtime warning: ${message}`) } if (liveHealth.billing?.webhookSecretConfigured !== true) { if (resolvedDeploymentTier === 'preview') { warnings.push('Live auth health reports Paddle webhook secret missing; billing webhook handling remains in preview posture.') } else { failures.push('Live auth health reports Paddle webhook secret missing.') } } if (liveHealth.billing?.productPlanMapConfigured !== true && liveHealth.billing?.pricePlanMapConfigured !== true) { warnings.push('Live auth health reports no Paddle product/price map configured; custom_data-based resolution remains the only billing-plan path.') } } else if (!liveHealthAttempted) { warnings.push('Live auth health was not checked; runtime readiness was evaluated from env posture only.') } if (liveReleaseManifest) { if (liveReleaseManifest.ok !== true) { failures.push('Live release manifest did not report ok=true.') } if (!Array.isArray(liveReleaseManifest.manifest?.platforms)) { failures.push('Live release manifest did not return a platforms array.') } else { const windowsPlatform = liveReleaseManifest.manifest.platforms.find((platform) => platform?.platform_key === 'windows') if (!windowsPlatform) { failures.push('Live release manifest is missing the Windows platform entry.') } if (liveReleaseManifest.manifest.platforms.some((platform) => normalizeTrimmed(platform?.download_url))) { failures.push('Live public release manifest exposes a raw download URL to anonymous viewers.') } } if (liveReleaseManifest.manifest?.viewer?.authenticated !== false || liveReleaseManifest.manifest?.viewer?.canDownload !== false) { failures.push('Live public release manifest viewer posture is not anonymous/non-downloadable.') } appendLiveReleaseManifestDriftChecks({ failures, frontendEnv, serverEnv, liveReleaseManifest, }) } else if (!liveReleaseManifestAttempted) { warnings.push('Live release manifest was not checked; public download-lane runtime posture was evaluated from env posture only.') } if (liveWebsiteShell) { if (liveWebsiteShell.placeholderDetected) { failures.push('Live website root still serves the placeholder rollout page instead of the first-party HyperTwist shell.') } if (!liveWebsiteShell.hasShellMarker) { failures.push('Live website root is missing the first-party HyperTwist shell marker.') } if (!liveWebsiteShell.hasRootMount) { failures.push('Live website root is missing the expected #root app mount.') } } else if (!liveWebsiteShellAttempted) { warnings.push('Live website shell was not checked; placeholder-versus-real-site posture was not verified.') } return { ok: failures.length === 0, failures, warnings, frontendEnvPath, serverEnvPath, healthBaseUrl, deploymentTier: resolvedDeploymentTier, liveHealthChecked: Boolean(liveHealth), liveReleaseManifestChecked: Boolean(liveReleaseManifest), liveWebsiteShellChecked: Boolean(liveWebsiteShell), } } export function formatRuntimeReadinessReport(report) { const lines = [] lines.push(`Runtime readiness: ${report.ok ? 'PASS' : 'FAIL'}`) if (report.frontendEnvPath) { lines.push(`Frontend env: ${report.frontendEnvPath}`) } if (report.serverEnvPath) { lines.push(`Server env: ${report.serverEnvPath}`) } if (report.healthBaseUrl) { lines.push(`Health base URL: ${report.healthBaseUrl}`) } lines.push(`Deployment tier: ${report.deploymentTier || 'launch'}`) lines.push(`Live health checked: ${report.liveHealthChecked ? 'yes' : 'no'}`) lines.push(`Live release manifest checked: ${report.liveReleaseManifestChecked ? 'yes' : 'no'}`) lines.push(`Live website shell checked: ${report.liveWebsiteShellChecked ? 'yes' : 'no'}`) if (report.failures.length > 0) { lines.push('Failures:') for (const item of report.failures) { lines.push(`- ${item}`) } } if (report.warnings.length > 0) { lines.push('Warnings:') for (const item of report.warnings) { lines.push(`- ${item}`) } } if (report.failures.length === 0 && report.warnings.length === 0) { lines.push('No failures or warnings.') } return `${lines.join('\n')}\n` }