Mirror launch blockers across protected HyperTwist surfaces

This commit is contained in:
axiomlogicnexus 2026-06-29 17:10:31 +00:00
parent 6da96771ad
commit fa71d0728f
8 changed files with 161 additions and 46 deletions

View file

@ -2259,6 +2259,10 @@ Latest same-family responsive public-route expansion follow-up on `2026-06-29`:
blockers coming back from auth-health and billing/runtime posture, so the
public site no longer compresses that state down to generic missing-label
prose alone
- the same concrete live-blocker detail now also appears inside the protected
dashboard launch-readiness panel and the signed-in `/app/launch-status`
route, so operator follow-through does not depend on cross-reading the
public page or the readiness CLI to understand the remaining preview gap
- current truthful reading after this continuation:
- no fresh browser/public/product regression surfaced under the stronger
responsive and live-preview proof

View file

@ -392,6 +392,9 @@ Latest responsive proof and live preview-readiness revalidation later on
- the public launch-status surface now also names the concrete live preview
blockers from auth-health and billing/runtime posture instead of reducing
the whole state to generic missing-label prose
- the protected dashboard and protected `/app/launch-status` route now mirror
that same concrete blocker detail too, so signed-in operators no longer have
to infer the real preview gap only from the public page or the readiness CLI
- current truthful reading after that rerun:
- the public and protected browser surfaces now have fresh practical
mobile/tablet proof rather than only desktop/unit confidence

View file

