mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
216 lines
9.4 KiB
Plaintext
216 lines
9.4 KiB
Plaintext
# Copy to .env for local/docker compose (not committed).
|
|
PORT=3001
|
|
# @tria-plc/auditlog's client interceptor stamps every AuditLog row's
|
|
# `application` from this env var directly, bypassing MezgebModule.forRoot's
|
|
# applicationName option (package quirk). audit.controller.ts reads the same
|
|
# var when filtering reads, so this can be anything as long as it's set.
|
|
APPLICATION_NAME=freight-api
|
|
# Also required for @tria-plc/auditlog: its producer (AuditClientModule)
|
|
# reads the RMQ URL at package IMPORT time, before MezgebModule.forRoot's
|
|
# rmqUrl option ever runs, so only an env var reaches it — an in-code
|
|
# override is too late. Without this, audit events are silently dropped
|
|
# (no error, nothing published). Point it at whatever broker/vhost your
|
|
# RabbitMQ actually has a user provisioned on.
|
|
RABBITMQ_URL=amqp://localhost:5672
|
|
# GT06 GPS tracker TCP listener port (raw TCP, must be reachable by tracker SIMs). 0 disables.
|
|
GT06_TCP_PORT=5023
|
|
DB_HOST=localhost
|
|
DB_PORT=5433
|
|
DB_USER=postgres
|
|
DB_PASSWORD=
|
|
DB_NAME=edr_freight
|
|
|
|
# Telebirr payment gateway (freight merchant credentials)
|
|
TELEBIRR_BASE_URL=
|
|
TELEBIRR_WEB_BASE_URL=
|
|
TELEBIRR_FABRIC_APP_ID=
|
|
TELEBIRR_APP_SECRET=
|
|
TELEBIRR_MERCHANT_APP_ID=
|
|
TELEBIRR_MERCHANT_CODE=
|
|
TELEBIRR_NOTIFY_URL=https://freight-api.edr.et/payments/webhooks/telebirr
|
|
TELEBIRR_RETURN_URL=
|
|
TELEBIRR_TIMEOUT_EXPRESS=15m
|
|
TELEBIRR_PRIVATE_KEY=
|
|
TELEBIRR_PUBLIC_KEY=
|
|
TELEBIRR_INSECURE_TLS=false
|
|
|
|
# Public origin of the freight customer portal. Password-reset links sent to
|
|
# customers are built against this — it must be browser-reachable.
|
|
FREIGHT_PORTAL_URL=http://localhost:5173
|
|
|
|
# Portal pages the payment provider redirects the browser to after payment.
|
|
# Point these at the freight portal's public payment result routes.
|
|
PAYMENT_RETURN_URL=http://localhost:5173/payment/success
|
|
PAYMENT_FAILURE_URL=http://localhost:5173/payment/failure
|
|
|
|
# Drain tail (minutes) added to every booking pay window before anything expires:
|
|
# settlement is asynchronous, so a payment made in the window's last seconds lands
|
|
# after the deadline. Nothing is expired, no wagons are resold and no window cycle
|
|
# concludes until the tail passes. Defaults to 5 when unset.
|
|
FREIGHT_PAYMENT_DRAIN_MINUTES=5
|
|
# JWT (used by @tria-plc/api-common SharedAuthModule)
|
|
JWT_SECRET=
|
|
JWT_ACCESS_TOKEN_SECRET=
|
|
JWT_REFRESH_TOKEN_SECRET=
|
|
JWT_EXPIRES_IN=3600
|
|
# JWT expiry for @tria-plc/api-common token utils (jsonwebtoken timespan format)
|
|
JWT_ACCESS_TOKEN_EXPIRES=1h
|
|
JWT_REFRESH_TOKEN_EXPIRES=7d
|
|
|
|
# IAM seed defaults (used by @tria-plc/iamapi-common on first boot)
|
|
SUPER_ADMIN_EMAIL=superadmin@tria.com
|
|
SUPER_ADMIN_PHONE=
|
|
# Super-admin password. Falls back to DEFAULT_PASSWORD when empty.
|
|
SUPER_ADMIN_DEFAULT_PASSWORD=
|
|
DEFAULT_PASSWORD=password@tria
|
|
|
|
# IAM baseline shared with edr-passenger-api (roles, IAM app + permissions,
|
|
# position types, organization types + default units, org/unit settings, super
|
|
# admin). Replaces the seeder that shipped inside @tria-plc/iamapi-common — see
|
|
# packages/iam-seed. Seeds by DEFAULT when unset; every write is insert-only.
|
|
# Set to false to opt out.
|
|
SEED_IAM_BASELINE=true
|
|
|
|
# Freight org + staff (bookings / rule-engine IAM)
|
|
SEED_EDR_ORG=true
|
|
SEED_FREIGHT_STAFF=true
|
|
SEED_EXPORT_DJIBOUTI_INTERCHANGE_DEMO=false
|
|
|
|
# Limits GET /staff/users to employees of this IAM organization (iam.organizations.key).
|
|
# Unset = every employee. A key matching no organization returns no users.
|
|
# Dev seed key: edr_freight
|
|
# Production: ETHIO_DJIBOUTI_STANDARD_GAUGE_RAILWAY_SHARE_COMPANY_001
|
|
FREIGHT_ORG_KEY=edr_freight
|
|
|
|
# MinIO (used by @tria-plc/iamapi-common for file storage)
|
|
MINIO_ENDPOINT=localhost
|
|
MINIO_PORT=9000
|
|
MINIO_USE_SSL=false
|
|
MINIO_ACCESS_KEY=
|
|
MINIO_SECRET_KEY=
|
|
# Preset region so signed URLs are generated locally (no GetBucketLocation
|
|
# network call per sign). MinIO's default is us-east-1.
|
|
MINIO_REGION=us-east-1
|
|
|
|
# Redis
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
|
|
# --- Notification broker (RabbitMQ) ---------------------------------------------
|
|
# SMS/email OTP + notifications are queued to RabbitMQ (consumed by the shared
|
|
# SMS/email services). Set RABBITMQ_ENABLED=false to skip the broker entirely
|
|
# (dev without a local broker).
|
|
RABBITMQ_ENABLED=false
|
|
RABBITMQ_URL=amqp://localhost:5672
|
|
SMS_QUEUE=sms_queue
|
|
|
|
# ── VeriFayda 2.0 (eSignet OIDC) identity verification ──────────────────────
|
|
# Disabled by default; /fayda/verification/start returns 503 until enabled.
|
|
FAYDA_ENABLED=false
|
|
FAYDA_CLIENT_ID=
|
|
FAYDA_AUTHORIZATION_ENDPOINT=
|
|
FAYDA_TOKEN_ENDPOINT=
|
|
FAYDA_USERINFO_ENDPOINT=
|
|
# Base64-encoded RSA private JWK used for the private_key_jwt client assertion
|
|
FAYDA_PRIVATE_KEY_BASE64=
|
|
# OAuth redirect_uri for MOBILE clients (must be registered with eSignet)
|
|
FAYDA_REDIRECT_URI=http://localhost:3001/api/fayda/verification/complete
|
|
# OAuth redirect_uri for WEB clients. Defaults to FAYDA_REDIRECT_URI when unset.
|
|
FAYDA_WEB_REDIRECT_URI=http://localhost:3000/fayda/callback
|
|
# OAuth redirect_uri for the customer portal (its own origin — must also be
|
|
# registered with eSignet). Defaults to FAYDA_WEB_REDIRECT_URI when unset.
|
|
FAYDA_PORTAL_REDIRECT_URI=http://localhost:5173/fayda/callback
|
|
CLIENT_ASSERTION_TYPE=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
|
|
FAYDA_SCOPE=openid profile email phone address
|
|
FAYDA_ACR_VALUES=mosip:idp:acr:generated-code
|
|
FAYDA_CLAIMS_LOCALES=en am
|
|
FAYDA_SESSION_TTL_MINUTES=10
|
|
EXPIRATION_TIME=15
|
|
ALGORITHM=RS256
|
|
EMAIL_QUEUE=email_queue
|
|
|
|
# Shared secret for service-to-service calls (payment microservice <-> freight).
|
|
# Required at boot; set ALLOW_UNAUTH_INTERNAL=true instead ONLY for local dev.
|
|
SERVICE_AUTH_TOKEN=change-me
|
|
|
|
# ── MoR EIMS e-invoicing (core.mor.gov.et) ─────────────────────────────────
|
|
# Disabled by default; every EIMS call fails fast with EIMS_NOT_CONFIGURED until enabled.
|
|
EIMS_ENABLED=false
|
|
EIMS_BASE_URL=https://core.mor.gov.et
|
|
EIMS_CLIENT_ID=
|
|
EIMS_CLIENT_SECRET=
|
|
EIMS_API_KEY=
|
|
EIMS_TIN=
|
|
# Source-system identity comes from the access token's systemNumber/systemType claims.
|
|
# Setting these turns them into expected-value checks: a mismatch against the token fails
|
|
# fast rather than one side silently winning. Leave empty to take the gateway's word.
|
|
EIMS_SYSTEM_NUMBER=
|
|
EIMS_SYSTEM_TYPE=
|
|
# Absolute paths to the INSA-issued credentials. Keep them OUTSIDE the repo; the file
|
|
# patterns are gitignored, but a path outside the working tree is safer still.
|
|
# The certificate is transmitted as base64 of this file's exact bytes — do not convert it.
|
|
EIMS_PRIVATE_KEY_PATH=
|
|
EIMS_CERTIFICATE_PATH=
|
|
# Optional tuning
|
|
EIMS_HTTP_TIMEOUT_MS=30000
|
|
EIMS_TOKEN_SKEW_SECONDS=45
|
|
|
|
# ── EIMS invoice registration (required only to register invoices) ─────────
|
|
# Seller identity: EDR's own legal details are not modelled anywhere in the DB.
|
|
# Region and Wereda are MoR *codes* (e.g. 13 / 574), not names.
|
|
EIMS_SELLER_LEGAL_NAME=
|
|
EIMS_SELLER_VAT_NUMBER=
|
|
EIMS_SELLER_PHONE=
|
|
EIMS_SELLER_EMAIL=
|
|
EIMS_SELLER_REGION=
|
|
EIMS_SELLER_WEREDA=
|
|
# Optional seller address parts; sent as null when unset.
|
|
EIMS_SELLER_CITY=
|
|
EIMS_SELLER_SUBCITY=
|
|
EIMS_SELLER_HOUSE_NUMBER=
|
|
EIMS_SELLER_LOCALITY=
|
|
# Tax treatment — REQUIRES FINANCE SIGN-OFF. The application models no tax at all
|
|
# (invoice.taxAmount is always 0), so nothing here is defaulted: registration fails
|
|
# locally, naming the missing variables, until these are set.
|
|
# Required, and deliberately unset here: the choice is a tax position, not a default.
|
|
# MoR's enum (from its own 400): TOT10 TOT2 VAT15 VWHT TWHT VATEX VATWH WHOP2 WTHOI VAT0 VWTH
|
|
# Finance confirmed 2026-08-12: VATEX (exempt) for EDR's freight business — set in .env.
|
|
EIMS_TAX_CODE=
|
|
EIMS_TAX_RATE_PERCENT=0
|
|
EIMS_EXCISE_TAX_VALUE=0
|
|
EIMS_INCOME_WITHHOLD_VALUE=0
|
|
EIMS_TRANSACTION_WITHHOLD_VALUE=0
|
|
# Per-chargeType override, for an invoice whose lines need different MoR tax treatment (e.g. a
|
|
# zero-rated freight line next to a taxed accessorial) — IRC-P01 compliance-test material.
|
|
# A charge type not listed here falls back to EIMS_TAX_CODE / EIMS_TAX_RATE_PERCENT above.
|
|
# EIMS_TAX_CODE_BY_CHARGE_TYPE and EIMS_TAX_RATE_BY_CHARGE_TYPE must list the same charge types.
|
|
EIMS_TAX_CODE_BY_CHARGE_TYPE=
|
|
EIMS_TAX_RATE_BY_CHARGE_TYPE=
|
|
# Same mechanism; charge types not listed fall back to EIMS_EXCISE_TAX_VALUE / 0 respectively.
|
|
EIMS_EXCISE_BY_CHARGE_TYPE=
|
|
EIMS_DISCOUNT_BY_CHARGE_TYPE=
|
|
# Document classification and payment presentation.
|
|
EIMS_TRANSACTION_TYPE=B2B
|
|
# Lowercase constant: MoR's oneOf branches require exactly 'goods' or 'service'.
|
|
EIMS_NATURE_OF_SUPPLIES=service
|
|
EIMS_PAYMENT_MODE=CASH
|
|
EIMS_PAYMENT_TERM=IMMIDIATE
|
|
EIMS_UNIT_DEFAULT=PCS
|
|
# MoR numeric country code for the buyer; our companies store the country name.
|
|
EIMS_BUYER_COUNTRY_CODE=
|
|
# Buyer region name -> MoR numeric code. companies.region holds names; MoR wants ^[0-9]{1,3}$.
|
|
# An unmapped region fails locally rather than being filed with a guess.
|
|
EIMS_BUYER_REGION_CODES=Addis Ababa=13
|
|
# Same mechanism for Wereda. MoR has never named a Wereda regex in an error (only Region's is
|
|
# confirmed), so this is precautionary — but an unmapped name still fails locally, not filed as a guess.
|
|
EIMS_BUYER_WEREDA_CODES=
|
|
EIMS_CASHIER_NAME=
|
|
EIMS_SALESPERSON_NAME=
|
|
# Automatic filing of issued invoices (@Cron sweep, one invoice per tick).
|
|
# Independent of EIMS_ENABLED on purpose: authentication can be live long before
|
|
# filing is. Both must be true before anything is submitted automatically.
|
|
EIMS_AUTO_SUBMIT=false
|
|
EIMS_AUTO_SUBMIT_CRON=0 */5 * * * *
|
|
# MoR rejects documents older than 3 days; the sweep will not attempt those.
|
|
EIMS_AUTO_SUBMIT_MAX_AGE_DAYS=3
|