Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
243 lines (217 loc) · 12.2 KB
/
Copy path.env.example
File metadata and controls
243 lines (217 loc) · 12.2 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
# Accepted values: TESTNET or PUBLIC (Stellar SDK canonical name for mainnet).
# "MAINNET" is also accepted as a legacy alias for "PUBLIC".
# An unrecognized value causes the app to fail fast at startup.
STELLAR_NETWORK=TESTNET
STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
# Multiple endpoints for failover (comma-separated, first is primary)
STELLAR_HORIZON_ENDPOINTS=https://horizon-testnet.stellar.org,https://testnet.stellar.org
SOROBAN_RPC_ENDPOINTS=https://soroban-testnet.stellar.org,https://rpc-testnet.stellar.org
TRUSTFLOW_CONTRACT_ID=
# Stellar timeout configuration (in milliseconds/seconds)
# STELLAR_TX_VALIDITY_SECONDS: how long a release transaction remains valid before being discarded.
# STELLAR_RPC_TIMEOUT_MS: request timeout for Horizon and Soroban RPC operations.
# STELLAR_HEALTH_CHECK_TIMEOUT_MS: timeout for health checks of Stellar endpoints.
# Defaults preserve existing behaviour; adjust for slow/unreliable networks (mainnet: consider 15-30s tx validity).
STELLAR_TX_VALIDITY_SECONDS=60
STELLAR_RPC_TIMEOUT_MS=10000
STELLAR_HEALTH_CHECK_TIMEOUT_MS=5000
# Amount convention: all XLM amounts in the API are decimal strings with up to 7 decimal places
# (e.g., "123.4567890" normalizes to "123.456789"). On-chain, amounts are stroops (1 XLM = 10,000,000 stroops).
# The backend handles conversion automatically; amounts never appear as raw numbers or unconverted stroops in the API.
JWT_SECRET=change-me-before-production
PORT=3001
DISCORD_WEBHOOK_URL=
# Retry configuration for failed Discord dispute notifications (#394)
DISCORD_NOTIFICATION_MAX_RETRIES=3
DISCORD_NOTIFICATION_RETRY_BASE_DELAY_MS=1000
# Platform balance monitoring (#730)
# Stellar account address (G...) to monitor for low balance warnings
STELLAR_PLATFORM_ADDRESS=
# Balance thresholds (XLM) for triggering alerts. Default: 1 XLM (warning), 0.5 XLM (critical)
STELLAR_LOW_BALANCE_THRESHOLD=1
STELLAR_CRITICAL_BALANCE_THRESHOLD=0.5
# Runtime environment: development | production | test. Controls CORS wildcard
# rules, Sentry activation, migration-on-startup, and more.
NODE_ENV=development
# Base URL advertised as the "Development" server in the generated Swagger docs.
API_URL=http://localhost:3001
# Comma-separated Stellar public keys (G...) allowed to hit /admin/* endpoints.
ADMIN_ADDRESSES=
# Sentry error reporting DSN. Empty -> Sentry is disabled (no-op).
SENTRY_DSN=
# Database read replicas (optional — comma-separated PostgreSQL connection strings)
# When set, read-only queries are distributed round-robin across the replicas.
# All writes always go to the primary (DATABASE_URL / DB_HOST).
DATABASE_READ_REPLICAS=
# OpenTelemetry tracing (optional)
# Set OTEL_ENABLED=true and point OTEL_EXPORTER_OTLP_ENDPOINT at your collector
# (OpenTelemetry Collector, Jaeger, Grafana Tempo, etc.) to enable auto-instrumentation.
# Install optional deps first: npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-http
OTEL_ENABLED=false
OTEL_SERVICE_NAME=trustflow-backend
OTEL_EXPORTER_OTLP_ENDPOINT=
OTEL_TRACES_SAMPLER_RATIO=1
# Abuse detection layered on top of the base rate limiter: an identity that
# trips the limit RATE_LIMIT_ABUSE_THRESHOLD times within
# RATE_LIMIT_ABUSE_WINDOW_SECONDS is locked out for RATE_LIMIT_LOCKOUT_SECONDS.
RATE_LIMIT_ABUSE_WINDOW_SECONDS=300
RATE_LIMIT_ABUSE_THRESHOLD=5
RATE_LIMIT_LOCKOUT_SECONDS=900
# What the rate limiter does when Redis is unreachable (command error or timeout):
# allow -> fail open: the request proceeds unthrottled (default). Most routes do not
# otherwise need Redis, so a Redis blip should not take the whole API down.
# deny -> fail closed: the request is rejected with 503 + Retry-After.
# This is only the default. Routes override it with @RateLimitOnRedisError('deny') or
# @RateLimit(points, duration, { onRedisError: 'deny' }); /auth/* is fail-closed by
# default so a Redis outage cannot be used to brute-force the login flow.
RATE_LIMIT_ON_REDIS_ERROR=allow
# Per-IP limits for the auth routes, stricter than the global 100/60s default (#369).
AUTH_CHALLENGE_RATE_LIMIT_POINTS=10
AUTH_CHALLENGE_RATE_LIMIT_DURATION=60
AUTH_VERIFY_RATE_LIMIT_POINTS=10
AUTH_VERIFY_RATE_LIMIT_DURATION=60
# Express 'trust proxy': false (direct), a hop count such as 1 (one load balancer),
# or comma-separated proxy IPs/CIDRs. Needed so the rate limiter sees the client IP.
TRUST_PROXY=false
# Max gig rooms a single WebSocket client may join (#393).
WS_MAX_ROOMS_PER_CLIENT=50
# TTL for stored Idempotency-Key records (see IdempotencyKeyService). Default 24h.
IDEMPOTENCY_KEY_TTL_SECONDS=86400
# Escrow reconciliation sweep — re-checks on-chain escrow state against the DB.
# Milliseconds; 0 or negative disables the background sweep. Default 10 minutes.
ESCROW_RECONCILIATION_SWEEP_INTERVAL_MS=600000
# Maximum concurrent chain reads per reconciliation sweep. Default 8.
ESCROW_RECONCILIATION_SWEEP_CONCURRENCY=8
# CORS configuration — required in production when running with credentials: true
# Set to a comma-separated list of allowed origins, e.g., https://app.example.com,https://admin.example.com
# Wildcard '*' is only allowed in development (NODE_ENV != production)
CORS_ORIGIN=http://localhost:3000
# Redis (required for rate limiting, caching, escrow durability, and distributed coordination).
# See docs/runtime-dependencies.md for what degrades when Redis is absent or unreachable.
REDIS_URL=redis://localhost:6379
# Max milliseconds a single Redis command may wait for a reply before it is rejected.
# Keeps a stalled/unreachable Redis from holding requests open for seconds. Default 1000.
REDIS_COMMAND_TIMEOUT_MS=1000
# Core DB (PostgreSQL) — optional. Set DATABASE_URL, or the discrete DB_HOST/DB_NAME
# pair below, to enable the connection pool. Neither set -> pool is unconfigured and
# GET /health reports database: true (not applicable) rather than degraded.
# See docs/runtime-dependencies.md for current usage and future plans.
DATABASE_URL=
# Discrete alternative to DATABASE_URL (ignored when DATABASE_URL is set):
DB_HOST=
DB_PORT=5432
DB_NAME=
DB_USER=
DB_PASSWORD=
# Set to "true" to connect over TLS. The server certificate is VERIFIED by default.
DB_SSL=false
# PEM CA bundle (inline PEM or a file path) used to verify the server, e.g. the root CA
# downloaded from your managed Postgres provider. Optional client cert/key for mTLS.
DB_SSL_CA=
DB_SSL_CERT=
DB_SSL_KEY=
# Explicit opt-out for local/legacy setups only: "false" skips certificate verification.
# Logged as a warning; refused when NODE_ENV=production.
DB_SSL_REJECT_UNAUTHORIZED=
DB_POOL_MAX=10
DB_POOL_IDLE_TIMEOUT_MS=30000
DB_POOL_CONNECTION_TIMEOUT_MS=5000
# Maximum retry attempts when establishing the initial database connection pool.
DB_RETRY_ATTEMPTS=5
# Base delay (ms) for exponential backoff between connection retries.
DB_RETRY_BACKOFF_MS=1000
# Swagger UI (/api/docs) and OpenAPI JSON (/api/docs-json). Defaults to true outside
# production and false in production. When enabled in production, set both SWAGGER_USER and
# SWAGGER_PASSWORD to protect the docs with HTTP basic auth.
SWAGGER_ENABLED=
SWAGGER_USER=
SWAGGER_PASSWORD=
# Run registered schema migrations automatically on backend startup (see MigrationModule).
# Defaults to enabled outside NODE_ENV=test; set to "false" to disable, e.g. when a
# migration should be triggered manually via POST /migrations/:name/run instead.
RUN_MIGRATIONS_ON_STARTUP=true
# TTL (time-to-live) for completed/failed migration run records in Redis (seconds).
# After a migration run reaches a terminal state (COMPLETED, ROLLED_BACK, FAILED),
# its record is retained for this duration, then automatically expired. Default 30 days.
MIGRATION_RUN_TTL_SECONDS=2592000
# Maximum number of run records to retain per migration name, even within the TTL window.
# Prevents unbounded growth when migrations re-run on every deploy. Default 50.
MIGRATION_MAX_RUNS_PER_NAME=50
# S3-compatible storage for avatar uploads.
# In production all four required vars (S3_BUCKET, S3_REGION, S3_ACCESS_KEY_ID,
# S3_SECRET_ACCESS_KEY) must be set or the app refuses to start (#722).
# Leave unset in local dev to use the no-op placeholder (responses include simulated: true).
S3_BUCKET=
S3_REGION=
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
# Custom endpoint for S3-compatible services (MinIO, Cloudflare R2, etc.). Leave blank for AWS.
S3_ENDPOINT=
# CDN base URL prefix for public avatar URLs. When set, returned URLs use this base
# instead of a pre-signed S3 URL (e.g. https://cdn.example.com).
S3_PUBLIC_URL_BASE=
# IPFS pinning providers (all optional in dev — unconfigured providers run in an
# in-memory simulated mode, so pinning/failover work without any credentials.
# In production, all providers must be configured or the app refuses to start (#409)).
IPFS_PINATA_JWT=
IPFS_WEB3_STORAGE_TOKEN=
IPFS_INFURA_PROJECT_ID=
IPFS_INFURA_PROJECT_SECRET=
# Timeout for IPFS provider HTTP requests (#409). Default 30 seconds.
IPFS_PROVIDER_TIMEOUT_MS=30000
# IPFS repin (reconciliation) sweep interval and concurrency
IPFS_REPIN_INTERVAL_MS=300000
# How many CIDs to reconcile in parallel within one IPFS repin sweep (#237). Default 8.
IPFS_REPIN_SWEEP_CONCURRENCY=8
# Maximum request body size for JSON payloads (in MB).
# The IPFS pin endpoint accepts base64-encoded content; 15 MB provides headroom
# for a 10 MB decoded deliverable (~13.6 MB base64) plus JSON envelope overhead.
BODY_LIMIT_MB=15
# Graceful shutdown — how long to wait for in-flight HTTP requests to complete after
# the process receives SIGTERM/SIGINT, before connections are severed and the process
# exits. On SIGTERM the API first flips /health/ready to 503 so the load balancer stops
# routing new traffic, sheds new requests with 503 + Retry-After, closes the WebSocket
# gateway, then runs Nest's shutdown hooks (ending the PostgreSQL pool) and exits.
# Keep this below your orchestrator's terminationGracePeriodSeconds, or the orchestrator
# will SIGKILL the process mid-drain and defeat it. Default 30 seconds.
SHUTDOWN_TIMEOUT_MS=30000
# Set to false to skip the explicit process.exit() after a clean shutdown. Only useful
# where something else owns the event loop (e.g. a test runner); leaving this unset in
# production can leave the process hanging on a reconnecting Redis client.
SHUTDOWN_FORCE_EXIT=true
# Inbound request timeout (ms). Returns HTTP 408 if a handler exceeds this duration.
# Routes can be exempted via @SkipTimeout() or given a custom timeout with @SkipTimeout(ms).
# Health checks (/health*), metrics (/metrics), and docs (/api/docs*) are always exempt.
# Default 30 seconds.
REQUEST_TIMEOUT_MS=30000
# Webhook outgoing request timeout (ms). Requests that exceed this are aborted
# rather than hanging indefinitely. Defaults to 10 seconds.
WEBHOOK_TIMEOUT_MS=10000
# Transactional outbox webhook relay — how many pending webhook events to fetch and relay per batch.
WEBHOOK_RELAY_BATCH_SIZE=100
# Transactional outbox webhook relay — the Redis lease timeout (ms) to prevent concurrent
# processing of the same event batch on multiple nodes.
WEBHOOK_RELAY_LEASE_MS=30000
# Maximum concurrent webhook deliveries in the WebhookProcessor cron sweep. Default 10.
WEBHOOK_PROCESSOR_CONCURRENCY=10
# Gig expiry sweep — marks unanswered gig solicitations expired past their response deadline
GIG_EXPIRY_SWEEP_INTERVAL_MS=300000
# How many gigs to expire in parallel within one sweep (#236). Default 8.
GIG_EXPIRY_SWEEP_CONCURRENCY=8
# Cap on gigs to expire per sweep (#410). Prevents monopolising a tick with an unbounded
# batch; if capped, the sweep continues on the next tick. Default unlimited.
GIG_EXPIRY_SWEEP_MAX_GIGS=
# How long a paginated GET /gigs search result page stays cached in Redis
GIG_SEARCH_CACHE_TTL_SECONDS=30
# Transactional outbox relay. Redis is required in production so domain updates
# and durable event rows are committed in the same MULTI/EXEC transaction.
OUTBOX_RELAY_INTERVAL_MS=1000
OUTBOX_RELAY_BATCH_SIZE=100
OUTBOX_RELAY_LEASE_MS=30000
# Delivered event body retention in Redis. Failed events are retained without TTL.
OUTBOX_DELIVERED_TTL_SECONDS=604800
# Maximum delivery failures before an event becomes terminally failed.
OUTBOX_MAX_ATTEMPTS=5
# Maximum number of serialized payloads retained in the worker queue.
OUTBOX_QUEUE_MAX_LENGTH=1000