Harden HyperTwist launch status blocker details
This commit is contained in:
parent
f977546c52
commit
6da96771ad
5 changed files with 366 additions and 2 deletions
|
|
@ -2215,3 +2215,56 @@ Latest same-family responsive public-route expansion follow-up on `2026-06-29`:
|
|||
desktop handoff while the package-validated simulator remains desktop-first
|
||||
- the native XR/controller lane still remains a deliberate desktop-hosted
|
||||
`No-Go` rather than something this refresh reclassified as complete
|
||||
|
||||
## Latest responsive public/protected proof plus live preview-readiness rerun (`2026-06-29`)
|
||||
|
||||
- the next bounded continuation stayed inside the same production-hardening and
|
||||
public/manual authority lane instead of widening product scope again
|
||||
- the live same-origin preview lane was rechecked directly through:
|
||||
- `npm --prefix website run check:runtime-readiness:preview-live`
|
||||
- result:
|
||||
- `Runtime readiness: PASS`
|
||||
- live `/health` check green
|
||||
- live anonymous release-manifest check green
|
||||
- live first-party website-shell marker check green
|
||||
- the current truthful live warnings remained explicit during that check:
|
||||
- Windows download URL still absent in preview posture
|
||||
- operator and studio Paddle checkout URLs still absent in preview posture
|
||||
- Paddle webhook secret still absent in preview posture
|
||||
- `SUPERTOKENS_CORE_URI` still targets a loopback/local-development host
|
||||
- billing plan resolution still relies on webhook `custom_data` because no
|
||||
product/price map is configured yet
|
||||
- the broader owned web-surface umbrella then reran green with responsive
|
||||
browser proof enabled:
|
||||
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||
- focused website route/auth/release validation:
|
||||
- `14` files passed
|
||||
- `81` tests passed
|
||||
- deployment/readiness tooling validation:
|
||||
- `3` files passed
|
||||
- `30` tests passed
|
||||
- responsive public-route Playwright proof:
|
||||
- `34` tests passed
|
||||
- responsive protected-route Playwright proof:
|
||||
- `12` tests passed
|
||||
- `website/server` validation:
|
||||
- `10` files passed
|
||||
- `36` tests passed
|
||||
- website plus `Content/Browser` production builds passed
|
||||
- `website/` and `Content/Browser/` production audits stayed at
|
||||
`found 0 vulnerabilities`
|
||||
- `website/server/` again retained only the already-documented upstream
|
||||
`supertokens-node -> nodemailer` residual advisory
|
||||
- the public launch-status surface now also renders the concrete live preview
|
||||
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
|
||||
- current truthful reading after this continuation:
|
||||
- no fresh browser/public/product regression surfaced under the stronger
|
||||
responsive and live-preview proof
|
||||
- the public/protected website lane is now backed by both unit/integration
|
||||
coverage and renewed practical mobile/tablet route proof
|
||||
- the live `hypertwist.app` surface is healthy and first-party, but it still
|
||||
remains a preview deployment rather than full public launch because the
|
||||
checkout, Windows download, billing-secret, and non-loopback auth-core
|
||||
launch conditions are not yet satisfied
|
||||
|
|
|
|||
|
|
@ -352,6 +352,53 @@ Latest shared-auth ORCID frontend-closure follow-up on `2026-06-29`:
|
|||
- website focused route/auth/release suite: `14` files, `81` tests passed
|
||||
- website/server suite: `10` files, `36` tests passed
|
||||
|
||||
Latest responsive proof and live preview-readiness revalidation later on
|
||||
`2026-06-29`:
|
||||
|
||||
- the owned browser/public/product lane was then rechecked under the broader
|
||||
responsive umbrella instead of relying only on route-unit coverage
|
||||
- `npm --prefix website run check:runtime-readiness:preview-live` passed again
|
||||
against `https://hypertwist.app`, confirming:
|
||||
- live `/health` check green
|
||||
- live anonymous release-manifest check green
|
||||
- live first-party website-shell marker check green
|
||||
- current truthful preview posture remained explicit during that live check:
|
||||
- Windows download URL still missing in preview env
|
||||
- operator and studio Paddle checkout URLs still missing in preview env
|
||||
- Paddle webhook secret still missing in preview env
|
||||
- `SUPERTOKENS_CORE_URI` still points at a loopback/local-development host
|
||||
- billing plan maps still rely on webhook `custom_data`
|
||||
- the broader owned web-surface umbrella then reran green with responsive
|
||||
browser proof enabled:
|
||||
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||
- focused website route/auth/release validation:
|
||||
- `14` files passed
|
||||
- `81` tests passed
|
||||
- deployment/readiness tooling validation:
|
||||
- `3` files passed
|
||||
- `30` tests passed
|
||||
- responsive public-route Playwright proof:
|
||||
- `34` tests passed
|
||||
- responsive protected-route Playwright proof:
|
||||
- `12` tests passed
|
||||
- `website/server` validation:
|
||||
- `10` files passed
|
||||
- `36` tests passed
|
||||
- website plus `Content/Browser` production builds passed
|
||||
- `website/` and `Content/Browser/` production audits stayed at
|
||||
`found 0 vulnerabilities`
|
||||
- `website/server/` again retained only the already-documented upstream
|
||||
`supertokens-node -> nodemailer` residual advisory
|
||||
- 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
|
||||
- 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
|
||||
- the live site is healthy and real, but it still honestly remains a preview
|
||||
deployment until checkout, Windows download, billing secret, and
|
||||
non-loopback shared-auth core posture are configured
|
||||
|
||||
Latest exact-source proof and owned validation refresh later on `2026-06-29`:
|
||||
|
||||
- the public/browser lane was then re-synced against the refreshed exact-source
|
||||
|
|
|
|||
203
website/src/__tests__/PublicLaunchStatus.test.tsx
Normal file
203
website/src/__tests__/PublicLaunchStatus.test.tsx
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
import { cleanup, render, screen, waitFor } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { MemoryRouter } from 'react-router-dom'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ROUTER_FUTURE_FLAGS } from '../router/router-future'
|
||||
|
||||
const mockGetAuthHealth = vi.fn()
|
||||
|
||||
vi.mock('../auth/auth-api', () => ({
|
||||
getAuthHealth: (...args: unknown[]) => mockGetAuthHealth(...args),
|
||||
}))
|
||||
|
||||
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
|
||||
|
||||
function renderComponent() {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<MemoryRouter future={ROUTER_FUTURE_FLAGS}>
|
||||
<PublicLaunchStatus />
|
||||
</MemoryRouter>
|
||||
</QueryClientProvider>,
|
||||
)
|
||||
}
|
||||
|
||||
describe('PublicLaunchStatus', () => {
|
||||
beforeEach(() => {
|
||||
cleanup()
|
||||
mockGetAuthHealth.mockReset()
|
||||
})
|
||||
|
||||
it('surfaces concrete live preview blockers instead of only generic missing labels', async () => {
|
||||
mockGetAuthHealth.mockResolvedValue({
|
||||
ok: true,
|
||||
service: 'hypertwist-auth-server',
|
||||
supertokens: {
|
||||
configured: true,
|
||||
reachable: true,
|
||||
ready: false,
|
||||
apiVersion: '5.4',
|
||||
error: null,
|
||||
oauth: {
|
||||
github: true,
|
||||
google: false,
|
||||
orcid: true,
|
||||
},
|
||||
},
|
||||
fallback: {
|
||||
enabled: true,
|
||||
active: false,
|
||||
reason: null,
|
||||
},
|
||||
billing: {
|
||||
statePath: '/tmp/hypertwist-billing.json',
|
||||
processedEventCount: 0,
|
||||
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,
|
||||
macosDownloadConfigured: false,
|
||||
linuxDownloadConfigured: 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'],
|
||||
targets: {
|
||||
operatorCheckoutTarget: null,
|
||||
studioCheckoutTarget: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
renderComponent()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText(/Checking live launch-readiness posture/i)).toBeNull()
|
||||
})
|
||||
|
||||
expect(screen.getByText('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('omits the blocker section when the live launch posture is ready and warning-free', async () => {
|
||||
mockGetAuthHealth.mockResolvedValue({
|
||||
ok: true,
|
||||
service: 'hypertwist-auth-server',
|
||||
supertokens: {
|
||||
configured: true,
|
||||
reachable: true,
|
||||
ready: true,
|
||||
apiVersion: '5.4',
|
||||
error: null,
|
||||
oauth: {
|
||||
github: true,
|
||||
google: true,
|
||||
orcid: true,
|
||||
},
|
||||
},
|
||||
fallback: {
|
||||
enabled: true,
|
||||
active: false,
|
||||
reason: null,
|
||||
},
|
||||
billing: {
|
||||
statePath: '/tmp/hypertwist-billing.json',
|
||||
processedEventCount: 4,
|
||||
pricePlanMapConfigured: true,
|
||||
productPlanMapConfigured: true,
|
||||
webhookSecretConfigured: true,
|
||||
},
|
||||
runtime: {
|
||||
mode: 'public',
|
||||
public_origin_ready: true,
|
||||
cookie_secure: true,
|
||||
api_domain: 'https://hypertwist.app',
|
||||
website_domain: 'https://hypertwist.app',
|
||||
warnings: [],
|
||||
errors: [],
|
||||
},
|
||||
launch: {
|
||||
posture: 'launch-ready',
|
||||
ready: true,
|
||||
readiness: {
|
||||
windowsDownloadConfigured: true,
|
||||
macosDownloadConfigured: false,
|
||||
linuxDownloadConfigured: false,
|
||||
operatorCheckoutConfigured: true,
|
||||
studioCheckoutConfigured: true,
|
||||
mplSourceConfigured: true,
|
||||
openSourceRepoConfigured: true,
|
||||
billingProductPlanMapConfigured: true,
|
||||
billingPricePlanMapConfigured: true,
|
||||
billingWebhookSecretConfigured: true,
|
||||
publicAuthRuntimeReady: true,
|
||||
},
|
||||
checklist: [
|
||||
{
|
||||
id: 'windows-download',
|
||||
label: 'Windows release authority',
|
||||
configured: true,
|
||||
requiredForPublicLaunch: true,
|
||||
},
|
||||
],
|
||||
missingLabels: [],
|
||||
targets: {
|
||||
operatorCheckoutTarget: 'https://buy.paddle.com/operator',
|
||||
studioCheckoutTarget: 'https://buy.paddle.com/studio',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
renderComponent()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText(/Checking live launch-readiness posture/i)).toBeNull()
|
||||
})
|
||||
|
||||
expect(screen.queryByText('Current preview blockers from the live auth runtime')).toBeNull()
|
||||
expect(screen.queryByText('Live runtime notes')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
|
@ -1,11 +1,53 @@
|
|||
import { useMemo } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { getAuthHealth } from '../../auth/auth-api'
|
||||
import { getAuthHealth, type AuthHealthPayload } from '../../auth/auth-api'
|
||||
import { 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'],
|
||||
|
|
@ -28,10 +70,14 @@ function usePublicLaunchStatus() {
|
|||
|
||||
return labels
|
||||
}, [authHealthQuery.isError, authHealthQuery.isLoading, launchStatus.missingLabels])
|
||||
const liveBlockerDetails = useMemo(() => (
|
||||
buildLiveLaunchBlockerDetails(authHealthQuery.data, launchStatus)
|
||||
), [authHealthQuery.data, launchStatus])
|
||||
|
||||
return {
|
||||
authHealthQuery,
|
||||
checklist,
|
||||
liveBlockerDetails,
|
||||
missingLabels,
|
||||
ready,
|
||||
launchStatus,
|
||||
|
|
@ -71,7 +117,7 @@ export function PublicLaunchStatus({
|
|||
}: {
|
||||
title?: string
|
||||
}) {
|
||||
const { authHealthQuery, checklist, launchStatus, missingLabels, ready } = usePublicLaunchStatus()
|
||||
const { authHealthQuery, checklist, launchStatus, liveBlockerDetails, missingLabels, ready } = usePublicLaunchStatus()
|
||||
|
||||
return (
|
||||
<article className="callout">
|
||||
|
|
@ -95,6 +141,16 @@ export function PublicLaunchStatus({
|
|||
<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>{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}
|
||||
{authHealthQuery.isLoading ? (
|
||||
<p>Checking live launch-readiness posture from the deployed auth server.</p>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -1036,6 +1036,11 @@ export const publicManualRouteAtlasCards = [
|
|||
] as const
|
||||
|
||||
export const changelogEntries = [
|
||||
{
|
||||
date: 'June 29, 2026',
|
||||
title: 'Responsive route proof and live preview-readiness were revalidated again',
|
||||
details: 'The owned web-surface umbrella was rerun with responsive Playwright coverage, keeping all major public and protected routes clean on mobile and tablet while the same-origin preview-readiness command also passed again against `https://hypertwist.app`. The current launch truth remains disciplined: the site is live and healthy in preview posture, while Windows download, Paddle checkout, webhook-secret, and loopback SuperTokens-core warnings still remain explicit instead of being blurred into a false public-launch claim.',
|
||||
},
|
||||
{
|
||||
date: 'June 29, 2026',
|
||||
title: 'Owned validation and refactor-tool refresh stayed green on the refreshed package proof',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue