hypertwist/website/server/README.md
2026-06-24 23:01:36 +00:00

9.7 KiB

HyperTwist Auth Server

Self-hosted SuperTokens auth backend for the HyperTwist website.

Responsibilities:

  • email/password sign-up and sign-in
  • optional GitHub and Google OAuth
  • session bootstrap for the browser dashboard
  • browser-to-desktop token handoff with exact-origin checks, bounded issuance, and one-time verification tokens
  • server-backed release-manifest authority for public/protected desktop distribution surfaces
  • 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

cd /home/dev/src/HyperTwist/website/server
npm install
cp .env.example .env
npm run dev

The website frontend should point at this backend through:

VITE_SUPERTOKENS_API_DOMAIN=http://localhost:3001
VITE_SUPERTOKENS_WEBSITE_DOMAIN=http://localhost:4273
VITE_AUTH_API_BASE_URL=http://localhost:3001

Important note

/api/billing/paddle/webhook now verifies the Paddle-Signature header against PADDLE_WEBHOOK_SECRET using the documented raw-body ts:h1 HMAC-SHA256 flow before it accepts the event.

The desktop-link lane is intentionally stricter than a generic session helper:

  • request origin must match the configured website origin exactly
  • token issuance is rate-limited per user
  • verification consumes the token on first successful use
  • verification now returns resolved download-entitlement posture alongside identity, plan, and role

The remaining Paddle deployment work is now configuration, not missing server ownership:

  • real production checkout URLs
  • live notification-destination secret management
  • event-specific async processing after verification

The server now also supports a small first-party entitlement store:

  • BILLING_STATE_PATH optionally relocates the persisted billing state file
  • PADDLE_PRODUCT_PLAN_MAP can map Paddle product IDs to free / operator / studio / enterprise
  • PADDLE_PRICE_PLAN_MAP can map Paddle price IDs to the same plan codes
  • if neither map is present, the verified webhook lane can still derive plan from custom_data.plan

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
  • PORT=3011 on the current shared VPS so the lane does not collide with the existing FamiliarOS auth server on 3001
  • 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

