Add protected launch status route

This commit is contained in:
axiomlogicnexus 2026-06-27 23:41:35 +00:00
parent d5f800de65
commit af07f720ff
12 changed files with 381 additions and 47 deletions

View file

@ -128,6 +128,12 @@ The protected dashboard now also has a first-party launch-readiness panel for:
- backend webhook-secret and billing-map configuration posture
- public auth runtime posture, cookie-hardening posture, and local-vs-public runtime diagnostics
The next same-family protected-shell continuation then widened that signed-in
launch-truth lane into a dedicated `/app/launch-status` route so rollout
blockers, release action, packaged desktop proof, notices references, and
signed-in next steps no longer collapse back to a single dashboard panel after
auth succeeds.
The adjacent protected account route now also mirrors that same signed-in
auth/session-authority truth instead of reducing the account lane to a thinner
identity-and-billing shell than the main protected dashboard.
@ -292,6 +298,10 @@ Current behavior:
- the protected dashboard launch-readiness panel and the public
preview-versus-launch callouts now also consume manifest-backed Windows
download truth instead of relying only on static frontend config
- the dedicated protected `/app/launch-status` route now consumes that same
manifest-backed Windows download truth too, so signed-in rollout review
stays aligned with both the public authority page and the protected release
action surface
- the same public launch-status lane now also checks live auth-health webhook
and public-origin readiness posture before presenting the site as launch-ready
- the runtime-readiness verifier now accepts server-backed release-manifest

View file

@ -1053,6 +1053,10 @@ Current audit note:
preview-versus-launch posture through a dedicated public `/launch-status`
route, so rollout blockers, release references, support lanes, and packaged
proof no longer have to be reconstructed from pricing plus scattered callouts
- the adjacent protected-shell parity continuation then mirrored that same
rollout truth after sign-in through a dedicated `/app/launch-status` route,
so the signed-in browser lane no longer reduces launch authority back to a
single dashboard panel once account context is present
- this keeps the public manual professional without inventing browser
simulator parity or widening the native XR branch
- focused validation for that continuation stayed green under:

File diff suppressed because one or more lines are too long

View file

@ -7,14 +7,14 @@ First-party `hypertwist.app` surface for HyperTwist:
- dedicated public `/launch-status` route for the canonical preview-versus-launch rollout checklist
- public feature-atlas route for current capability and boundary truth
- browser-facing operator/account dashboard
- protected browser-access, account, and notices routes backed by live auth-health and release-manifest authority
- protected launch-status, browser-access, account, and notices routes backed by live auth-health and release-manifest authority
- shared SuperTokens auth posture reused from the FamiliarOS and ScriptoriumAI website lane
- route-aware SuperTokens wrapping so public brochure routes do not pay for auth chrome unnecessarily while `/app`, `/login`, `/register`, `/auth/*`, and stored-session continuity still do
- FamiliarOS-style first-party auth-shell backdrop for login/register/auth callback posture, including first-paint HTML fallback plus route-synced runtime ownership
- desktop download posture and desktop-link handshake endpoints
- server-backed release-manifest authority shared by public and protected download surfaces
- Paddle-ready pricing/check-out wiring
- dashboard-side launch-readiness surface for download, checkout, auth, and notice configuration
- dashboard-side plus dedicated protected launch-status surfaces for download, checkout, auth, and notice configuration
- public launch-status callouts across pricing, download, and notices surfaces
- route-aware metadata, canonical, Open Graph, Twitter-card, and protected-route noindex posture for the live `hypertwist.app` surface
- first-party `robots.txt` plus `sitemap.xml` for the public crawlable route set while keeping `/app`, `/login`, and `/register` out of crawler posture
@ -84,6 +84,9 @@ manual:
- the same launch-authority story is now also anchored at a dedicated public
`/launch-status` route so preview-versus-launch truth, rollout blockers,
packaged proof, and release references have one canonical authority surface
- the protected operator shell now also mirrors that same launch-authority
posture on a dedicated signed-in `/app/launch-status` route, so rollout
truth no longer collapses back down to a single dashboard panel after sign-in
- the protected app shell now also carries richer operator-facing browser
boundary, account, entitlement, and notices guidance instead of treating
those routes as thin placeholders beside the main dashboard
@ -444,7 +447,7 @@ The focused frontend test coverage now also pins:
- platform-preserving `/download -> /app/downloads?platform=...` continuation plus requested-target surfacing inside the protected release lane
- support-topic fallback routing for pricing and launch-readiness actions when live checkout is not configured yet
- protected-route loading/redirect behavior plus auth-aware marketing/app shell actions
- real `AppRouteTree` smoke coverage for `/`, `/features`, `/pricing`, `/download`, `/login`, `/app`, and `/app/downloads`
- real `AppRouteTree` smoke coverage for `/`, `/features`, `/pricing`, `/download`, `/login`, `/app`, `/app/launch-status`, and `/app/downloads`
- top-level `App` bootstrap coverage for unknown-route redirect and SuperTokens wrapper on/off posture
- login/register unhappy-path coverage for returned form errors, auth-runtime warning callouts, and OAuth-button visibility/invocation
- dashboard launch-readiness plus desktop-link verify-url behavior

