forked from CredenceOrg/Credence-Backend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
313 lines (274 loc) · 17.9 KB
/
Copy path.env.example
File metadata and controls
313 lines (274 loc) · 17.9 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# ──────────────────────────────────────────────
# Credence Backend – Environment Variables
# Copy this file: cp .env.example .env
# ──────────────────────────────────────────────
# --- App ---
NODE_ENV=development
PORT=3000
# --- PostgreSQL ---
POSTGRES_USER=credence
POSTGRES_PASSWORD=credence
POSTGRES_DB=credence
POSTGRES_PORT=5432
# Composed automatically in docker-compose; override for non-Docker use:
# DATABASE_URL=postgres://credence:credence@localhost:5432/credence
# --- Redis ---
REDIS_PORT=6379
# REDIS_URL=redis://localhost:6379
# Exactly 32 characters for AES-256-GCM
EVIDENCE_ENCRYPTION_KEY="12345678901234567890123456789012"
# =============================================================================
# Credence Backend – Environment Variables
# =============================================================================
# Copy this file to .env and fill in the values for local development.
# cp .env.example .env
# =============================================================================
# ── Server ───────────────────────────────────────────────────────────────────
PORT=3000
NODE_ENV=development
LOG_LEVEL=info
# ── Dev Mode ────────────────────────────────────────────────────────────────
# Enables dev-only endpoints (e.g. fault injection for chaos testing).
# Must NOT be set to "true" in production.
DEV_MODE=false
# ── Global Request Timeout ───────────────────────────────────────────────────
# The global timeout budget for a single request across all downstream calls.
# If this is exceeded, subsequent internal operations (like DB or HTTP calls)
# will fail fast. Default: 30000 (30 seconds)
# TIMEOUT_GLOBAL_MS=30000
# ── Database ─────────────────────────────────────────────────────────────────
DB_URL=postgresql://user:password@localhost:5432/credence
# ── Testing ──────────────────────────────────────────────────────────────────
# When set, integration tests skip testcontainers and connect to this URL directly.
# Required in CI where a managed PostgreSQL service is provided.
# Example (matches docker-compose.test.yml defaults):
# TEST_DATABASE_URL=postgresql://credence:credence@localhost:5433/credence_test
# TEST_DATABASE_URL=
# Reset drop/create/migrate: npm run test:db:reset (see docs/local-testing-guide.md)
# ── Database Pool Tuning ─────────────────────────────────────────────────────
# Maximum connections in the API pool (default: 20)
DB_POOL_MAX=20
# Per-tenant cap for concurrent DB clients before the request is rejected with
# a typed budget error; prevents one tenant from draining shared pool capacity.
# Default: 5
DB_TENANT_CONNECTION_BUDGET=5
# Milliseconds a client can sit idle before being closed (default: 30000)
DB_POOL_IDLE_TIMEOUT_MS=30000
# Milliseconds to wait for a connection before erroring (default: 5000)
DB_POOL_CONNECTION_TIMEOUT_MS=5000
# Default per-statement timeout in milliseconds; kills runaway queries (default: 30000)
DB_STATEMENT_TIMEOUT_MS=30000
# Maximum connections in the worker pool for background jobs (default: 5)
DB_WORKER_POOL_MAX=5
# Maximum connections in the read-replica pool. Optional — falls back to
# DB_POOL_MAX when unset, so most setups don't need to touch this.
# DB_REPLICA_POOL_MAX=20
# Maximum acceptable replication lag (ms) before reads fall back to the
# primary pool (default: 1000)
MAX_REPLICA_LAG_MS=1000
# Minimum query duration (ms) that triggers a slow-query log entry with the
# query's EXPLAIN plan attached. Set to 0 to disable. (default: 1000)
SLOW_QUERY_THRESHOLD_MS=1000
# Maximum number of distinct query-text shapes tracked per pool (api/worker/
# replica) in the prepared-statement name cache. Bounds server-side prepared-
# statement memory; evicted queries still work, just without server-side
# reuse until they're queried often enough to re-enter the cache. Sustained
# db_prepared_statement_cache_size near this value indicates cache-miss
# thrash. (default: 200)
DB_PREPARED_STATEMENT_CACHE_MAX=200
# ── Long Transaction Reaper ──────────────────────────────────────────────────
# Defence-in-depth guard: periodically scans pg_stat_activity and calls
# pg_terminate_backend() on any client backend that has held a transaction
# open longer than DB_LONG_TRANSACTION_MAX_AGE_MS. DB_STATEMENT_TIMEOUT_MS
# alone does not cover this — it resets on every new statement, so it never
# fires for an idle-in-transaction session or a transaction made of many
# fast statements separated by slow app-level work. Either shape holds
# row/table locks and blocks autovacuum indefinitely, which starves other
# connections behind those locks and saturates the pool (a "hold-off
# cascade"). See src/jobs/longTransactionReaper.ts.
# Master on/off switch (default: true)
DB_LONG_TRANSACTION_REAPER_ENABLED=true
# Transactions open longer than this are terminated, in ms (default: 30000)
DB_LONG_TRANSACTION_MAX_AGE_MS=30000
# How often to scan pg_stat_activity, in ms (default: 10000)
DB_LONG_TRANSACTION_REAPER_INTERVAL_MS=10000
# When true, over-age transactions are logged/counted but not terminated (default: false)
DB_LONG_TRANSACTION_REAPER_DRY_RUN=false
# ── Redis ────────────────────────────────────────────────────────────────────
REDIS_URL=redis://localhost:6379
# ── Authentication ───────────────────────────────────────────────────────────
# Must be at least 32 characters
JWT_SECRET=change-me-to-a-secure-random-string-at-least-32-chars
JWT_EXPIRY=1h
# ── JWT Key Rotation ─────────────────────────────────────────────────────────
# How often (seconds) to rotate the active signing key. Default: 86400 (24 h).
KEY_ROTATION_INTERVAL_SECONDS=86400
# Max-age (seconds) for the Cache-Control header on the JWKS endpoint.
# Default: 300 (5 minutes).
# JWKS_CACHE_MAX_AGE_SECONDS=300
# How long (seconds) a retired key stays valid for JWT verification after
# rotation, allowing tokens signed before the rotation to remain verifiable.
# Default: 3600 (1 h).
KEY_GRACE_PERIOD_SECONDS=3600
# Clock skew tolerance (seconds). Added to the grace window before a retired
# key is hard-pruned, and passed as clockTolerance to jwtVerify() so tokens
# from slightly-fast issuer clocks are still accepted. Default: 300 (5 min).
KEY_CLOCK_SKEW_SECONDS=300
#
# Optional: pre-load a PKCS8 PEM-encoded RSA private key as the initial signing key.
# When set, the server imports this key on startup instead of generating a new one,
# ensuring tokens remain valid across restarts. The rotation scheduler still applies.
# Generate with: openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt
# In production, inject this via your secret manager (Vault, AWS Secrets Manager, etc.)
# KEY_PRIVATE_PEM="-----BEGIN PRIVATE KEY-----\nMII...\n-----END PRIVATE KEY-----"
#
# Optional stable kid for the key loaded from KEY_PRIVATE_PEM. Defaults to a random UUID.
# KEY_INITIAL_KID=my-key-v1
# ── Feature Flags ────────────────────────────────────────────────────────────
ENABLE_TRUST_SCORING=false
ENABLE_BOND_EVENTS=false
# ── Feature Flag Service (issue #570) ────────────────────────────────────────
# In-process cache TTL for feature flags, overrides, and per-tenant rollouts
# (milliseconds). Lower values reduce stale-flag window; higher values reduce DB load.
# Default: 30000 (30 seconds).
# FLAG_CACHE_TTL_MS=30000
# ── Outbox Pattern ───────────────────────────────────────────────────────────
OUTBOX_ENABLED=true
OUTBOX_POLL_INTERVAL_MS=1000
OUTBOX_BATCH_SIZE=100
OUTBOX_PUBLISHED_RETENTION_DAYS=7
OUTBOX_FAILED_RETENTION_DAYS=30
OUTBOX_CLEANUP_INTERVAL_MS=3600000
# ── Outbox Worker Leadership Lease ───────────────────────────────────────────
# When enabled, a Postgres advisory lock ensures only one outbox publisher
# instance runs at a time. Other instances stay in standby and take over
# automatically if the leader's connection dies.
OUTBOX_LEADER_LEASE_ENABLED=false
# How often (ms) a standby instance retries acquiring the lock. Default: 5000.
OUTBOX_LEADER_LEASE_RETRY_MS=5000
# How often (ms) the leader verifies its connection is alive. Default: 10000.
OUTBOX_LEADER_LEASE_HEARTBEAT_MS=10000
# ── Report Storage ────────────────────────────────────────────────────────────
# Signing secret for HMAC-signed report artifact download URLs.
# Must be non-empty; recommended length ≥ 32 characters.
REPORT_STORAGE_SIGNING_SECRET=change-me-report-storage-signing-32char
# Base URL for report artifact downloads (used in signed URL construction).
# Default: https://credence.example.com
# REPORT_DOWNLOAD_BASE_URL=https://credence.example.com
# ── Horizon (optional) ──────────────────────────────────────────────────────
# HORIZON_URL=https://horizon-testnet.stellar.org
# ── CORS ─────────────────────────────────────────────────────────────────────
# Allowed origins for CORS. Wildcard (*) is allowed in dev/test, but prohibited in production.
# In production, configure this as a single domain or comma-separated list of approved domains.
# Example: CORS_ORIGIN=https://app.credence.io
CORS_ORIGIN=*
# ── Admin Redirect Allowlist ─────────────────────────────────────────────────
# Comma-separated list of hosts (hostname[:port]) that admin routes are
# permitted to redirect to as an absolute URL. Same-origin relative paths
# (e.g. /dashboard) are always allowed and do not need to be listed here.
# Leave unset to only allow relative redirects (recommended default).
# Example: ADMIN_REDIRECT_ALLOWED_HOSTS=admin.credence.io,partner.credence.io
# ADMIN_REDIRECT_ALLOWED_HOSTS=
# ── Database Lock Timeouts (milliseconds) ────────────────────────────────────
# Timeout for read-only queries with minimal contention tolerance
DB_LOCK_TIMEOUT_READONLY=2000
# Timeout for standard read-modify-write operations
DB_LOCK_TIMEOUT_DEFAULT=5000
# Timeout for critical flows requiring extended wait
DB_LOCK_TIMEOUT_CRITICAL=10000
# ── Analytics Materialized View Refresh ──────────────────────────────────────
ANALYTICS_REFRESH_CRON=*/5 * * * *
ANALYTICS_STALENESS_SECONDS=300
# ── Compression ──────────────────────────────────────────────────────────────
# Minimum response size (in bytes) to trigger compression. Default: 1024 (1 KB).
COMPRESSION_THRESHOLD=1024
# ── Soroban RPC ───────────────────────────────────────────────────────────────
# Circuit-breaker thresholds for the Soroban RPC client
# Number of consecutive failures before the breaker trips (opens). Default: 5.
# SOROBAN_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
#
# How long (ms) the breaker stays OPEN and rejects all requests immediately
# after tripping (fail-fast window). Default: 10000 ms (10 s).
# SOROBAN_CIRCUIT_BREAKER_OPEN_WINDOW_MS=10000
#
# How long (ms) after tripping before a single probe request is allowed
# through to test whether the RPC has recovered. Must be ≥ OPEN_WINDOW_MS.
# Default: 30000 ms (30 s).
# SOROBAN_CIRCUIT_BREAKER_HALF_OPEN_AFTER_MS=30000
#
# DEPRECATED: use SOROBAN_CIRCUIT_BREAKER_HALF_OPEN_AFTER_MS instead.
# Kept for backwards compatibility; maps to halfOpenAfterMs when the new
# variable is absent.
# SOROBAN_CIRCUIT_BREAKER_COOLDOWN_MS=30000
#
# Short-TTL read-through cache for getIdentityState().
# Keyed by network + contractId + address; only successful responses cached.
# Set to 0 to disable. Default: 5000 ms (5 seconds).
# SOROBAN_STATE_CACHE_TTL_MS=5000
# ── Bond / Attestation Caches ────────────────────────────────────────────────
# Redis cache TTL (seconds) for bond lookups by id/identity. Default: 300 (5 min).
# BOND_CACHE_TTL_SECONDS=300
# Redis cache TTL (seconds) for attestation lookups by id/subject/bond. Default: 300 (5 min).
# ATTESTATION_CACHE_TTL_SECONDS=300
# Version identifier for the scoring model (recorded in score snapshots)
REPUTATION_MODEL_VERSION=1.0.0
# Maximum points for bond amount component (default: 50, achieved at ≥ 1 ETH)
REPUTATION_BOND_SCORE_MAX=50
# Maximum points for bond duration component (default: 20, achieved at ≥ 365 days)
REPUTATION_DURATION_SCORE_MAX=20
# Maximum points for attestation component (default: 30, achieved at ≥ 5 attestations)
REPUTATION_ATTESTATION_SCORE_MAX=30
# 1 ETH in wei (default: 1000000000000000000)
REPUTATION_ONE_ETH_WEI=1000000000000000000
# Maximum duration in days for full duration score (default: 365)
REPUTATION_MAX_DURATION_DAYS=365
# Maximum attestation count for full attestation score (default: 5)
REPUTATION_MAX_ATTESTATION_COUNT=5
# ── Per-Tenant Defaults ────────────────────────────────────────────────────────
# These values serve as the default configuration for any tenant that does not
# have an explicit per-tenant override stored in the database (e.g. via the
# tenant_rate_limit_overrides table). Sane defaults are provided; override them
# here to change the baseline for all tenants at the deployment level.
# Default rate-limit (max requests) per tenant when no DB override exists.
# Default: 100
# TENANT_DEFAULT_RATE_LIMIT=100
# Default rate-limit window (seconds) per tenant when no DB override exists.
# Default: 60
# TENANT_DEFAULT_RATE_LIMIT_WINDOW_SEC=60
# Per-tenant rate limits for auth login / refresh (brute-force protection).
# Default: enabled, 20 requests per 60s window per tenant (IP fallback when tenant unknown).
# AUTH_RATE_LIMIT_ENABLED=true
# AUTH_RATE_LIMIT_WINDOW_SEC=60
# AUTH_RATE_LIMIT_MAX_PER_TENANT=20
# AUTH_RATE_LIMIT_FAIL_OPEN=true
# Default per-tenant DB connection budget cap — prevents one tenant from
# draining the shared pool. Should align with DB_TENANT_CONNECTION_BUDGET.
# Default: 5
# TENANT_DEFAULT_CONNECTION_BUDGET=5
# Default monthly credits allocated to new tenants.
# Default: 10000
# TENANT_DEFAULT_MONTHLY_CREDITS=10000
# Default low-credit threshold below which the system emits warnings for a tenant.
# Default: 100
# TENANT_DEFAULT_LOW_CREDIT_THRESHOLD=100
# ── Node.js Memory Configuration ─────────────────────────────────────────────
# Maximum old space size in MB. If set, starts node with --max-old-space-size
# Example: NODE_MAX_OLD_SPACE_SIZE_MB=2048 (2 GB)
# NODE_MAX_OLD_SPACE_SIZE_MB=
# ── Feature Flags ────────────────────────────────────────────────────────────
# Toggles the new pipeline logic
NEW_PIPELINE=false
# ── Expired Sessions Sweeper ─────────────────────────────────────────────────
# TTL in seconds for session rows. Expired rows are pruned by the sweeper.
# Default: 86400 (24 hours). Min: 60, Max: 2592000 (30 days).
# SESSION_TTL_SECONDS=86400
# Interval in ms between sweeper runs. Default: 3600000 (1 hour). Min: 60000.
# SESSION_SWEEP_INTERVAL_MS=3600000
# ── Response Compression ──────────────────────────────────────────────────────
# Master switch for the response-compression middleware (gzip / deflate / brotli).
# When false, no response body is ever compressed. Default: true.
# COMPRESSION_ENABLED=true
# Minimum response body size in bytes before compression kicks in. Smaller
# responses are sent uncompressed — the gzip header overhead exceeds the
# savings for tiny payloads. Default: 1024. Range: 0–10485760 (0–10 MiB).
# COMPRESSION_THRESHOLD_BYTES=1024