204 lines
9.7 KiB
Markdown
204 lines
9.7 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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`
|