-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration Reference
VA Dispatch has separate API and web environments. Vercel service bindings provide some values automatically in the multi-service deployment, but every production operator must still verify the complete configuration.
Primary example: apps/api/.env.example.
| Variable | Default | Required when | Purpose and constraints |
|---|---|---|---|
NODE_ENV |
development |
Always |
development, test, or production
|
VERCEL_ENV |
unset | Vercel supplies it |
development, preview, or production; takes precedence when selecting the production ACARS policy |
VERCEL_BRANCH_URL / VERCEL_URL
|
unset | Vercel Preview redirect recovery | Vercel-supplied bare hostnames; Preview prefers the stable branch URL, then the exact deployment URL |
PORT |
3001 |
Local override only | Positive integer used by the local Node server |
CORS_ORIGIN |
http://localhost:3000 |
Fallback cross-origin deployment | Comma-separated allowed web origins |
APP_ORIGIN |
unset | Production and local real-provider flows | Canonical public origin only; explicit HTTPS value is mandatory in Production |
DATABASE_URL |
unset | Every authenticated or persistent workflow | PostgreSQL connection URL, normally Neon |
CLERK_SECRET_KEY |
unset | Real authentication and Clerk member sync | Server secret; never expose as NEXT_PUBLIC_*
|
CLERK_PUBLISHABLE_KEY |
unset | Deployment integration may provide it | Parsed by API configuration; browser Clerk uses NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
AUTH_DEV_BYPASS |
false |
Local header-auth mode | Allowed only when NODE_ENV is not production
|
VSAS_CLERK_ORG_ID |
unset | Trusted vSAS production mapping | Clerk organization ID allowed to create or repair the initial vsas tenant mapping |
ACARS_PROVIDER |
mock |
Declare hoppie in production |
mock or hoppie; production runtime always resolves to Hoppie |
TENANT_SECRETS_KEY |
unset | Every production deployment; protected flows elsewhere | Exactly 32 random bytes, base64-encoded; protects tenant credentials and signed/sealed transient state |
CRON_SECRET |
insecure development placeholder | Production ACARS/privacy cron calls | Long random bearer secret; replace the default |
SEED_DEMO_DATA |
false |
None currently | Reserved parsed setting; it does not currently seed records automatically |
SIMBRIEF_API_KEY |
unset | SimBrief Dispatch Redirect | Application key issued by SimBrief |
SIMBRIEF_CALLBACK_URL |
unset | SimBrief generation | Public API callback URL |
NAVIGRAPH_CLIENT_ID / NAVIGRAPH_CLIENT_SECRET
|
unset | Navigraph account connection | OAuth client credentials; server-only |
NAVIGRAPH_REDIRECT_URI |
unset | Navigraph OAuth | Exact registered callback URL |
BLOB_READ_WRITE_TOKEN |
unset | Tenant logo upload | Vercel Blob server credential |
AVIATION_WEATHER_API_ORIGIN |
Aviation Weather API | Dispatch release weather | HTTPS provider origin; local integrated tests replace it |
AVIATION_WEATHER_USER_AGENT |
project identifier | Weather requests | Operator-identifying user agent |
E2E_FIXTURE_MODE |
false |
Integrated tests only | Requires test environment, fixture secret, and exact disposable database confirmation |
E2E_FIXTURE_SECRET |
unset | Integrated tests only | Dedicated high-entropy fixture authority; never reuse CRON_SECRET
|
E2E_CONFIRM_DATABASE |
unset | Integrated tests only | Exact disposable database name |
Generate independent production secrets:
openssl rand -base64 32 # TENANT_SECRETS_KEY
openssl rand -hex 32 # suitable CRON_SECRET materialChanging TENANT_SECRETS_KEY without re-encrypting stored values makes existing
Hoppie credentials unreadable, invalidates issued simulator device tokens, and
invalidates pending SimBrief callback or Navigraph OAuth state. Plan rotation
as a controlled key rotation or re-enter credentials, reissue device tokens, and restart
pending provider flows under the new key.
schema.ts is canonical while this Shiftbloom project is pre-production.
Create an empty database and run DATABASE_URL=... pnpm db:push from the exact
release commit. Never use it against data that must be preserved.
Primary example: apps/web/.env.example.
| Variable | Exposure | Required when | Purpose |
|---|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
Browser | Normal auth | Clerk publishable key |
CLERK_SECRET_KEY |
Server only | Server-side Clerk auth | Clerk secret key |
API_INTERNAL_URL |
Server only | Multi-service/local server calls | Preferred API origin; Vercel service binding injects it |
API_ORIGIN |
Server/build | Local rewrite or two-project fallback | Next.js rewrites browser /api/* requests to this origin |
NEXT_PUBLIC_SOURCE_URL |
Browser | Every hosted fork | Corresponding source for the deployed AGPL version |
NEXT_PUBLIC_E2E_ROUTE_FIXTURE_MODE |
Browser | Fast Playwright suite only | Selects deterministic intercepted UI fixtures |
NEXT_PUBLIC_E2E_FIXTURE_MODE |
Browser | Integrated test only | Selects synthetic auth backed by the real local API/DB |
E2E_FIXTURE_SECRET |
Server | Integrated test only | Signs server-to-API fixture identity; same test authority |
Never enable fixture values in production. API and web code reject or ignore them there, and deployment configuration should remain explicit and clean.
The public /impressum and /privacy pages load operator identity from server environment values. In production, required values fail closed instead of displaying placeholders.
| Variable | Meaning |
|---|---|
LEGAL_OPERATOR_NAME |
Controller/operator's real legal name |
LEGAL_OPERATOR_ADDRESS |
Serviceable postal address; separate lines with the pipe character (|) |
LEGAL_OPERATOR_EMAIL |
Public legal contact email |
LEGAL_PRIVACY_EMAIL |
Privacy/data-subject request contact |
LEGAL_SUPERVISORY_AUTHORITY_NAME |
Competent data-protection authority |
LEGAL_SUPERVISORY_AUTHORITY_URL |
Absolute HTTPS official authority URL |
| Variable | Notes |
|---|---|
LEGAL_OPERATOR_DESCRIPTION |
Plain-language capacity; does not replace the legal name |
LEGAL_OPERATOR_PHONE |
Rendered as a telephone link |
LEGAL_REPRESENTATIVE |
Legal representative |
LEGAL_REGISTER_NAME |
Must be set together with register number |
LEGAL_REGISTER_NUMBER |
Must be set together with register name |
LEGAL_VAT_ID |
VAT identifier |
LEGAL_EDITORIALLY_RESPONSIBLE_NAME |
Must be set together with a complete address |
LEGAL_EDITORIALLY_RESPONSIBLE_ADDRESS |
Pipe-separated (|) address paired with the responsible person |
The repository cannot decide which optional disclosure duties apply to a specific operator. Review the rendered pages and docs/privacy-compliance.md with qualified counsel before launch.
The global Clerk application administrator must configure the instance once:
- Enable Organizations with membership optional. Applicants must be able to hold a verified user session before they belong to an organization.
- Enable organization slugs.
- Disable user-created organizations and automatic first-organization creation. Only global application administrators provision tenants.
- Disable Verified Domain automatic invitations/suggestions and Clerk-native membership requests for this deployment. VA Dispatch owns the tenant-level manual approval queue; enabling a second enrollment path would create inconsistent approval state.
- Enable Clerk Waitlist mode and email delivery. The waitlist is the
application-wide gate for self-service account requests; VA Dispatch still
owns the separate tenant-role application after account creation. Do not
enable Invite-only (
restricted) sign-up mode or the paid allowlist; neither is required for this flow. - Add custom roles with keys
pilotanddispatcher, producingorg:pilotandorg:dispatcher. Include them withorg:adminin the Primary Role Set and makeorg:pilotthe new-member default. - Create the vSAS organization with slug exactly
vsasand setVSAS_CLERK_ORG_IDto its immutable ID. - In the Clerk Account Portal Redirects settings, set the sign-up fallback
to the public
https://<web-origin>/vsas/joinURL. Dashboard-approved waitlist emails use the Account Portal sign-up page by default and do not inherit the application'sClerkProviderURLs. - Set Production
APP_ORIGINto the canonical public web origin so server-created organization invitations return through/vsas/sign-in. Preview uses Vercel's trustedVERCEL_BRANCH_URL, thenVERCEL_URL; keep system environment variables enabled and allowlist the stable Preview branch URL before testing direct invitations. Confirm Clerk's redirect/origin settings cover the tested URL, then acceptance-test the Account Portal waitlist flow, tenant-branded invited sign-up, and direct organization invitation separately.
Do not give tenant administrators Clerk Dashboard team access. Their Clerk
organization role and the VA Dispatch admin role are tenant-scoped; global
instance settings, API keys, tenant provisioning, role definitions, and
Verified Domain policy remain with the global application administrator.
Clerk organization roles map as follows:
| Clerk role suffix | Application role |
|---|---|
admin, owner
|
admin |
dispatcher |
dispatcher |
pilot, member, unknown, or absent |
pilot |
First tenant access provisions the verified org:pilot or org:dispatcher
role. The stored local membership is the runtime authority after provisioning,
and active role changes from the VA Dispatch admin console are synchronized
back to Clerk. The sole recovery exception can promote a verified Clerk
organization Admin when the tenant has no active application Admin. Disabled
or invited local memberships cannot access the application and are not revived
by directory synchronization.
Tenant administrators configure the organization name, allowed application
roles, application open/closed switch, and 7/14/30-day invitation lifetime at
/:slug/settings/organization. They send/revoke invitations, decide
applications, manage roles, and remove members at /:slug/admin.
Global environment selects the provider policy; each tenant stores its own station and encrypted logon.
| Environment | Effective provider |
|---|---|
Development/test with ACARS_PROVIDER=mock
|
DB-backed mock |
Development/preview with ACARS_PROVIDER=hoppie
|
Hoppie |
| Production with any declared value | Hoppie |
Configure the tenant credential through /:slug/settings/organization. The API tests it before saving. Do not put a tenant Hoppie logon into environment variables or source control.
The checked-in vercel.ts defines:
- Vercel Git deployments disabled so GitHub Actions owns validation, readiness, and promotion order;
-
webservice rooted atapps/web; -
apiservice rooted atapps/apiwithsrc/index.tsentrypoint; - a private service binding exposed to web as
API_INTERNAL_URL; -
/api/*routed to API; - all remaining paths routed to web;
-
/api/v1/internal/cron/acars-pollevery minute; and -
/api/v1/internal/cron/privacy-lifecycleevery hour.
GitHub Actions needs the repository secret VERCEL_TOKEN, plus the repository
variables VERCEL_ORG_ID, VERCEL_PROJECT_ID, and
VERCEL_GITHUB_REPOSITORY_ID. Application and database secrets remain
environment-scoped in Vercel. Configure Protection Bypass for Automation in
Vercel; the workflow reads and masks its current value through the project-scoped
token instead of duplicating it in GitHub. After CI succeeds, a default-branch
workflow deploys only internal pull requests and main without checking out
untrusted code while holding the Vercel token. It does not modify the database;
/api/ready confirms connectivity and the tenant/membership schema. Each
Production request disables custom-domain assignment until readiness passes,
then the workflow promotes the staged deployment.
A one-minute cron requires an eligible Vercel plan. If the cron is deployed less frequently, outbound messages still send immediately, but inbound Hoppie traffic appears later.
Before promoting a deployment:
- Load
/health, confirm the database-configured flag and effective ACARS provider, then verify readiness with a synthetic authenticated read. - Create a synthetic account through the tenant URL, submit an application, approve it in the tenant admin UI, select the organization, and confirm URL, Clerk organization, role, and API tenant agree.
- Load
/impressumand/privacy; verify real operator details and all links. - Confirm
NEXT_PUBLIC_SOURCE_URLpoints to the corresponding source of the deployed version. - From an admin account, test the Hoppie ground station.
- Verify BotID Basic and Deep Analysis mutations through the browser.
- Confirm the ACARS cron is succeeding and polling only configured tenants.
- Verify the privacy lifecycle cron and approved policy before execution.
- Verify SimBrief/Navigraph callback URLs and tenant logo storage without exposing credentials.
- Publish a synthetic dispatch release and verify its weather-unavailable fallback as well as the successful provider path where permitted.
- Verify direct pilot/dispatcher invitation, role change, removal, failed- provider retry messaging, and application closed/role-specific policy.
- Issue a synthetic simulator device token, ingest a sequenced sample, verify dispatcher presence/OOOI, then revoke the token.
VA Dispatch repository · OpenAPI source · Security policy · AGPL-3.0-or-later · Simulation use only
VA Dispatch
Using the application
Building and operating
- Architecture
- Authentication and Multi-Tenancy
- Data Model
- API Guide
- Local Development
- Configuration Reference
- Deployment and Operations
- Testing and Quality
- Security and Privacy
Maintaining the project