Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
153 lines (128 loc) · 7.31 KB
/
Copy path.env.example
File metadata and controls
153 lines (128 loc) · 7.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# See README.md. This service delegates authentication entirely to an
# external OIDC provider — it holds no credentials of its own.
# Required. Your identity provider's issuer URL — e.g.
# Cognito: https://cognito-idp.<region>.amazonaws.com/<userPoolId>
# Keycloak: https://<host>/realms/<realm>
OIDC_ISSUER=
# Required. Checked against every token's `aud` claim — the identifier
# your IdP assigns to *this API* as a protected resource (not a client ID).
# Without this, a validly-signed ID token (or an access token minted for a
# different client of the same IdP) would be accepted here as if it were a
# genuine access token for this API.
OIDC_AUDIENCE=
# Optional. Skips OIDC discovery and uses this JWKS URI directly — set this
# if your IdP doesn't expose /.well-known/openid-configuration, or for
# faster/offline-safe local development against a fixed JWKS.
OIDC_JWKS_URI=
# Optional, default none. JSON array of {issuer, audience, jwksUri?} to
# accept tokens from more than one IdP at once — see README.md's "Multiple
# identity providers, proxies, and custom certificate authorities."
# OIDC_ADDITIONAL_ISSUERS=[{"issuer":"https://idp-b.example.org","audience":"modelforge-iam-server-b"}]
OIDC_ADDITIONAL_ISSUERS=
# Optional. If your network requires an outbound HTTP(S) proxy or your IdP
# presents a certificate from an internal/self-signed CA, these are Node.js
# runtime capabilities, not something this service configures itself — see
# README.md's "Multiple identity providers, proxies, and custom certificate
# authorities" for details.
# NODE_OPTIONS=--use-env-proxy
# HTTPS_PROXY=https://proxy.example.org:8080
# NODE_EXTRA_CA_CERTS=/path/to/your-ca-bundle.pem
# Optional, default 4000.
PORT=4000
# Optional. postgres://user:password@host:port/database — if unset, the
# service runs on InMemoryIamStore and loses all IAM data on restart. See
# server/README.md's "Known gaps." Migrations (server/migrations/*.sql) run
# automatically at startup when this is set.
DATABASE_URL=
# Optional. When set, DATABASE_URL is used only to run migrations (a
# migration-owner role: CREATE SCHEMA/CREATE FUNCTION/ALTER DEFAULT
# PRIVILEGES) and the running application connects to Postgres as *this*
# role instead — a separate, restricted runtime role (NO BYPASSRLS, can't
# CREATE SCHEMA; see migrations/010_runtime_role_grants.sql and
# README.md's "Role separation" section). Unset (the default) means
# DATABASE_URL is used for both, exactly as before this setting existed.
RUNTIME_DATABASE_URL=
# Optional. Exact origin (scheme+host+port) of a deployed admin-console web
# app to allow via CORS, e.g. https://admin.example-hospital.org. Unset
# (the default) means CORS is fully off — this API has no CORS support
# otherwise, so a browser blocks every cross-origin fetch() from any web
# page regardless of any other header. Only one origin is supported.
ADMIN_CONSOLE_ORIGIN=
# --- Observability (src/metrics.ts, GET /metrics) ---
# See docs/OBSERVABILITY.md. Prometheus exposition text: HTTP/authz-decision/
# audit-write latency histograms, audit-write outcome counts, authorization-
# cache stats, and Node.js process metrics. Deliberately metadata-only/
# PHI-free (route *patterns*, never a patient/case/session/user/org id), so
# it's open by default like GET /health.
# Optional. When set, GET /metrics requires `Authorization: Bearer <token>`
# to match exactly. Defense in depth only — the real boundary a production
# deployment should rely on is network-level (don't route the public
# internet to /metrics at all).
METRICS_TOKEN=
# Ed25519 SPKI public key used to verify organization-bound compute resource
# policies. Preserve PEM newlines using your deployment platform's secret/
# config mechanism. When unset or malformed, policy creation fails closed.
COMPUTE_POLICY_PUBLIC_KEY_PEM=
# --- Caching (src/cache/, src/store/caching-iam-store.ts) ---
# Every authenticated request resolves the caller's user record and full
# effective policy set at least once; caching those reads is on by default.
# See README.md's "Caching" section for backends, negative caching,
# invalidation, degraded-mode/recovery, and observability.
# Optional. Set to "1" to run with no cache at all (every request hits
# DATABASE_URL directly) — useful when debugging a permissions issue you
# want to rule caching in/out of.
CACHE_DISABLE=
# Optional, default 30000 (30s). How long a cached read stays fresh, on top
# of this service's own invalidation on writes — see
# caching-iam-store.ts's class doc comment. Validated at startup: must be a
# whole number of milliseconds between 1000 (1s) and 3600000 (1h) — this is
# an authorization cache, so both bounds are deliberate safety limits, not
# just performance guidance. A malformed or out-of-range value fails
# startup with a clear error rather than silently never expiring (or always
# expiring) every cache entry.
CACHE_TTL_MS=
# Optional, default 5000 (5s), capped at whatever CACHE_TTL_MS resolves to.
# How long findUserByExternalSubject's negative-cache entries ("no account
# for this identity in this organization") stay fresh — deliberately much
# shorter than CACHE_TTL_MS, since that lookup runs on every request to an
# org-scoped route and a "no account" result is the one negative lookup
# result this service caches at all. Validated the same way as
# CACHE_TTL_MS, and additionally rejected if set higher than CACHE_TTL_MS
# (a "shorter" TTL that's actually longer would defeat its own purpose).
CACHE_NEGATIVE_TTL_MS=
# Optional. redis://[:password@]host:port[/db]. If unset, caching falls
# back to an in-memory cache local to this process (fine for local dev and
# a single-instance deployment). Set this for a multi-instance deployment
# so every instance shares one coherent cache instead of each carrying its
# own. `docker compose up -d redis` (docker-compose.yml, this directory)
# runs one locally at redis://localhost:6379. If Redis becomes unreachable,
# caching degrades safely (falls through to the database) rather than
# serving stale authorization data — see README.md's "Failure mode: Redis
# unreachable" for the exact guarantee and automatic recovery path. A
# deployment running against Redis should also set Redis's own `maxmemory`
# + `maxmemory-policy` (e.g. `volatile-lru`) — this service does not cap
# Redis-side cache size itself.
REDIS_URL=
# --- Postgres connection pool (src/index.ts) — only relevant when
# DATABASE_URL is set. All optional; defaults are conservative, not tuned
# for any specific deployment size.
# Default 10. Caps concurrent Postgres connections this process holds.
POOL_MAX=
# Default 10000 (10s). How long to wait for a new connection to Postgres
# before failing that acquisition.
POOL_CONNECTION_TIMEOUT_MS=
# Default 30000 (30s). How long an idle pooled connection is kept open
# before it's closed.
POOL_IDLE_TIMEOUT_MS=
# Default 30000 (30s). Postgres-side `statement_timeout` for every query —
# bounds how long one slow/blocked query (e.g. lock contention) can hold a
# connection.
POOL_STATEMENT_TIMEOUT_MS=
# --- Rate limiting (src/app.ts, @fastify/rate-limit) ---
# Global per-client-IP request cap, always on. GET /health is exempt (an
# orchestrator's liveness/readiness probe shouldn't compete with real
# traffic for the same budget).
# Default 300 requests per RATE_LIMIT_WINDOW_MS, per IP.
RATE_LIMIT_MAX=
# Default 60000 (1 minute).
RATE_LIMIT_WINDOW_MS=