Skip to content

Commit b7ffec4

Browse files
fix: remove unused GIGL keys, harden prod Compose env, complete DEPLOYMENT.md (#1021)
Closes #978 — remove GIGL_API_BASE_URL and GIGL_API_TOKEN from ConfigService.Config and the all-snapshot getter; update the stale GIGL_API_TOKEN comment in logistics.service.ts to LOGISTICS_API_KEY. Closes #983 — fix hardcoded 'trustlink' password in app-prod's DATABASE_URL; now uses ${POSTGRES_PASSWORD} to match db-prod. Closes #982 — pass every production-required variable to app-prod: PRESIGN_SECRET, SYSTEM_SIGNER_SECRET, CONTRACT_ID, FRONTEND_URL, EVIDENCE_STORAGE_BASE_URL, CONTACT_ENCRYPTION_KEY, CREDENTIAL_ENCRYPTION_KEY, STELLAR_WEBHOOK_SECRET, SENTRY_DSN, SOROBAN_RPC_URL, plus STELLAR_NETWORK, ALLOWED_ORIGINS, API_BASE_URL, and the optional SendGrid/Twilio variables. Closes #981 — update DEPLOYMENT.md Environment Rules to list every variable the config schema requires in production (PRESIGN_SECRET, SYSTEM_SIGNER_SECRET, CONTRACT_ID, FRONTEND_URL, EVIDENCE_STORAGE_BASE_URL, CONTACT_ENCRYPTION_KEY, SOROBAN_RPC_URL, SENTRY_DSN); mark SENDGRID_FROM_EMAIL and TWILIO_FROM_NUMBER as conditionally required; update the docker .env example so it would pass schema validation. Co-authored-by: Dev Fashman <jajafwangshak86@gmail.com>
1 parent 58e667b commit b7ffec4

4 files changed

Lines changed: 57 additions & 18 deletions

File tree

‎DEPLOYMENT.md‎

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,28 @@ Set all required variables before running migrations or starting the service:
2323
- `PORT`
2424
- `DATABASE_URL`
2525
- `SEP10_JWT_SECRET`
26+
- `SYSTEM_SIGNER_SECRET` — Stellar secret key used for transaction signing
2627
- `ADMIN_ADDRESS`
2728
- `STELLAR_NETWORK`
28-
- `STELLAR_WEBHOOK_SECRET`
29+
- `STELLAR_WEBHOOK_SECRET` — required in production; validates inbound Stellar webhook payloads
2930
- `REDIS_URL`
3031
- `ALLOWED_ORIGINS`
3132
- `API_BASE_URL`
32-
- `SENDGRID_API_KEY`
33-
- `TWILIO_ACCOUNT_SID`
34-
- `TWILIO_AUTH_TOKEN`
33+
- `PRESIGN_SECRET` — signs evidence pre-signed URLs; must be stable across restarts and replicas
34+
- `CONTRACT_ID` — Soroban escrow contract ID
35+
- `FRONTEND_URL` — required in production
36+
- `EVIDENCE_STORAGE_BASE_URL` — public base URL evidence objects are served from
37+
- `CONTACT_ENCRYPTION_KEY` — 64-character hex string (32 bytes); required in production
38+
- `CREDENTIAL_ENCRYPTION_KEY` — 64-character hex string (32 bytes); required in production
39+
- `SOROBAN_RPC_URL` — required in production; no safe default RPC endpoint exists
40+
- `SENTRY_DSN` — required in production; error reporting endpoint URL
41+
- `SENDGRID_API_KEY` *(optional)* — enable email notifications
42+
- `SENDGRID_FROM_EMAIL` — **required when `SENDGRID_API_KEY` is set**; verified sender address
43+
- `TWILIO_ACCOUNT_SID` *(optional)* — enable SMS notifications
44+
- `TWILIO_AUTH_TOKEN` — required when `TWILIO_ACCOUNT_SID` is set
45+
- `TWILIO_FROM_NUMBER` — **required when `TWILIO_ACCOUNT_SID` is set**; E.164 format
3546
- `OTEL_ENABLED`
3647
- `OTEL_EXPORTER_OTLP_ENDPOINT`
37-
- `CREDENTIAL_ENCRYPTION_KEY` (64-character hex string for logistics API key encryption)
3848

3949
Keep secrets in the deployment platform secret manager. Do not bake them into images, workflow files, or migration scripts.
4050

@@ -53,14 +63,33 @@ The `docker-compose.yml` includes a production profile optimized for production
5363
1. Create a `.env` file with production secrets:
5464
```bash
5565
SEP10_JWT_SECRET=your-production-jwt-secret-at-least-32-chars
56-
ADMIN_ADDRESS=your-admin-stellar-address
66+
SYSTEM_SIGNER_SECRET=Sxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
67+
ADMIN_ADDRESS=Gxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
5768
POSTGRES_PASSWORD=your-secure-postgres-password
58-
CREDENTIAL_ENCRYPTION_KEY=64-character-hex-string-for-encryption
69+
PRESIGN_SECRET=your-cryptographically-random-presign-secret
70+
CONTRACT_ID=your-soroban-contract-id
71+
FRONTEND_URL=https://app.yourdomain.com
72+
EVIDENCE_STORAGE_BASE_URL=https://storage.yourdomain.com
73+
CONTACT_ENCRYPTION_KEY=64-character-hex-string-for-contact-encryption
74+
CREDENTIAL_ENCRYPTION_KEY=64-character-hex-string-for-credential-encryption
75+
STELLAR_NETWORK=MAINNET
76+
STELLAR_WEBHOOK_SECRET=your-stellar-webhook-secret
77+
SENTRY_DSN=https://xxxx@sentry.io/yyyy
78+
SOROBAN_RPC_URL=https://your-soroban-rpc-endpoint
79+
ALLOWED_ORIGINS=https://app.yourdomain.com
80+
API_BASE_URL=https://api.yourdomain.com
5981
OTEL_ENABLED=false
6082
OTEL_EXPORTER_OTLP_ENDPOINT=
83+
# Optional — enable email notifications
84+
# SENDGRID_API_KEY=SG.xxxx
85+
# SENDGRID_FROM_EMAIL=noreply@yourdomain.com
86+
# Optional — enable SMS notifications
87+
# TWILIO_ACCOUNT_SID=ACxxxx
88+
# TWILIO_AUTH_TOKEN=xxxx
89+
# TWILIO_FROM_NUMBER=+15550001234
6190
```
6291

63-
2. Ensure the `CREDENTIAL_ENCRYPTION_KEY` is exactly 64 hex characters (32 bytes). Generate one with:
92+
2. Generate 64-character hex keys for `CONTACT_ENCRYPTION_KEY` and `CREDENTIAL_ENCRYPTION_KEY` with:
6493
```bash
6594
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
6695
```

‎docker-compose.yml‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,31 @@ services:
7777
- "3000:3000"
7878
environment:
7979
- NODE_ENV=production
80-
- DATABASE_URL=postgresql://trustlink:trustlink@db-prod:5432/trustlink_db
80+
- DATABASE_URL=postgresql://trustlink:${POSTGRES_PASSWORD}@db-prod:5432/trustlink_db
8181
- REDIS_URL=redis://redis-prod:6379
8282
- SEP10_JWT_SECRET=${SEP10_JWT_SECRET}
8383
- ADMIN_ADDRESS=${ADMIN_ADDRESS}
84+
- PRESIGN_SECRET=${PRESIGN_SECRET}
85+
- SYSTEM_SIGNER_SECRET=${SYSTEM_SIGNER_SECRET}
86+
- CONTRACT_ID=${CONTRACT_ID}
87+
- FRONTEND_URL=${FRONTEND_URL}
88+
- EVIDENCE_STORAGE_BASE_URL=${EVIDENCE_STORAGE_BASE_URL}
89+
- CONTACT_ENCRYPTION_KEY=${CONTACT_ENCRYPTION_KEY}
90+
- CREDENTIAL_ENCRYPTION_KEY=${CREDENTIAL_ENCRYPTION_KEY}
91+
- STELLAR_WEBHOOK_SECRET=${STELLAR_WEBHOOK_SECRET}
92+
- SENTRY_DSN=${SENTRY_DSN}
93+
- SOROBAN_RPC_URL=${SOROBAN_RPC_URL}
94+
- STELLAR_NETWORK=${STELLAR_NETWORK:-MAINNET}
8495
- OTEL_ENABLED=${OTEL_ENABLED:-false}
8596
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT}
8697
- OTEL_SERVICE_NAME=trustlink-backend
98+
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS}
99+
- API_BASE_URL=${API_BASE_URL}
100+
- SENDGRID_API_KEY=${SENDGRID_API_KEY}
101+
- SENDGRID_FROM_EMAIL=${SENDGRID_FROM_EMAIL}
102+
- TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
103+
- TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
104+
- TWILIO_FROM_NUMBER=${TWILIO_FROM_NUMBER}
87105
depends_on:
88106
db-prod:
89107
condition: service_healthy

