Configuration
This repo is intentionally “ops-first”: safe defaults, explicit hardening toggles, and predictable failure modes.Store / durability
STORE(memory|pg, default:memory)DATABASE_URL(required whenSTORE=pg)PROXY_PG_SCHEMA(default:public)PROXY_PG_LOG_SLOW_MS(default:0= disabled)
When nonzero, logs slow queries aspg.query.slowwith duration + a best-effort query label (never logs query args).PROXY_MIGRATE_ON_STARTUP(1|0, default:1)
When1, Nooterra runs SQL migrations on startup (PG advisory-lock protected so concurrent instances are safe). Set0if you run migrations out-of-band.PROXY_DATA_DIR(memory mode durability via file tx-log; default: unset = purely in-memory)
HTTP limits
PROXY_MAX_BODY_BYTES(default:1000000)PROXY_INGEST_MAX_EVENTS(default:200)
Protocol / versioning
Nooterra exposes a protocol version contract viax-nooterra-protocol and enforces compatibility windows.
-
PROXY_PROTOCOL_MIN(default: current, e.g.1.0)
Requests below this return426withcode: PROTOCOL_TOO_OLD. -
PROXY_PROTOCOL_MAX(default: current, e.g.1.0)
Requests above this return400withcode: PROTOCOL_TOO_NEW. -
PROXY_PROTOCOL_DEPRECATIONS(optional file path)
JSON map of protocol version -> cutoff date; requests past cutoff return426withcode: PROTOCOL_DEPRECATED. Example:
- When
NODE_ENV=production,/ingest/proxyandPOST /{jobs|robots|operators}/:id/eventsrequire the request headerx-nooterra-protocol(else400withcode: PROTOCOL_VERSION_REQUIRED).
Rate limiting
PROXY_RATE_LIMIT_RPM(default:0= disabled)PROXY_RATE_LIMIT_BURST(default:PROXY_RATE_LIMIT_RPM)PROXY_RATE_LIMIT_PER_KEY_RPM(default:0= disabled)
Applies an additional token bucket per authenticated API key (auth.keyId) after tenant-level limiting.PROXY_RATE_LIMIT_PER_KEY_BURST(default:PROXY_RATE_LIMIT_PER_KEY_RPM)
Outbox reclaim / worker loop
-
PROXY_RECLAIM_AFTER_SECONDS(default:60)
Reclaim “claimed but not processed” outbox rows after this window. -
PROXY_PG_WORKER_STATEMENT_TIMEOUT_MS(default:0= disabled; PG only)
Setsstatement_timeoutfor worker-transaction queries (outbox claims + delivery claims + outbox processors) to prevent “hung query” pileups. -
PROXY_AUTOTICK(1enables a default loop) -
PROXY_AUTOTICK_INTERVAL_MS(default:0, or250whenPROXY_AUTOTICK=1) -
PROXY_AUTOTICK_MAX_MESSAGES(default:100)
-
PROXY_WORKER_CONCURRENCY_ARTIFACTS(default:1)
Max concurrent artifact build groups (grouped bytenantId + jobId). -
PROXY_WORKER_CONCURRENCY_DELIVERIES(default:1)
Max concurrent delivery scope groups (grouped byscopeKey; preserves ordering within each scope). -
PROXY_DELIVERY_HTTP_TIMEOUT_MS(default:0= disabled)
Abort outbound delivery HTTP requests after this timeout and retry with backoff.
Ops / API auth
-
PROXY_OPS_TOKENS
Format:token:scope1,scope2;token2:scopeA(scopes includeops_read,ops_write,audit_read,finance_write, …) -
PROXY_OPS_TOKEN(legacy)
IfPROXY_OPS_TOKENSis empty, this single token grants full ops access. -
PROXY_AUTH_KEY_TOUCH_MIN_SECONDS(default:60)
Throttle how oftenlast_used_atis updated for API keys (reduces DB write amplification).
Public onboarding routing
-
PROXY_ONBOARDING_BASE_URL(optional but required for public onboarding onnooterra-api)
Absolutehttp(s)URL for the onboarding service (services/magic-link). When set,nooterra-apireverse-proxies public onboarding routes:/v1/public/auth-mode/v1/public/signup/v1/tenants/:tenantId/buyer/login/otp/v1/tenants/:tenantId/buyer/login/v1/tenants/:tenantId/onboarding/*
503and codeONBOARDING_PROXY_NOT_CONFIGURED.
Ingest auth
PROXY_INGEST_TOKEN(optional)
When set,/ingest/proxyrequires headerx-proxy-ingest-tokento match.
Export destinations (deliveries)
PROXY_EXPORT_DESTINATIONS(JSON)
MapstenantId -> destinations[].
- Inline secrets (
secret,accessKeyId,secretAccessKey) are rejected whenNODE_ENV=productionunlessPROXY_ALLOW_INLINE_SECRETS=1.
Evidence store
PROXY_EVIDENCE_STORE(fs|memory|s3|minio, default:fs)PROXY_EVIDENCE_DIR(fs store root; default: tmp dir when not usingPROXY_DATA_DIR)
PROXY_EVIDENCE_S3_ENDPOINTPROXY_EVIDENCE_S3_REGION(default:us-east-1)PROXY_EVIDENCE_S3_BUCKETPROXY_EVIDENCE_S3_ACCESS_KEY_ID(orAWS_ACCESS_KEY_ID)PROXY_EVIDENCE_S3_SECRET_ACCESS_KEY(orAWS_SECRET_ACCESS_KEY)PROXY_EVIDENCE_S3_FORCE_PATH_STYLE(default:1)
PROXY_EVIDENCE_SIGNING_SECRET(optional; default derived from server signer)PROXY_EVIDENCE_PRESIGN_MAX_SECONDS(default:300, max:3600)PROXY_EVIDENCE_RETENTION_MAX_DAYS(default:365)
Tenant cap forcontract.policies.evidencePolicy.retentionDays.PROXY_EVIDENCE_RETENTION_MAX_DAYS_BY_TENANT(JSON map, optional)
Per-tenant override forPROXY_EVIDENCE_RETENTION_MAX_DAYS.
Secrets provider
PROXY_ENABLE_ENV_SECRETS(1enablesenv:NAMErefs; default: disabled unlessNODE_ENV=development)PROXY_SECRETS_CACHE_TTL_SECONDS(default:30)
env:NAME(dev-only unless explicitly enabled)file:/absolute/path(k8s secret mounts)
URL safety overrides (dev only)
These exist to make local development possible (e.g. MinIO onlocalhost). Do not enable in production.
PROXY_ALLOW_HTTP_URLS(1allowshttp://where URL safety checks apply)PROXY_ALLOW_PRIVATE_URLS(1allows private IP ranges)PROXY_ALLOW_LOOPBACK_URLS(1allowslocalhost/ loopback)
Retention / cleanup
Retention is tenant-configurable via in-memory config and capped by these runtime env vars.-
PROXY_RETENTION_INGEST_RECORDS_DAYS(default:0= no expiry)
Setsexpires_atforingest_records. -
PROXY_RETENTION_INGEST_RECORDS_MAX_DAYS(default:0= no platform cap)
When set, tenant0means “use the cap”. -
PROXY_RETENTION_DELIVERIES_DAYS(default:0= no expiry)
Expiration for delivered deliveries. -
PROXY_RETENTION_DELIVERIES_MAX_DAYS(default:0= no platform cap) -
PROXY_RETENTION_DELIVERY_DLQ_DAYS(default:PROXY_RETENTION_DELIVERIES_DAYS)
Expiration for failed (DLQ) deliveries. -
PROXY_RETENTION_DELIVERY_DLQ_MAX_DAYS(default:PROXY_RETENTION_DELIVERIES_MAX_DAYS)
-
PROXY_RETENTION_CLEANUP_BATCH_SIZE(default:500)
Max rows per table per cleanup run. -
PROXY_RETENTION_CLEANUP_MAX_MILLIS(default:1500)
Wall-clock budget for a single cleanup run (enforced via PGstatement_timeout). -
PROXY_RETENTION_CLEANUP_DRY_RUN(1prints would-delete counts; no deletes)
-
PROXY_FINANCE_RECONCILE_ENABLED(default:1)
Enables periodic finance reconciliation maintenance ticks. -
PROXY_FINANCE_RECONCILE_INTERVAL_SECONDS(default:300)
Minimum interval between automatic reconciliation runs. -
PROXY_FINANCE_RECONCILE_MAX_TENANTS(default:50)
Max tenants scanned per automatic run. -
PROXY_FINANCE_RECONCILE_MAX_PERIODS_PER_TENANT(default:2)
Max GL periods reconciled per tenant in one run.
-
PROXY_MONEY_RAIL_RECONCILE_ENABLED(default:1)
Enables periodic money-rail reconciliation maintenance ticks. -
PROXY_MONEY_RAIL_RECONCILE_INTERVAL_SECONDS(default:300)
Minimum interval between automatic money-rail reconciliation runs. -
PROXY_MONEY_RAIL_RECONCILE_MAX_TENANTS(default:50)
Max tenants scanned per automatic run. -
PROXY_MONEY_RAIL_RECONCILE_MAX_PERIODS_PER_TENANT(default:2)
Max payout periods reconciled per tenant in one run. -
PROXY_MONEY_RAIL_RECONCILE_MAX_PROVIDERS_PER_TENANT(default:10)
Max money-rail providers reconciled per tenant in one run.
PROXY_MAINTENANCE_INTERVAL_SECONDS(default:300)
Sleep between cleanup runs insrc/api/maintenance.js.
Quotas / backpressure
On quota breach, requests return429 with code: TENANT_QUOTA_EXCEEDED.
-
PROXY_QUOTA_MAX_OPEN_JOBS(default:0= unlimited) -
PROXY_QUOTA_PLATFORM_MAX_OPEN_JOBS(default:0= no platform cap) -
PROXY_QUOTA_MAX_PENDING_DELIVERIES(default:0= unlimited) -
PROXY_QUOTA_PLATFORM_MAX_PENDING_DELIVERIES(default:0= no platform cap) -
PROXY_QUOTA_MAX_INGEST_DLQ_DEPTH(default:0= unlimited) -
PROXY_QUOTA_PLATFORM_MAX_INGEST_DLQ_DEPTH(default:0= no platform cap) -
PROXY_QUOTA_MAX_EVIDENCE_REFS_PER_JOB(default:0= unlimited) -
PROXY_QUOTA_PLATFORM_MAX_EVIDENCE_REFS_PER_JOB(default:0= no platform cap) -
PROXY_QUOTA_MAX_ARTIFACTS_PER_JOB_TYPE(default:0= unlimited) -
PROXY_QUOTA_PLATFORM_MAX_ARTIFACTS_PER_JOB_TYPE(default:0= no platform cap)
Outbox poison-pill
PROXY_OUTBOX_MAX_ATTEMPTS(default:25)
After this many attempts, outbox work is marked done with a DLQ error marker.
Evidence ingest constraints (optional hardening)
-
PROXY_EVIDENCE_CONTENT_TYPE_ALLOWLIST(comma-separated)
If set,EVIDENCE_CAPTURED.payload.contentTypemust be in the allowlist. -
PROXY_EVIDENCE_REQUIRE_SIZE_BYTES(1requiresEVIDENCE_CAPTURED.payload.sizeBytes) -
PROXY_EVIDENCE_MAX_SIZE_BYTES(default:0= unlimited)
Backups / restore (Postgres)
These helper scripts assume you have Postgres client tools installed (pg_dump, pg_restore, psql).
-
Backup:
-
Restore (to a fresh DB is recommended):
-
Verify a restored DB:
VERIFY_MAX_STREAMS(default:100)VERIFY_MAX_ARTIFACTS(default:100)VERIFY_MAX_LEDGER_ENTRIES(default:0= all)
- RPO is the time between successful backups.
- RTO is
restore time + verification timeand scales with DB size.