Configuration and secrets #
Customer runtime and control plane have separate server-only loaders under
configuration/. They do not read process.env or Vite build variables. Pass
Cloudflare Worker bindings to the appropriate loader. FLAREBOT_MODE is required
and must match that entry. FLAREBOT_ENV defaults to production; the only other
value is explicit development. Unknown FLAREBOT_ bindings fail validation so
misspellings and cross-boundary credentials cannot silently become settings.
Platform bindings such as AI are outside this namespace.
Customer runtime #
Set these nonsecret Worker variables when installing the immutable release:
{
"FLAREBOT_MODE": "customer-runtime",
"FLAREBOT_ENV": "production",
"FLAREBOT_INSTALLATION": "{\"schemaVersion\":1,\"installationId\":\"0123456789abcdef0123456789abcdef\",\"ownerSubject\":\"authenticated-owner-subject\",\"runtimeOrigin\":\"https://customer.example.com\",\"controlPlaneOrigin\":\"https://control.example.com\"}"
}
Installation IDs are generated once as 32 lowercase hexadecimal characters. Preserve the ID and stable authenticated owner subject across upgrades. Changing these settings is an ownership operation, not a local override. Origins must be exact HTTPS origins, without credentials, paths, query strings, fragments or a trailing slash. Schema version 1 accepts only the five fields shown above.
Generate an independent random session secret for each installation (for example,
openssl rand -hex 32), then set FLAREBOT_SESSION_SECRET with wrangler secret put FLAREBOT_SESSION_SECRET --name flarebot-<installationId> or the Workers
secrets API. It must contain at least 32 bytes. Length validation cannot certify
entropy; never reuse the example or test values in production. This binding is
the runtime session-auth foundation; this issue does not expose an auth route.
Workers AI uses the native AI binding and needs no provider API key.
The customer Worker validates config and required secrets on ingress before SSR.
Invalid settings return a generic, uncached HTTP 503. Worker configuration logs
identify the field and recovery action without including supplied values or raw
JSON parse errors. Static assets may still be served by Cloudflare's asset router.
SSR receives only ASSETS, not secret-bearing Worker bindings. Do not put loaded
configuration/secrets in Agent setState, browser props or broadcast payloads.
loadCustomerConfig returns the base installation and the
effectiveInstallation after local overrides. Use serializeInstallationConfig
at nonsecret persistence/export boundaries: it reparses unknown input, rejects
extra or nested fields, and serializes only a valid installation. Neither loader
persists anything. This schema protects against credential fields and wrappers;
it cannot identify a secret deliberately supplied as an otherwise valid owner
subject. Callers must source identity from authenticated ownership metadata.
Local development #
Copy .dev.vars.example to .dev.vars and run pnpm dev:worker. Wrangler loads
the local bindings at runtime. Keep credentials out of Vite .env files and
VITE_* variables. .dev.vars and .dev.vars.* are ignored except the committed
placeholder example. Do not use real production credentials locally.
FLAREBOT_DEV_OVERRIDES accepts a JSON object containing only runtimeOrigin
and/or controlPlaneOrigin. HTTP is permitted only for localhost, 127.0.0.1
or [::1] in development. Overrides never mutate the base installation record
and cannot change the owner, installation ID, mode or secrets. Any override
binding, including an empty object, fails in production. Vite's pnpm dev is
only a frontend preview; use the Worker command to exercise these boundaries.
When the effective runtime origin is loopback, GET /auth/login issues a local
owner session. This development-only shortcut cannot activate in production or
for a non-loopback runtime origin.
Control plane #
configuration/control-plane.ts configures the separate control-plane
entry/artifact; the customer bundle never imports it. See
OAuth onboarding for the required reviewed capability
manifest, token authentication method, publisher setup and build commands.
The small example below illustrates the base parser contract only; it cannot
enable onboarding without those additional verified setup fields. It requires
FLAREBOT_MODE=control-plane and a FLAREBOT_CONTROL_PLANE JSON string:
{
"schemaVersion": 1,
"publicOrigin": "https://control.example.com",
"oauthClientId": "your-registered-cloudflare-client-id",
"oauthRedirectUri": "https://control.example.com/auth/callback",
"oauthScopes": ["openid", "account.read", "workers-platform.write"]
}
The callback must be on publicOrigin without credentials, query or fragment.
Scope syntax accepts dot-delimited identifiers; the example is not a complete
installer permission set. The onboarding preflight must discover and validate the
actual registered scopes. serializeControlPlaneConfig is the strict nonsecret
serialization boundary. Control-plane config cannot contain installation data.
loadControlPlaneSecrets independently loads FLAREBOT_SESSION_SECRET (at least
32 bytes), FLAREBOT_CREDENTIAL_ENCRYPTION_KEY (32 random bytes encoded as
unpadded base64url, e.g. node -e 'console.log(require("node:crypto").randomBytes(32).toString("base64url"))'),
and optional FLAREBOT_OAUTH_CLIENT_SECRET for a confidential OAuth client.
These secrets must be independent of customer secrets and live only on the
control-plane Worker. OAuth access/refresh tokens belong in a separate protected
credential store, never either config schema or installation metadata. The separate control-plane Worker implements the OAuth flow and native encrypted
AuthVault storage; these parsers themselves persist nothing.
Secret values are wrapped with private storage; JSON, string interpolation and
inspection produce redacted output. Call .reveal() only when passing a secret
to the consuming crypto/provider API. Redaction is defense in depth, not a vault:
never serialize or log revealed values, raw environments or credential responses.
Provider keys are encrypted in customer-owned Durable Object storage and managed
through Settings. See model providers for OpenRouter's
native AI Gateway transport, key and billing requirements, retirement migration
from OpenCode, and provider-extension instructions.
Cloudflare documents runtime secrets and local .dev.vars behavior in its
Workers secrets reference.