diff --git a/docs/ops/HYPERTWIST_PUBLIC_WEBSITE_AUTH_BILLING_AND_DISTRIBUTION_PACKET_2026-06-22.md b/docs/ops/HYPERTWIST_PUBLIC_WEBSITE_AUTH_BILLING_AND_DISTRIBUTION_PACKET_2026-06-22.md
index ef77038..850a3a9 100644
--- a/docs/ops/HYPERTWIST_PUBLIC_WEBSITE_AUTH_BILLING_AND_DISTRIBUTION_PACKET_2026-06-22.md
+++ b/docs/ops/HYPERTWIST_PUBLIC_WEBSITE_AUTH_BILLING_AND_DISTRIBUTION_PACKET_2026-06-22.md
@@ -92,6 +92,7 @@ Current behavior:
- optional ORCID redirect posture retained client-side as a backend-gated extension point
- deterministic local fallback mode when the backend is not configured
- bounded auth-health probing that now distinguishes configured, reachable, and ready shared-core posture without mutating auth state
+- bounded frontend auth-env diagnostics that now warn when the browser lane still points at loopback, insecure `http`, or split backend/auth targets
### Browser dashboard posture
@@ -118,6 +119,11 @@ The protected dashboard now also has a first-party launch-readiness panel for:
- Paddle checkout-link presence by plan
- corresponding-source and open-source notices URL presence
- backend webhook-secret and billing-map configuration posture
+- public auth runtime posture, cookie-hardening posture, and local-vs-public runtime diagnostics
+
+The login and register pages now also surface those shared-auth runtime warnings
+instead of silently behaving like production auth when the lane is still in
+local fallback or mixed deployment posture.
This is browser-based user access for the operator/account surface.
@@ -188,6 +194,11 @@ Before public launch, operators still must configure:
- live notification-destination secret management
- any broader operator/admin billing workflow beyond the current bounded entitlement application
+Recommended public runtime values and same-origin deployment posture now have a
+dedicated authority note:
+
+- `docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md`
+
## Validation completed
Frontend validation:
diff --git a/docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md b/docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md
new file mode 100644
index 0000000..67f28ff
--- /dev/null
+++ b/docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md
@@ -0,0 +1,90 @@
+# HyperTwist Website Runtime Configuration Guide
+
+Created on `2026-06-22`.
+
+## Purpose
+
+This note records the recommended production runtime posture for the first-party
+`website/` and `website/server/` lane that powers `hypertwist.app`.
+
+It exists because the source tree now has:
+
+- a real public website
+- a real browser auth/dashboard surface
+- explicit runtime diagnostics that can distinguish local, mixed, and public posture
+
+## Recommended public posture
+
+For the simplest honest public deployment, prefer same-origin browser and auth
+posture:
+
+- frontend public origin: `https://hypertwist.app`
+- backend public origin: `https://hypertwist.app`
+- frontend route prefix: `/`
+- auth API base path: `/auth`
+- auth website base path: `/auth`
+
+Recommended server env posture:
+
+- `API_DOMAIN=https://hypertwist.app`
+- `WEBSITE_DOMAIN=https://hypertwist.app`
+- `API_BASE_PATH=/auth`
+- `WEBSITE_BASE_PATH=/auth`
+- `COOKIE_SECURE=true`
+- real `PADDLE_WEBHOOK_SECRET`
+- real `PADDLE_PRODUCT_PLAN_MAP` and/or `PADDLE_PRICE_PLAN_MAP`
+
+Recommended frontend env posture:
+
+- `VITE_SUPERTOKENS_API_DOMAIN=https://hypertwist.app`
+- `VITE_SUPERTOKENS_WEBSITE_DOMAIN=https://hypertwist.app`
+- `VITE_AUTH_API_BASE_URL=https://hypertwist.app`
+- real `VITE_WINDOWS_DOWNLOAD_URL`
+- real `VITE_PADDLE_CHECKOUT_URL_OPERATOR`
+- real `VITE_PADDLE_CHECKOUT_URL_STUDIO`
+- real `VITE_MPL_SOURCE_URL`
+- real `VITE_OPEN_SOURCE_REPO_URL`
+
+## Why same-origin is the clean default
+
+The current first-party browser lane already supports exact-origin checks,
+dashboard-side launch-readiness visibility, and same-origin auth fallback.
+
+That means same-origin public deployment is the least ambiguous posture for:
+
+- auth cookies
+- protected dashboard access
+- browser-to-desktop token issuance
+- public download gating
+- billing webhook and entitlement reflection
+
+## If a split-host auth topology is chosen later
+
+That is allowed, but it should not be the unexamined default.
+
+If a split-host topology is used:
+
+- keep all public-facing auth origins on `https`
+- keep `COOKIE_SECURE=true`
+- ensure `VITE_AUTH_API_BASE_URL` and `VITE_SUPERTOKENS_API_DOMAIN` still point at the same backend
+- ensure dashboard health reports `public auth origin ready: yes`
+- ensure launch-readiness warnings are empty before public launch
+
+## Current diagnostics that must be green
+
+Before public launch, the current runtime and dashboard surfaces should show:
+
+- runtime mode: `public`
+- `public auth origin ready: yes`
+- no runtime config errors
+- no runtime config warnings that indicate loopback, insecure `http`, or partial OAuth setup
+- dashboard launch-readiness issues cleared for download/check-out/source configuration
+
+## Related authorities
+
+- `website/README.md`
+- `website/server/README.md`
+- `docs/ops/HYPERTWIST_PUBLIC_WEBSITE_AUTH_BILLING_AND_DISTRIBUTION_PACKET_2026-06-22.md`
+- `docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md`
+- `docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md`
+- `docs/ops/HYPERTWIST_VPS_TLS_CERTIFICATE_AND_IONOS_SEPARATION_GUIDE_2026-05-30.md`
diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md
index 4972c76..e221384 100644
--- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md
+++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md
@@ -264,7 +264,7 @@ repo.
| Feature | Status | Primary authority | Notes |
|---|---|---|---|
| Public `hypertwist.app` marketing shell | Implemented now | first-party `website/` app + feature registry/roadmap authority | HyperTwist now has a dedicated first-party public web surface for homepage, about, resources, pricing, download, support, and legal routes. This lane is separate from the embedded Unreal browser runtime under `Content/Browser/` and does not claim browser-simulator parity. |
-| Browser-based operator/account dashboard | Implemented now | first-party `website/` app + shared auth/dashboard packet | A protected browser dashboard is now live for operator access, account state, download posture, browser-access boundary explanation, notices review, and bounded billing/entitlement status. It reuses the shared SuperTokens auth posture proven in FamiliarOS and ScriptoriumAI while remaining HyperTwist-specific in product content and boundary claims, the current auth-health surface now truthfully distinguishes configured versus reachable or ready shared-core posture while exposing fallback-active reason instead of hardcoding readiness, and the same dashboard now also surfaces launch-readiness truth for download URLs, checkout links, source/notices URLs, and billing-secret/map configuration. |
+| Browser-based operator/account dashboard | Implemented now | first-party `website/` app + shared auth/dashboard packet | A protected browser dashboard is now live for operator access, account state, download posture, browser-access boundary explanation, notices review, and bounded billing/entitlement status. It reuses the shared SuperTokens auth posture proven in FamiliarOS and ScriptoriumAI while remaining HyperTwist-specific in product content and boundary claims, the current auth-health surface now truthfully distinguishes configured versus reachable or ready shared-core posture while exposing fallback-active reason instead of hardcoding readiness, and the same dashboard now also surfaces launch-readiness truth for download URLs, checkout links, source/notices URLs, billing-secret/map configuration, and local-versus-public runtime deployment posture. |
| Desktop download posture and browser-to-desktop pairing | Implemented now | first-party `website/` app + `website/server` desktop-link endpoints | Public download targets, dashboard-side release posture, and short-lived desktop-link token generation/verification are now first-party owned. The current server posture now enforces exact website-origin matching, bounded per-user issuance, one-time token consumption, and billing-backed plan/download entitlement resolution with focused `website/server` tests green on `2026-06-22`, and the verify handshake now returns the same resolved download-entitlement posture the dashboard sees instead of only identity plus plan/role. The public `/download` page now keeps raw download URLs behind the protected dashboard instead of exposing them directly. Actual release URLs remain deployment configuration rather than hardcoded product truth. |
| Paddle-ready pricing and billing webhook seam | Implemented now | first-party `website/` app + `website/server` billing endpoint | The public pricing surface now exists with plan structure, checkout-link configuration seams, and the same `/api/billing/paddle/webhook` endpoint family used by the broader product website lane. The current server now verifies `Paddle-Signature` against `PADDLE_WEBHOOK_SECRET` using the documented raw-body HMAC flow, persists a bounded first-party billing state file, and applies verified Paddle events into account/download entitlement state that the browser dashboard consumes, with focused `website/server` tests green on `2026-06-22`. Production checkout URLs, secret management, and broader operator/admin billing workflows remain deployment/application tasks, not shipped-code omissions. |
| Public open-source notices and corresponding-source surface | Implemented now | first-party `website/` app + `HYPERTWIST_MPL_DISTRIBUTION_PLACEMENT_CHECKLIST_2026-05-25.md` | HyperTwist now has a stable public `Open Source Notices` route linked from pricing, download, and footer surfaces, satisfying the requirement that public distribution surfaces expose notice and corresponding-source guidance when shipped builds contain `MPL`-covered material. The exact public corresponding-source URL still must be configured before external launch. |
diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md
index 4f56023..c25c86e 100644
--- a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md
+++ b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md
@@ -209,7 +209,11 @@ Current consolidated milestone snapshot:
fallback-active reason back into the protected dashboard rather than
hardcoding readiness, and the protected dashboard now also carries a
first-party launch-readiness panel for download/check-out/legal configuration
- posture using the existing site-config and auth-health seams,
+ posture using the existing site-config and auth-health seams, while the
+ website/server lane now also has first-party runtime-configuration
+ diagnostics for local versus mixed versus public auth posture and the
+ login/register surfaces now expose those warnings instead of silently
+ resembling a production-ready lane,
persists a bounded first-party billing-state file, applies verified Paddle
events into account/download entitlement state, and surfaces that resolved
billing/download posture back through `/api/auth/me`, the protected browser
diff --git a/website/.env.example b/website/.env.example
index b868be0..c1a0e90 100644
--- a/website/.env.example
+++ b/website/.env.example
@@ -3,6 +3,7 @@ VITE_SUPERTOKENS_WEBSITE_DOMAIN=http://localhost:4273
VITE_SUPERTOKENS_API_BASE_PATH=/auth
VITE_SUPERTOKENS_WEBSITE_BASE_PATH=/auth
VITE_AUTH_API_BASE_URL=http://localhost:3001
+VITE_AUTH_API_TIMEOUT_MS=8000
VITE_GITHUB_OAUTH_ENABLED=false
VITE_GOOGLE_OAUTH_ENABLED=false
VITE_ORCID_OAUTH_ENABLED=false
diff --git a/website/README.md b/website/README.md
index 7aae4e8..89b9b71 100644
--- a/website/README.md
+++ b/website/README.md
@@ -8,6 +8,7 @@ First-party `hypertwist.app` surface for HyperTwist:
- desktop download posture and desktop-link handshake endpoints
- Paddle-ready pricing/check-out wiring
- dashboard-side launch-readiness surface for download, checkout, auth, and notice configuration
+- runtime diagnostics that distinguish local, mixed, and public auth deployment posture
- public open-source notices surface required by HyperTwist's MPL distribution doctrine
## Why this app exists
@@ -65,3 +66,7 @@ Before public launch, configure:
Do not launch the public pricing/download pages without a valid open-source
notices and corresponding-source destination.
+
+Recommended production posture is documented in:
+
+- `docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md`
diff --git a/website/server/README.md b/website/server/README.md
index 0cede81..54808e4 100644
--- a/website/server/README.md
+++ b/website/server/README.md
@@ -11,6 +11,7 @@ Responsibilities:
- Paddle webhook endpoint with raw-body signature verification
- verified billing-event application into first-party account/download entitlement state
- public auth-health probe for the website with configured vs reachable core truth
+- runtime configuration diagnostics for local vs mixed vs public auth posture
## Quick start
@@ -61,3 +62,15 @@ The auth-health route now probes the configured SuperTokens core non-mutatively:
- `SUPERTOKENS_HEALTH_TIMEOUT_MS` bounds the probe duration
- `/api/auth/health` now distinguishes configured, reachable, and ready state
- the protected dashboard can now show when browser fallback posture is active because the shared auth core is unreachable
+
+Recommended public `hypertwist.app` posture:
+
+- `API_DOMAIN=https://hypertwist.app`
+- `WEBSITE_DOMAIN=https://hypertwist.app`
+- `COOKIE_SECURE=true`
+- real `PADDLE_WEBHOOK_SECRET`
+- real plan-map configuration or equivalent verified-event plan resolution
+
+That recommended same-origin production posture is recorded in:
+
+- `docs/ops/HYPERTWIST_WEBSITE_RUNTIME_CONFIGURATION_GUIDE_2026-06-22.md`
diff --git a/website/server/src/__tests__/runtime-config.test.ts b/website/server/src/__tests__/runtime-config.test.ts
new file mode 100644
index 0000000..51748ad
--- /dev/null
+++ b/website/server/src/__tests__/runtime-config.test.ts
@@ -0,0 +1,51 @@
+import { describe, expect, it } from 'vitest'
+
+import { getRuntimeConfigDiagnostics } from '../runtime-config'
+
+describe('getRuntimeConfigDiagnostics', () => {
+ it('marks loopback-only development posture as local and not public-ready', () => {
+ const diagnostics = getRuntimeConfigDiagnostics({
+ apiDomain: 'http://localhost:3001',
+ websiteDomain: 'http://localhost:4273',
+ superTokensCoreUri: 'http://localhost:3567',
+ cookieSecure: false,
+ })
+
+ expect(diagnostics.mode).toBe('local')
+ expect(diagnostics.publicOriginReady).toBe(false)
+ expect(diagnostics.errors).toEqual([])
+ expect(diagnostics.warnings).toContain('API_DOMAIN still targets a loopback/local-development origin.')
+ expect(diagnostics.warnings).toContain('WEBSITE_DOMAIN still targets a loopback/local-development origin.')
+ })
+
+ it('marks public https posture as ready when cookie hardening is enabled', () => {
+ const diagnostics = getRuntimeConfigDiagnostics({
+ apiDomain: 'https://hypertwist.app',
+ websiteDomain: 'https://hypertwist.app',
+ superTokensCoreUri: 'https://auth-core.internal',
+ cookieSecure: true,
+ githubClientId: 'github-client-id',
+ githubClientSecret: 'github-client-secret',
+ })
+
+ expect(diagnostics.mode).toBe('public')
+ expect(diagnostics.publicOriginReady).toBe(true)
+ expect(diagnostics.errors).toEqual([])
+ expect(diagnostics.warnings).toEqual([])
+ })
+
+ it('flags invalid origins and partial oauth configuration', () => {
+ const diagnostics = getRuntimeConfigDiagnostics({
+ apiDomain: 'https://hypertwist.app/auth',
+ websiteDomain: 'not-a-url',
+ superTokensCoreUri: 'http://localhost:3567',
+ cookieSecure: false,
+ googleClientId: 'only-client-id',
+ })
+
+ expect(diagnostics.publicOriginReady).toBe(false)
+ expect(diagnostics.errors).toContain('API_DOMAIN must not include a path; use API_BASE_PATH for route prefixing.')
+ expect(diagnostics.errors).toContain('WEBSITE_DOMAIN must be an absolute URL origin.')
+ expect(diagnostics.warnings).toContain('Google OAuth is only partially configured; set both client ID and client secret or neither.')
+ })
+})
diff --git a/website/server/src/index.ts b/website/server/src/index.ts
index 5e04b80..0b84f3f 100644
--- a/website/server/src/index.ts
+++ b/website/server/src/index.ts
@@ -13,6 +13,7 @@ import GoogleProvider from 'supertokens-node/lib/build/recipe/thirdparty/provide
import { probeSuperTokensCoreHealth } from './auth-health'
import { createBillingStateStore, type BillingPlan, type BillingRole } from './billing-state'
import { verifyPaddleWebhookSignature } from './paddle-webhook'
+import { getRuntimeConfigDiagnostics } from './runtime-config'
import { buildAllowedOriginMatcher, createDesktopLinkStore } from './security'
const Github = GithubProvider as unknown as (options: { clientId: string; clientSecret: string; scope?: string[] }) => ReturnType Plan: {user?.plan} Role: {user?.role || 'operator'} Desktop downloads: {user?.canDownload ? 'enabled' : 'not yet entitled'}
+ This session is currently using local fallback posture, not fully shared production auth.
+
Runtime deployment diagnostics
+ {healthQuery.data.runtime.errors.length > 0 ? ( +diff --git a/website/src/pages/auth-pages.tsx b/website/src/pages/auth-pages.tsx index 9a19b8e..ba360a3 100644 --- a/website/src/pages/auth-pages.tsx +++ b/website/src/pages/auth-pages.tsx @@ -1,7 +1,14 @@ import { useEffect, useState } from 'react' import { Link, useNavigate, useSearchParams } from 'react-router-dom' import { usePlatformAuth } from '../auth/platform-auth' -import { isGitHubOAuthEnabled, isGoogleOAuthEnabled, isOrcidOAuthEnabled } from '../auth/supertokens-client' +import { + getSuperTokensAuthRuntimeValidation, + isGitHubOAuthEnabled, + isGoogleOAuthEnabled, + isOrcidOAuthEnabled, +} from '../auth/supertokens-client' + +const authRuntimeValidation = getSuperTokensAuthRuntimeValidation() function AuthShell({ title, @@ -67,6 +74,28 @@ export function LoginPage() { subtitle="Use the same browser auth posture as FamiliarOS and ScriptoriumAI, then hand off to the desktop runtime when needed." footer={
Need access? Create an account.
} > + {!authRuntimeValidation.ready || authRuntimeValidation.warnings.length > 0 ? ( ++ Shared browser auth is not fully in production posture yet. + {!authRuntimeValidation.ready ? ' Local fallback mode may activate until the required auth env vars are configured.' : ''} +
+ {authRuntimeValidation.missing.length > 0 ? ( +