mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
MoR stamps systemNumber and systemType into the access token it issues for the authenticating credentials, which makes the token the authority on them. Registration now reads both from there instead of from configuration, so the SourceSystem block cannot drift from what the gateway believes we are. EimsAuthService decodes the token payload after login, requires both claims to be non-empty, and exposes them through getSessionContext(). The token is decoded but never verified -- it is MoR's, signed with MoR's key -- and is kept out of the log line, which names only the system it identified. EIMS_SYSTEM_NUMBER and EIMS_SYSTEM_TYPE become optional expectations rather than inputs: when set they are compared against the claims and a mismatch fails fast, so neither side silently wins. Neither is required to register any more. Registration and manual resolution both resolve the session before touching the state row, which is keyed by the system number: a login failure now costs nothing because no counter has been reserved yet. Test fixtures move to eims-test-fixtures.ts. They previously lived in eims-auth.service.spec.ts, which made jest execute that suite again inside every importing spec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
184 lines
7.4 KiB
Plaintext
184 lines
7.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
|
|
|
|
# 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.
|
|
EIMS_TAX_CODE=0
|
|
EIMS_TAX_RATE_PERCENT=0
|
|
EIMS_EXCISE_TAX_VALUE=0
|
|
EIMS_INCOME_WITHHOLD_VALUE=0
|
|
EIMS_TRANSACTION_WITHHOLD_VALUE=0
|
|
# Document classification and payment presentation.
|
|
EIMS_TRANSACTION_TYPE=B2B
|
|
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=
|
|
EIMS_CASHIER_NAME=
|
|
EIMS_SALESPERSON_NAME=
|