mirror of
https://github.com/djdevin/recflare.git
synced 2026-10-25 15:09:18 -07:00
106 lines
5.9 KiB
TypeScript
106 lines
5.9 KiB
TypeScript
import type { HonoApp } from '@repo/hono-helpers'
|
|
import type { SharedHonoEnv, SharedHonoVariables } from '@repo/hono-helpers/src/types'
|
|
|
|
export type Env = SharedHonoEnv & {
|
|
// Shared rooms/accounts D1 database. The `auth` worker owns the `accounts`
|
|
// table (creates accounts on signup, seeds the system + Coach accounts). Also
|
|
// seeds new players' presence to the Orientation room (the shared `presence`
|
|
// table, see @repo/domain) so the match heartbeat keeps them there.
|
|
DB: D1Database
|
|
// Shared Secrets Store binding for the HS256 signing key. Resolve the value with
|
|
// `await env.JWT_SECRET.get()`. Every worker binds the same store, so tokens
|
|
// signed here verify in all of them. Provisioned via `wrangler secrets-store`;
|
|
// the store id is spliced into wrangler.jsonc at deploy time (RECFLARE_SECRETS_STORE).
|
|
JWT_SECRET: SecretsStoreSecret
|
|
// The Meta (Oculus) app secret, from the app's page in the Meta developer dashboard.
|
|
// Bound from the same Secrets Store as JWT_SECRET; resolve it with `.get()`. Used
|
|
// only to authenticate US to Meta's graph API when validating a login nonce (see
|
|
// meta-nonce.ts) — it never leaves the worker. Unlike Steam, whose ticket verifies
|
|
// offline, Meta logins are impossible without it, so an empty value fails those
|
|
// logins with a 500 rather than silently trusting the client's platform_id.
|
|
META_APP_SECRET: SecretsStoreSecret
|
|
// Signup caps, both optional (see auth.app.ts for what each arm counts and why).
|
|
// Unset falls back to the DEFAULT_MAX_ACCOUNTS_* constants there; 0 disables that arm.
|
|
// Typed `string | number` because a var declared in wrangler.jsonc `vars` arrives as a
|
|
// number while the same var set from the dashboard or `--var` arrives as a string —
|
|
// read them through `intVar`, never as a bare number.
|
|
MAX_ACCOUNTS_PER_PLATFORM_ID?: string | number
|
|
MAX_ACCOUNTS_PER_IP?: string | number
|
|
MAX_ACCOUNTS_PER_DEVICE_ID?: string | number
|
|
/**
|
|
* Whether `create_account` accepts a signup with NO platform identity — the password
|
|
* account the website makes (`www` `/api/signup`), or anything else that posts the
|
|
* grant without a `platform`. `on`/`off` (or true/false, 1/0); unset means OFF, so a
|
|
* server opens web signup deliberately. Read through `flagVar`. The `www` worker reads
|
|
* the same knob to hide its form and refuse its endpoint, so the two agree for free.
|
|
* Platform signups (Steam, Meta) are never governed by this — they always have an
|
|
* identity to authenticate with later, and the caps above are what limit them.
|
|
*/
|
|
PASSWORD_SIGNUP?: string | number | boolean
|
|
/**
|
|
* Which linked arms a ban is enforced through, as a comma-separated list out of `ip`
|
|
* and `platform` — or `off` for neither. Unset means BOTH: a ban reaches the accounts
|
|
* that share a proven platform identity or an IP with the banned one, and refuses a
|
|
* signup from either, which is what stops an evader simply making a new account.
|
|
*
|
|
* The `ip` arm is coarse (households, NAT, campus and carrier networks share one
|
|
* address), so `platform` alone is the setting for a server whose players share
|
|
* networks. Whatever this says, a ban always applies to the account it was handed to.
|
|
* Read through `banEvasionMatch`; the `match` worker reads the same knob.
|
|
*/
|
|
BAN_EVASION_MATCH?: string
|
|
/**
|
|
* The Discord role ids that may sign in on a ROLLOUT-GATED client build (see
|
|
* `ROLLOUT_GAME_VERSIONS` in @repo/domain) — numeric snowflakes, separated by commas
|
|
* and/or whitespace, exactly like `www`'s DISCORD_BENEFITS_ROLE_IDS. ANY one of them
|
|
* qualifies. A login whose posted `ver` is a gated build is refused unless the account's
|
|
* Discord link (`platform_account`, platform 101, written by the website's benefits
|
|
* claim) records one of these roles — or the account is STAFF (developer or moderator),
|
|
* who are always let in, configured roles or not.
|
|
*
|
|
* Unset — or parsing to no ids — leaves the gate CLOSED: nobody but staff gets a token on
|
|
* a gated build. That is the safe reading of "supporters only" when no supporter role has been
|
|
* named, and it keeps a build that isn't ready from being reachable by accident.
|
|
* Logins on every other build are never touched by this.
|
|
*/
|
|
DISCORD_ROLLOUT_ROLE_IDS?: string
|
|
/**
|
|
* The client builds a `/connect/token` grant may post as `ver` and still get a token:
|
|
* a comma-separated list of builds (`20230414,20250718`), or `off` for none. Unset means
|
|
* the default `SUPPORTED_GAME_VERSIONS` in @repo/domain. Set for every worker from the
|
|
* root `.env` (`RECFLARE_SUPPORTED_GAME_VERSIONS`), so this refuses exactly the builds
|
|
* `api`'s `/api/versioncheck/v4` tells to update — dropping a build from the list is how
|
|
* its players are made to upgrade. Read through `supportedGameBuilds`, which also folds
|
|
* in every build under rollout (below). A grant posting no `ver` is never gated.
|
|
*/
|
|
SUPPORTED_GAME_VERSIONS?: string
|
|
/**
|
|
* The builds under staged rollout — the ones the Discord-role gate above applies to —
|
|
* overriding `ROLLOUT_GAME_VERSIONS` in @repo/domain: same format, or `off` to end the
|
|
* rollout and open those builds to every account. Set for every worker
|
|
* (`RECFLARE_ROLLOUT_GAME_VERSIONS`), so `match`'s rollout voice pool follows the same
|
|
* list. A build here is served whether or not `SUPPORTED_GAME_VERSIONS` names it. Read
|
|
* through `rolloutGameBuilds`.
|
|
*/
|
|
ROLLOUT_GAME_VERSIONS?: string
|
|
/**
|
|
* Base domain, e.g. `recflare.net`. Injected for every worker at deploy time
|
|
* (`--var DOMAIN`). Studio's device-login response points the browser at
|
|
* `www.<domain>/device`, so auth has to know the same domain `ns` advertises.
|
|
*/
|
|
DOMAIN: string
|
|
/**
|
|
* The same `SUBDOMAINS` JSON `ns` applies. A `www` override has to move the
|
|
* verification URI with the host the editor was told WWW lives on.
|
|
*/
|
|
SUBDOMAINS: string
|
|
}
|
|
|
|
/** Variables can be extended */
|
|
export type Variables = SharedHonoVariables
|
|
|
|
export interface App extends HonoApp {
|
|
Bindings: Env
|
|
Variables: Variables
|
|
}
|