The server now also supports a bounded first-party same-origin deployment mode:

  • if website/dist/index.html exists, the server auto-serves the built public site from ../dist
  • SPA fallback is limited to non-file public/app routes and does not intercept /api/*, /auth*, or /health
  • WEBSITE_DIST_PATH can override the bundle location when deployment layout differs
  • SERVE_STATIC_WEBSITE=true forces the server to expect a built bundle, while SERVE_STATIC_WEBSITE=false keeps api-only mode explicit
  • the example env files now carry those static-serving controls directly so deployment posture is not implicit
  • request-level tests now also prove that public/app routes serve the shell while /api/*, /auth*, /health, and missing asset paths remain unshadowed
  • a spawned bootstrap test now also proves the real src/index.ts process can start from production-shaped same-origin env, reach a ready SuperTokens core, expose green /api/auth/health, serve the built shell, accept a verified webhook, and reflect that processed billing event through live health plus the persisted entitlement file
  • the same spawned proof lane now also exercises /api/auth/me and /api/auth/desktop-link through a bounded signed test-session harness that is only active when TEST_MODE=testing and HYPERTWIST_TEST_SESSION_SECRET are explicitly set; this is validation-only, not a production auth widening
  • the repo now also ships first-party systemd plus nginx handoff templates under website/deploy/ for that same-origin public lane
  • the website package now also includes npm run render:same-origin-deployment so operators can emit resolved systemd and nginx files from real checkout paths instead of editing the examples by hand
  • the website package now also includes npm run render:same-origin-bundle so one manifest file can own the public origin and emit validated frontend env, server env, systemd, and nginx outputs together before installation
  • the website package now also includes npm run run:vps-same-origin-staging-proof so the same bundle manifest can be exercised through a temporary VPS checkout on the real shared host before root-owned service/vhost cutover
  • the same bundle/readiness lane now distinguishes launch from preview posture, so non-public same-origin rehearsal may keep runtime mode mixed with the loopback SuperTokens warning and an empty PADDLE_WEBHOOK_SECRET while public launch still requires real checkout/download/webhook values
  • the staging-proof helper now also supports --archive-source worktree when operators need real host proof for the exact in-progress packet before commit
  • the same package now also ships npm run run:vps-same-origin-live-deploy for the bounded root-owned checkout/env/build/systemd/nginx replacement flow that was used to cut https://hypertwist.app over to the first-party same-origin preview lane and then re-proved idempotently

The website package now also ships a deploy-time verification command:

cd /home/dev/src/HyperTwist/website
npm run check:runtime-readiness -- --frontend-env .env --server-env server/.env --health-url https://hypertwist.app

Use --skip-live-health when only file-level env verification is possible.

Keep the example env files separated by posture:

  • website/.env.example and website/server/.env.example remain local-development defaults
  • website/.env.production.example and website/server/.env.production.example are public-posture scaffolds that still intentionally fail readiness until placeholder values are replaced

The repo now also proves that behavior directly by running the real check-runtime-readiness CLI against those production example files in test mode and asserting that placeholder launch values still fail.

Release-manifest authority

The auth server now exposes:

  • GET /api/releases/manifest

This route is the shared runtime authority for desktop release metadata across the public website and the protected dashboard download lane.

Behavior:

  • anonymous viewers receive release metadata without raw download URLs
  • entitled session-backed viewers receive the same metadata plus the configured direct download URL for each allowed platform
  • the payload also carries top-level support/docs/release-notes/corresponding-source/open-source-repo references so marketing and operator surfaces stay aligned
  • the payload now also carries public commerce config for operator/studio checkout URLs plus live plan-price strings so public pricing and protected launch-readiness surfaces can read runtime checkout posture from the server
  • the Windows platform entry now also carries first-party packaged-validation summary truth from the current higher-dimensional desktop lane, separate from whether a launch download URL has been configured yet

Primary server env inputs for this route:

  • RELEASE_MANIFEST_VERSION
  • RELEASE_MANIFEST_CHANNEL
  • SUPPORT_EMAIL
  • PUBLIC_DOCS_URL
  • RELEASE_NOTES_URL
  • MPL_SOURCE_URL
  • OPEN_SOURCE_REPO_URL
  • WINDOWS_*, MACOS_*, and LINUX_* release fields for url/version/channel/build/published-at/file-name/file-size/checksum

Compatibility note:

  • the manifest still falls back to legacy VITE_* download/source keys when the server-specific release env is not yet populated, so the new route can be adopted without breaking earlier preview scaffolds

The same deployment lane is now also probed by the runtime-readiness command through three live surfaces at the same public origin:

  • GET /api/auth/health
  • GET /api/releases/manifest
  • GET / for the first-party shell marker

That means the verifier can now fail explicitly when hypertwist.app is still serving the earlier placeholder rollout page instead of the real same-origin website/auth-server deployment.

The same verifier now also compares the live anonymous release-manifest payload against the currently configured launch authority for support/docs/source, checkout/price, and per-platform release metadata, so a stale host env or partially rolled deploy fails as configuration drift instead of passing on structural safety alone.

Live same-origin status on 2026-06-22:

  • the root-owned cutover now has https://hypertwist.app serving the first-party website/auth-server lane from the shared VPS
  • live /health, /api/auth/health, /api/releases/manifest, and root-shell verification are green in preview posture
  • the remaining live gap is launch-tier checkout/download/webhook completion, not website-host cutover

Canonical deployment handoff:

  • docs/ops/HYPERTWIST_WEBSITE_SAME_ORIGIN_DEPLOYMENT_HANDOFF_2026-06-22.md

The repo bootstrap CI now also validates this auth-server lane through:

  • npm ci
  • npm run type-check
  • npm test