‎src/config/config.service.ts‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ export interface Config {
7171
GIT_SHA?: string;
7272
EVIDENCE_UPLOAD_LIMIT?: number;
7373
EVIDENCE_UPLOAD_TTL?: number;
74-
GIGL_API_BASE_URL?: string;
75-
GIGL_API_TOKEN?: string;
7674
SOROBAN_RPC_URL?: string;
7775
/** Always present: the config schema applies a validated default of 5000. */
7876
SOROBAN_POLL_INTERVAL_MS: number;
@@ -171,12 +169,6 @@ export class ConfigService {
171169
),
172170
LOG_LEVEL: this.nestConfigService.get('LOG_LEVEL', { infer: true }),
173171
API_BASE_URL: this.nestConfigService.get('API_BASE_URL', { infer: true }),
174-
GIGL_API_BASE_URL: this.nestConfigService.get('GIGL_API_BASE_URL', {
175-
infer: true,
176-
}),
177-
GIGL_API_TOKEN: this.nestConfigService.get('GIGL_API_TOKEN', {
178-
infer: true,
179-
}),
180172
SOROBAN_POLL_INTERVAL_MS: this.get('SOROBAN_POLL_INTERVAL_MS'),
181173
SOROBAN_RPC_TIMEOUT_MS: this.get('SOROBAN_RPC_TIMEOUT_MS'),
182174
WEBHOOK_EVENT_RETENTION_DAYS: this.get('WEBHOOK_EVENT_RETENTION_DAYS'),

‎src/logistics/logistics.service.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class LogisticsService implements OnModuleInit {
5757
/**
5858
* Loads the logistics API key at startup, preferring a previously rotated
5959
* value persisted in `ProviderCredential` (issue #499) over the
60-
* `GIGL_API_TOKEN` environment variable. The environment variable remains
60+
* `LOGISTICS_API_KEY` environment variable. The environment variable remains
6161
* the fallback for a first boot with nothing stored yet.
6262
*/
6363
private async loadPersistedApiKey(): Promise<void> {

0 commit comments

Comments
 (0)