View file

@ -202,6 +202,11 @@ describe('DashboardOverviewPage', () => {
expect(screen.getByText('Signed-in help lanes')).toBeTruthy()
expect(screen.getByText('Protected browser-versus-desktop reality')).toBeTruthy()
expect(screen.getByText('Current input, XR, and settings truth')).toBeTruthy()
expect(
screen
.getAllByRole('link', { name: 'Open protected launch status' })
.some((link) => link.getAttribute('href') === '/app/launch-status'),
).toBe(true)
expect(screen.getByRole('link', { name: 'Open account' }).getAttribute('href')).toBe('/app/account')
expect(screen.getAllByRole('link', { name: 'Open browser access' }).every((link) => link.getAttribute('href') === '/app/browser-access')).toBe(true)
expect(screen.getAllByRole('link', { name: 'Open notices' }).length).toBeGreaterThan(0)

View file

@ -348,6 +348,75 @@ describe('AppRouteTree', () => {
expect(screen.getByText('Windows')).toBeTruthy()
})
it('renders the protected launch-status route through the real route tree when authenticated', async () => {
mockUsePlatformAuth.mockReturnValue({
isAuthenticated: true,
isLoading: false,
login: vi.fn(),
register: vi.fn(),
logout: vi.fn(),
toggleColorMode: vi.fn(),
colorMode: 'dark',
superTokensConfigured: true,
user: {
id: 'operator-1',
name: 'Operator',
email: 'operator@hypertwist.app',
plan: 'operator',
role: 'operator',
canDownload: true,
billing: {
source: 'session',
accessStatus: 'active',
canDownload: true,
lastEventType: 'transaction.completed',
},
},
})
mockGetReleaseManifest.mockResolvedValue({
ok: true,
manifest: {
generated_at: '2026-06-22T12:00:00.000Z',
support_email: 'hello@hypertwist.app',
public_docs_url: 'https://docs.hypertwist.app',
release_notes_url: 'https://notes.hypertwist.app',
corresponding_source_url: 'https://hypertwist.app/open-source/source.zip',
open_source_repo_url: 'https://github.com/hypertwist/hypertwist',
viewer: {
authenticated: true,
canDownload: true,
plan: 'operator',
role: 'operator',
accessStatus: 'active',
},
platforms: [
{
platform_key: 'windows',
platform: 'Windows',
subtitle: 'Primary shipping lane',
details: 'Current packaged validation is strongest on the Windows Unreal lane.',
configured: true,
channel: 'candidate',
version: '1.0.0',
build_id: 'win64-1000',
published_at: '2026-06-22T00:00:00.000Z',
file_name: 'HyperTwist-Windows.zip',
file_size_bytes: 1048576,
checksum_sha256: 'abc123',
download_url: 'https://downloads.hypertwist.app/windows.exe',
download_available: true,
},
],
},
})
renderRoute('/app/launch-status')
await waitFor(() => {
expect(screen.getByText('Protected launch status')).toBeTruthy()
})
expect(screen.getByText('Launch references and notices')).toBeTruthy()
})
it('renders the protected browser-access route through the real route tree when authenticated', async () => {
mockUsePlatformAuth.mockReturnValue({
isAuthenticated: true,

View file

@ -20,7 +20,7 @@ vi.mock('../auth/auth-api', () => ({
getReleaseManifest: (...args: unknown[]) => mockGetReleaseManifest(...args),
}))
import { AccountPage, BrowserAccessPage, DownloadCenterPage, NoticesPage } from '../pages/app-pages'
import { AccountPage, BrowserAccessPage, DownloadCenterPage, NoticesPage, ProtectedLaunchStatusPage } from '../pages/app-pages'
function renderPage(page: React.ReactNode, initialEntry: string) {
const queryClient = new QueryClient({
@ -209,6 +209,23 @@ describe('protected app pages', () => {
expect(screen.getByRole('link', { name: 'Open support' }).getAttribute('href')).toBe('/support?topic=operator-access')
})
it('surfaces a dedicated protected launch-status route with signed-in rollout authority', async () => {
renderPage(<ProtectedLaunchStatusPage />, '/app/launch-status')
expect(await screen.findByText('Protected launch status')).toBeTruthy()
expect(screen.getByText('Signed-in rollout authority')).toBeTruthy()
expect(screen.getByText('Current release action')).toBeTruthy()
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
expect(screen.getByText('Launch-readiness support lane')).toBeTruthy()
expect(screen.getByText('Launch references and notices')).toBeTruthy()
expect(screen.getByText('Protected browser-versus-desktop reality')).toBeTruthy()
expect(screen.getByRole('link', { name: 'Open public launch status' }).getAttribute('href')).toBe('/launch-status')
expect(screen.getByRole('link', { name: 'Open protected launch status' }).getAttribute('href')).toBe('/app/launch-status')
expect(await screen.findByText(byExactTextContent('Public repository/notices URL: https://github.com/hypertwist/hypertwist', 'LI'))).toBeTruthy()
expect(screen.getByRole('link', { name: 'Protected notices' }).getAttribute('href')).toBe('/app/notices')
expect(screen.getByRole('link', { name: 'Public notices' }).getAttribute('href')).toBe('/open-source-notices')
})
it('keeps the protected download center aligned with packaged proof, notices, and escalation guidance', async () => {
renderPage(<DownloadCenterPage />, '/app/downloads?platform=windows')

View file

@ -250,6 +250,8 @@ describe('website route and shell behavior', () => {
expect(screen.getByText('studio plan')).toBeTruthy()
expect(screen.getByText('Overview content')).toBeTruthy()
expect(screen.getByText('Desktop-first operator lane')).toBeTruthy()
expect(screen.getByRole('link', { name: 'Launch Status' }).getAttribute('href')).toBe('/app/launch-status')
expect(screen.getByRole('link', { name: 'Protected launch status' }).getAttribute('href')).toBe('/app/launch-status')
expect(screen.getByRole('link', { name: 'Public download posture' }).getAttribute('href')).toBe('/download')
expect(screen.getByRole('link', { name: 'Public notices' }).getAttribute('href')).toBe('/open-source-notices')
expect(screen.getByRole('link', { name: 'Operator access support' }).getAttribute('href')).toBe('/support?topic=operator-access')

View file

@ -1,4 +1,4 @@
import { Gauge, KeyRound, MonitorSmartphone, PackageOpen, ShieldCheck } from 'lucide-react'
import { Gauge, KeyRound, Landmark, MonitorSmartphone, PackageOpen, ShieldCheck } from 'lucide-react'
import { Link, NavLink, Outlet } from 'react-router-dom'
import { usePlatformAuth } from '../../auth/platform-auth'
import { brandConfig } from '../../site-config'
@ -6,6 +6,7 @@ import { buildSupportPath } from '../../site-routes'
const appLinks = [
{ to: '/app', label: 'Overview', icon: Gauge, end: true },
{ to: '/app/launch-status', label: 'Launch Status', icon: Landmark },
{ to: '/app/downloads', label: 'Downloads', icon: MonitorSmartphone },
{ to: '/app/browser-access', label: 'Browser Access', icon: PackageOpen },
{ to: '/app/account', label: 'Account', icon: KeyRound },
@ -53,6 +54,7 @@ export function AppShell() {
Use the native Unreal runtime for actual simulator execution.
</p>
<ul className="list top-gap">
<li><Link to="/app/launch-status">Protected launch status</Link></li>
<li><Link to="/download">Public download posture</Link></li>
<li><Link to="/open-source-notices">Public notices</Link></li>
<li><Link to={buildSupportPath('operator-access')}>Operator access support</Link></li>

View file

@ -370,6 +370,11 @@ type ProtectedReleaseAction = {
primary?: boolean
}
type ProtectedLaunchReadinessAction = {
label: string
to: string
}
type ProtectedReleaseActionSurface = {
badge: string
tone: 'success' | 'info'
@ -383,6 +388,7 @@ function buildProtectedSupportTopicActions(topicKey: string): readonly Protected
switch (topicKey) {
case 'launch-readiness':
return [
{ label: 'Open protected launch status', to: '/app/launch-status' },
{ label: 'Open downloads', to: buildProtectedDownloadPath('windows') },
{ label: 'Open notices', to: '/app/notices' },
{ label: 'Open pricing', to: '/pricing' },
@ -431,6 +437,79 @@ function ProtectedActionLink({
)
}
function ProtectedLaunchReadinessPanel({
title,
kicker,
description,
launchStatus,
releaseManifestQuery,
actions = [],
}: {
title: string
kicker: string
description?: string
launchStatus: ReturnType<typeof resolvePublicLaunchStatusSummary>
releaseManifestQuery: {
isLoading: boolean
isError: boolean
}
actions?: readonly ProtectedLaunchReadinessAction[]
}) {
const launchReadinessIssues = launchStatus.missingLabels
return (
<Panel title={title} kicker={kicker}>
{description ? <p>{description}</p> : null}
<p className={`status-pill${launchStatus.ready ? ' status-pill--success' : ''}`}>
{launchStatus.ready ? 'Launch-ready posture' : 'Preview posture'}
</p>
<ul className="list">
{launchStatus.checklist.map((item) => (
<li key={item.id}>
{item.label}: {item.configured
? (item.id === 'public-auth-runtime' ? 'production-ready' : 'configured')
: (item.id === 'public-auth-runtime' ? 'local-or-mixed' : 'missing')}
</li>
))}
<li>Operator checkout target: {launchStatus.targets.operatorCheckoutTarget || 'support fallback active'}</li>
<li>Studio checkout target: {launchStatus.targets.studioCheckoutTarget || 'support fallback active'}</li>
</ul>
{releaseManifestQuery.isLoading ? (
<p>Refreshing release-manifest download readiness from the auth server.</p>
) : null}
{releaseManifestQuery.isError ? (
<ProtectedReleaseAuthorityNotice
badge="Dashboard release fallback"
title="Live release-manifest lookup failed."
summary="Download readiness is currently using local fallback metadata rather than current runtime release authority."
stillWorks={[
'Protected launch-readiness interpretation, packaged proof, and account posture remain visible.',
'The protected browser shell can still separate auth, package, runtime, and rollout work while release authority recovers.',
]}
actionTo="/app/downloads"
actionLabel="Open downloads"
/>
) : null}
{launchReadinessIssues.length > 0 ? (
<p className="form-error">
Public launch is not fully configured yet: {launchReadinessIssues.join('; ')}.
</p>
) : (
<p>Core public release configuration is present for the current bounded website lane.</p>
)}
{actions.length > 0 ? (
<div className="button-row top-gap">
{actions.map((action) => (
<Link key={`${title}-${action.label}`} className="button button--ghost" to={action.to}>
{action.label}
</Link>
))}
</div>
) : null}
</Panel>
)
}
function describeReleaseTarget(
platform: ReleaseManifestView['platforms'][number] | null | undefined,
) {
@ -751,6 +830,79 @@ function ProtectedReleaseActionPanel({
)
}
function ProtectedSupportTopicPanel({
title,
kicker,
description,
topicKey,
}: {
title: string
kicker: string
description: string
topicKey: string
}) {
const topic = protectedSupportTopicGuides.find((item) => item.topicKey === topicKey)
if (!topic) {
return null
}
return (
<Panel title={title} kicker={kicker}>
<p>{description}</p>
<div className="card-grid top-gap">
<article className="card card--compact">
<p className="status-pill status-pill--info">{topic.title}</p>
<p>{topic.description}</p>
<ul className="list top-gap">
{topic.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
<div className="button-row top-gap">
{topic.actions.map((action) => (
<Link key={`${topic.topicKey}-${action.label}`} className="button button--ghost" to={action.to}>
{action.label}
</Link>
))}
</div>
</article>
</div>
</Panel>
)
}
function ProtectedReleaseReferencesPanel({
title,
kicker,
description,
releaseManifest,
}: {
title: string
kicker: string
description: string
releaseManifest: ReleaseManifestView
}) {
const supportEmail = releaseManifest.support_email || 'hello@hypertwist.app'
return (
<Panel title={title} kicker={kicker}>
<p>{description}</p>
<ul className="list top-gap">
<li>Public docs URL: {releaseManifest.public_docs_url || 'configure before launch'}</li>
<li>Release notes URL: {releaseManifest.release_notes_url || 'configure before launch'}</li>
<li>Corresponding-source URL: {releaseManifest.corresponding_source_url || 'configure before launch'}</li>
<li>Public repository/notices URL: {releaseManifest.open_source_repo_url || 'configure before launch'}</li>
<li>Operator support contact: {supportEmail}</li>
</ul>
<ReleaseAuthorityLinks
releaseManifest={releaseManifest}
includeProtectedNoticesLink
includePublicNoticesLink
/>
</Panel>
)
}
function PackagedValidationPanel({
title,
kicker,
@ -1055,8 +1207,6 @@ export function DashboardOverviewPage() {
return `${baseUrl}/api/auth/desktop-link/verify?token=${encodeURIComponent(token)}`
}, [desktopLinkMutation.data?.token])
const launchReadinessIssues = launchStatus.missingLabels
return (
<>
<SiteMetadata
@ -1144,45 +1294,17 @@ export function DashboardOverviewPage() {
releaseAuthorityUnavailable={releaseManifestQuery.isError}
/>
<Panel title="Launch readiness" kicker="Public release configuration">
<p className={`status-pill${launchStatus.ready ? ' status-pill--success' : ''}`}>
{launchStatus.ready ? 'Launch-ready posture' : 'Preview posture'}
</p>
<ul className="list">
{launchStatus.checklist.map((item) => (
<li key={item.id}>
{item.label}: {item.configured
? (item.id === 'public-auth-runtime' ? 'production-ready' : 'configured')
: (item.id === 'public-auth-runtime' ? 'local-or-mixed' : 'missing')}
</li>
))}
<li>Operator checkout target: {launchStatus.targets.operatorCheckoutTarget || 'support fallback active'}</li>
<li>Studio checkout target: {launchStatus.targets.studioCheckoutTarget || 'support fallback active'}</li>
</ul>
{releaseManifestQuery.isLoading ? (
<p>Refreshing release-manifest download readiness from the auth server.</p>
) : null}
{releaseManifestQuery.isError ? (
<ProtectedReleaseAuthorityNotice
badge="Dashboard release fallback"
title="Live release-manifest lookup failed."
summary="Download readiness is currently using local fallback metadata rather than current runtime release authority."
stillWorks={[
'Protected launch-readiness interpretation, packaged proof, and account posture remain visible.',
'The operator dashboard can still separate auth, package, runtime, and rollout work while release authority recovers.',
]}
actionTo="/app/downloads"
actionLabel="Open downloads"
/>
) : null}
{launchReadinessIssues.length > 0 ? (
<p className="form-error">
Public launch is not fully configured yet: {launchReadinessIssues.join('; ')}.
</p>
) : (
<p>Core public release configuration is present for the current bounded website lane.</p>
)}
</Panel>
<ProtectedLaunchReadinessPanel
title="Launch readiness"
kicker="Public release configuration"
launchStatus={launchStatus}
releaseManifestQuery={releaseManifestQuery}
actions={[
{ label: 'Open protected launch status', to: '/app/launch-status' },
{ label: 'Open downloads', to: buildProtectedDownloadPath('windows') },
{ label: 'Open notices', to: '/app/notices' },
]}
/>
<ProtectedOperatorQuickRoutesPanel
title="Protected operator quick routes"
@ -1237,6 +1359,92 @@ export function DashboardOverviewPage() {
)
}
export function ProtectedLaunchStatusPage() {
const {
user,
superTokensConfigured,
releaseManifest,
releaseManifestQuery,
} = useProtectedReleaseSurface('launch-status')
const healthQuery = useProtectedAuthHealthQuery('launch-status')
const launchStatus = useMemo(() => (
resolvePublicLaunchStatusSummary(
healthQuery.data,
releaseManifestQuery.data?.manifest,
launchReadiness,
)
), [healthQuery.data, releaseManifestQuery.data?.manifest])
return (
<>
<SiteMetadata
title="HyperTwist protected launch status"
description="Review the signed-in HyperTwist launch-readiness posture, release action, package proof, and rollout references."
canonicalPath="/app/launch-status"
robots="noindex,nofollow"
/>
<div className="panel-grid">
<ProtectedAuthSessionAuthorityPanel
title="Auth and session authority"
kicker="Launch dependency"
user={user}
superTokensConfigured={superTokensConfigured}
healthQuery={healthQuery}
/>
<ProtectedLaunchReadinessPanel
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."
launchStatus={launchStatus}
releaseManifestQuery={releaseManifestQuery}
actions={[
{ label: 'Open downloads', to: buildProtectedDownloadPath('windows') },
{ label: 'Open notices', to: '/app/notices' },
{ label: 'Open public launch status', to: '/launch-status' },
]}
/>
<ProtectedReleaseActionPanel
title="Current release action"
kicker="Protected access guidance"
releaseManifest={releaseManifest}
releaseAuthorityUnavailable={releaseManifestQuery.isError}
/>
<PackagedValidationPanel
title={protectedPackagedDesktopProofTitle}
kicker="Desktop proof"
description="This protected launch route keeps rollout status anchored to the same Windows higher-dimensional package proof used by the public launch lane and the signed-in dashboard."
emptyMessage="The current protected launch-status route could not find a Windows release target, so packaged desktop evidence is unavailable here right now."
releaseManifest={releaseManifest}
/>
<ProtectedSupportTopicPanel
title="Launch-readiness support lane"
kicker="Signed-in escalation"
description="When rollout work turns from checklist review into action, this protected lane keeps the next signed-in destinations explicit."
topicKey="launch-readiness"
/>
<ProtectedReleaseReferencesPanel
title="Launch references and notices"
kicker="Distribution follow-through"
description="Rollout posture is only trustworthy when docs, release notes, corresponding source, public notices, and protected notices remain reachable from the same signed-in launch surface."
releaseManifest={releaseManifest}
/>
<ProtectedBrowserDesktopRealityPanel
title="Protected browser-versus-desktop reality"
kicker="Signed-in product boundary"
description="Launch authority belongs to the browser shell because checkout, notices, and release references are browser-owned, while the real simulator still remains native and the XR/controller branch remains explicitly bounded."
/>
</div>
</>
)
}
export function DownloadCenterPage() {
const { user, canDownload, releaseManifest, releaseManifestQuery } = useProtectedReleaseSurface('protected')
const [searchParams] = useSearchParams()

View file

@ -6,6 +6,7 @@ import { Suspense, lazy } from 'react'
import { GeneralPageLoader } from '../components/ui/Skeletons'
const DashboardOverviewPage = lazy(() => import('../pages/app-pages').then((m) => ({ default: m.DashboardOverviewPage })))
const ProtectedLaunchStatusPage = lazy(() => import('../pages/app-pages').then((m) => ({ default: m.ProtectedLaunchStatusPage })))
const DownloadCenterPage = lazy(() => import('../pages/app-pages').then((m) => ({ default: m.DownloadCenterPage })))
const BrowserAccessPage = lazy(() => import('../pages/app-pages').then((m) => ({ default: m.BrowserAccessPage })))
const AccountPage = lazy(() => import('../pages/app-pages').then((m) => ({ default: m.AccountPage })))
@ -24,6 +25,12 @@ const protectedAppLoaders = {
description:
'Resolving entitled desktop targets, current package proof, and rollout references before the signed-in download surface opens.',
},
launchStatus: {
title: 'Loading launch status...',
eyebrow: 'Protected rollout authority',
description:
'Restoring the signed-in launch checklist, release references, and packaged proof before protected rollout follow-through resumes.',
},
browserAccess: {
title: 'Loading browser access...',
eyebrow: 'Protected browser shell',
@ -75,6 +82,7 @@ export function AppRouteTree() {
<Route element={<ProtectedRoute />}>
<Route path="/app" element={<AppShell />}>
<Route index element={withAppLoader(protectedAppLoaders.dashboard, <DashboardOverviewPage />)} />
<Route path="launch-status" element={withAppLoader(protectedAppLoaders.launchStatus, <ProtectedLaunchStatusPage />)} />
<Route path="downloads" element={withAppLoader(protectedAppLoaders.downloads, <DownloadCenterPage />)} />
<Route path="browser-access" element={withAppLoader(protectedAppLoaders.browserAccess, <BrowserAccessPage />)} />
<Route path="account" element={withAppLoader(protectedAppLoaders.account, <AccountPage />)} />

View file

@ -156,6 +156,7 @@ export const productSurfaceMatrixRows = [
description: 'This is the account-aware browser lane for entitlement, auth health, billing posture, protected notices, and desktop pairing.',
owns: [
'Live session, billing, entitlement, and release-manifest viewer posture.',
'A dedicated signed-in launch-status route for rollout blockers, packaged proof, and protected next-step interpretation.',
'Desktop-link token issuance and protected follow-through after sign-in.',
'Operator-facing release, notice, and download-center context that should not sit on public pages.',
],
@ -865,6 +866,11 @@ export const resourceCollections = [
] as const
export const changelogEntries = [
{
date: 'June 27, 2026',
title: 'Protected launch status now has its own signed-in authority route',
details: 'The browser operator shell now exposes a dedicated `/app/launch-status` route for signed-in launch-readiness truth, release action, packaged desktop proof, notices references, and protected rollout next steps instead of collapsing that lane down to one dashboard panel.',
},
{
date: 'June 27, 2026',
title: 'Launch status now has its own canonical public authority route',