@ -195,6 +195,13 @@ describe('DashboardOverviewPage', () => {
expect(screen.getByText('Billing price-plan map: missing')).toBeTruthy()
expect(screen.getByText('Paddle webhook secret: missing')).toBeTruthy()
expect(screen.getByText('Public auth runtime posture: local-or-mixed')).toBeTruthy()
expect(screen.getByText('Current preview blockers from the live auth runtime')).toBeTruthy()
expect(screen.getByText('Shared browser-auth runtime is not yet production-ready on the live deployment.')).toBeTruthy()
expect(screen.getByText('Paddle webhook secret is not configured yet.')).toBeTruthy()
expect(screen.getByText('Billing product-plan map is not configured yet.')).toBeTruthy()
expect(screen.getByText('Billing price-plan map is not configured yet.')).toBeTruthy()
expect(screen.getByText('Runtime error: API_DOMAIN still points at localhost')).toBeTruthy()
expect(screen.getByText('Runtime warning: COOKIE_SECURE disabled')).toBeTruthy()
expect(screen.getByText('Current release action')).toBeTruthy()
expect(screen.getByText('Desktop access is visible, but no packaged target is published yet.')).toBeTruthy()
expect(screen.getAllByRole('link', { name: 'Review release notes' })[0]?.getAttribute('href')).toBe('/changelog')

View file

@ -300,6 +300,84 @@ describe('protected app pages', () => {
expect(screen.getByText(/Public launch is not fully configured yet: preview-tier launch gate\./i)).toBeTruthy()
})
it('surfaces concrete live preview blockers on the protected launch route', async () => {
mockGetAuthHealth.mockResolvedValue({
ok: true,
service: 'hypertwist-auth-server',
supertokens: {
configured: true,
reachable: true,
ready: false,
apiVersion: '5.0',
oauth: {
github: false,
google: false,
},
},
fallback: {
enabled: true,
active: false,
reason: null,
},
billing: {
statePath: '/tmp/hypertwist-billing.json',
processedEventCount: 1,
pricePlanMapConfigured: false,
productPlanMapConfigured: false,
webhookSecretConfigured: false,
},
runtime: {
mode: 'mixed',
public_origin_ready: true,
cookie_secure: true,
api_domain: 'https://hypertwist.app',
website_domain: 'https://hypertwist.app',
warnings: ['SUPERTOKENS_CORE_URI still targets a loopback/local-development host.'],
errors: [],
},
launch: {
posture: 'preview',
ready: false,
readiness: {
windowsDownloadConfigured: false,
operatorCheckoutConfigured: false,
studioCheckoutConfigured: false,
mplSourceConfigured: true,
openSourceRepoConfigured: true,
billingProductPlanMapConfigured: false,
billingPricePlanMapConfigured: false,
billingWebhookSecretConfigured: false,
publicAuthRuntimeReady: false,
},
checklist: [
{
id: 'windows-download',
label: 'Windows release authority',
configured: false,
requiredForPublicLaunch: true,
},
],
missingLabels: ['windows release authority', 'operator checkout URL', 'studio checkout URL'],
targets: {
operatorCheckoutTarget: null,
studioCheckoutTarget: null,
},
},
})
renderPage(<ProtectedLaunchStatusPage />, '/app/launch-status')
expect(await screen.findByText('Current preview blockers from the live auth runtime')).toBeTruthy()
expect(screen.getByText('Windows release lane is not configured on the live preview deployment yet.')).toBeTruthy()
expect(screen.getByText('Operator checkout is still on support fallback in the live preview deployment.')).toBeTruthy()
expect(screen.getByText('Studio checkout is still on support fallback in the live preview deployment.')).toBeTruthy()
expect(screen.getByText('Shared browser-auth runtime is not yet production-ready on the live deployment.')).toBeTruthy()
expect(screen.getByText('Paddle webhook secret is not configured yet.')).toBeTruthy()
expect(screen.getByText('Billing product-plan map is not configured yet.')).toBeTruthy()
expect(screen.getByText('Billing price-plan map is not configured yet.')).toBeTruthy()
expect(screen.getByText('Runtime warning: SUPERTOKENS_CORE_URI still targets a loopback/local-development host.')).toBeTruthy()
})
it('keeps the protected download center aligned with packaged proof, notices, and escalation guidance', async () => {
renderPage(<DownloadCenterPage />, '/app/downloads?platform=windows')

View file

@ -1,53 +1,11 @@
import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Link } from 'react-router-dom'
import { getAuthHealth, type AuthHealthPayload } from '../../auth/auth-api'
import { resolvePublicLaunchStatusSummary } from '../../public-launch'
import { getAuthHealth } from '../../auth/auth-api'
import { buildLiveLaunchBlockerDetails, resolvePublicLaunchStatusSummary } from '../../public-launch'
import { launchReadiness } from '../../site-config'
import { buildProtectedDownloadPath } from '../../site-routes'
function buildLiveLaunchBlockerDetails(
authHealth: AuthHealthPayload | undefined,
launchStatus: ReturnType<typeof resolvePublicLaunchStatusSummary>,
) {
if (!authHealth) {
return []
}
const details = new Set<string>()
if (!launchStatus.readiness.windowsDownloadConfigured) {
details.add('Windows release lane is not configured on the live preview deployment yet.')
}
if (!launchStatus.readiness.operatorCheckoutConfigured) {
details.add('Operator checkout is still on support fallback in the live preview deployment.')
}
if (!launchStatus.readiness.studioCheckoutConfigured) {
details.add('Studio checkout is still on support fallback in the live preview deployment.')
}
if (!launchStatus.readiness.publicAuthRuntimeReady) {
details.add('Shared browser-auth runtime is not yet production-ready on the live deployment.')
}
if (!authHealth.billing.webhookSecretConfigured) {
details.add('Paddle webhook secret is not configured yet.')
}
if (!authHealth.billing.productPlanMapConfigured) {
details.add('Billing product-plan map is not configured yet.')
}
if (!authHealth.billing.pricePlanMapConfigured) {
details.add('Billing price-plan map is not configured yet.')
}
authHealth.runtime.errors.forEach((item) => {
details.add(`Runtime error: ${item}`)
})
authHealth.runtime.warnings.forEach((item) => {
details.add(`Runtime warning: ${item}`)
})
return Array.from(details)
}
function usePublicLaunchStatus() {
const authHealthQuery = useQuery({
queryKey: ['auth-health', 'public-launch-status'],

View file

@ -1,13 +1,13 @@
import { useEffect, useMemo } from 'react'
import { useMutation, useQuery } from '@tanstack/react-query'
import { Link, useSearchParams } from 'react-router-dom'
import { buildAuthApiBaseUrls, createDesktopLinkToken, getAuthHealth, getReleaseManifest } from '../auth/auth-api'
import { buildAuthApiBaseUrls, createDesktopLinkToken, getAuthHealth, getReleaseManifest, type AuthHealthPayload } from '../auth/auth-api'
import { usePlatformAuth, type PlatformUser } from '../auth/platform-auth'
import { SiteMetadata } from '../components/seo/SiteMetadata'
import { OperationalStatusCallout } from '../components/ui/OperationalStatusCallout'
import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix'
import { ReleaseValidationSummary } from '../components/ui/ReleaseValidationSummary'
import { resolvePublicLaunchStatusSummary } from '../public-launch'
import { buildLiveLaunchBlockerDetails, resolvePublicLaunchStatusSummary } from '../public-launch'
import { downloadTargets, launchReadiness, mplSourceUrl, openSourceRepoUrl, publicDocsUrl, releaseNotesUrl } from '../site-config'
import { buildReleaseMetadataItems, resolveReleaseManifestView, type ReleaseManifestView } from '../release-manifest'
import {
@ -451,6 +451,7 @@ function ProtectedLaunchReadinessPanel({
title,
kicker,
description,
authHealth,
launchStatus,
releaseManifestQuery,
actions = [],
@ -458,6 +459,7 @@ function ProtectedLaunchReadinessPanel({
title: string
kicker: string
description?: string
authHealth?: AuthHealthPayload | null
launchStatus: ReturnType<typeof resolvePublicLaunchStatusSummary>
releaseManifestQuery: {
isLoading: boolean
@ -466,6 +468,10 @@ function ProtectedLaunchReadinessPanel({
actions?: readonly ProtectedLaunchReadinessAction[]
}) {
const launchReadinessIssues = launchStatus.missingLabels
const liveBlockerDetails = useMemo(
() => buildLiveLaunchBlockerDetails(authHealth, launchStatus),
[authHealth, launchStatus],
)
return (
<Panel title={title} kicker={kicker}>
@ -484,6 +490,16 @@ function ProtectedLaunchReadinessPanel({
<li>Operator checkout target: {launchStatus.targets.operatorCheckoutTarget || 'support fallback active'}</li>
<li>Studio checkout target: {launchStatus.targets.studioCheckoutTarget || 'support fallback active'}</li>
</ul>
{liveBlockerDetails.length > 0 ? (
<div className="callout top-gap">
<p>{launchStatus.ready ? 'Live runtime notes' : 'Current preview blockers from the live auth runtime'}</p>
<ul className="list">
{liveBlockerDetails.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
) : null}
{releaseManifestQuery.isLoading ? (
<p>Refreshing release-manifest download readiness from the auth server.</p>
) : null}
@ -1316,6 +1332,7 @@ export function DashboardOverviewPage() {
<ProtectedLaunchReadinessPanel
title="Launch readiness"
kicker="Public release configuration"
authHealth={healthQuery.data}
launchStatus={launchStatus}
releaseManifestQuery={releaseManifestQuery}
actions={[
@ -1416,6 +1433,7 @@ export function ProtectedLaunchStatusPage() {
title="Protected launch status"
kicker="Signed-in rollout authority"
description="This signed-in route keeps the live launch checklist, current targets, and rollout blockers in one operator-facing surface instead of leaving launch authority distributed across the dashboard and public pages."
authHealth={healthQuery.data}
launchStatus={launchStatus}
releaseManifestQuery={releaseManifestQuery}
actions={[

View file

@ -83,6 +83,48 @@ export function resolvePublicLaunchStatusSummary(
})
}
export function buildLiveLaunchBlockerDetails(
authHealth: AuthHealthPayload | null | undefined,
launchStatus: PublicLaunchStatusSummary,
) {
if (!authHealth) {
return []
}
const details = new Set<string>()
if (!launchStatus.readiness.windowsDownloadConfigured) {
details.add('Windows release lane is not configured on the live preview deployment yet.')
}
if (!launchStatus.readiness.operatorCheckoutConfigured) {
details.add('Operator checkout is still on support fallback in the live preview deployment.')
}
if (!launchStatus.readiness.studioCheckoutConfigured) {
details.add('Studio checkout is still on support fallback in the live preview deployment.')
}
if (!launchStatus.readiness.publicAuthRuntimeReady) {
details.add('Shared browser-auth runtime is not yet production-ready on the live deployment.')
}
if (!authHealth.billing.webhookSecretConfigured) {
details.add('Paddle webhook secret is not configured yet.')
}
if (!authHealth.billing.productPlanMapConfigured) {
details.add('Billing product-plan map is not configured yet.')
}
if (!authHealth.billing.pricePlanMapConfigured) {
details.add('Billing price-plan map is not configured yet.')
}
authHealth.runtime.errors.forEach((item) => {
details.add(`Runtime error: ${item}`)
})
authHealth.runtime.warnings.forEach((item) => {
details.add(`Runtime warning: ${item}`)
})
return Array.from(details)
}
export {
buildPublicLaunchStatusSummary,
normalizePublicLaunchReadiness,

View file

@ -1036,6 +1036,11 @@ export const publicManualRouteAtlasCards = [
] as const
export const changelogEntries = [
{
date: 'June 29, 2026',
title: 'Protected launch surfaces now name the concrete live preview blockers too',
details: 'The signed-in dashboard and protected `/app/launch-status` lane now mirror the same concrete live blocker details already shown on the public launch surface. Instead of only generic missing-label prose, signed-in operators now see whether Windows release publication, operator/studio checkout, webhook secret, billing plan maps, shared-auth runtime readiness, or live runtime warnings are the actual remaining preview blockers.',
},
{
date: 'June 29, 2026',
title: 'Responsive route proof and live preview-readiness were revalidated again',