Last update: 2026-10-02
This service exists to operate a multi-tenant security/monitoring backend that sits between edge AI execution engines and user-facing applications.
APP_TYPE, where Preventics uses the internal banksight tag) while keeping domain modules isolated (clients, equipment, identity, plugins, system).Prerequisites:
node:18-alpine)cp .env.example .env
src/main.ts enforces these at startup):MQTT_PROTOCOL, MQTT_HOST, MQTT_PORTDATABASE_HOST, DATABASE_PORT, DATABASE_USERNAME, DATABASE_PASSWORD, DATABASE_NAME; DATABASE_DRIVER defaults to postgres and only needs to be set for oracleCACHE_HOST, CACHE_PORTJWT_SECRET, JWT_EXPIRATIONSTORAGE_HOST, STORAGE_PORT, STORAGE_USERNAME, STORAGE_PASSWORDK8S_REDIS_SERVICE, K8S_REDIS_NAMESPACE, AIXPAND_* or ZxAI_* namespace/initiator/key valuesnpm install
make check-postgres
make check-redis
make check-minio
npm run build
npm run typeorm:migration:run
npm run start:dev
Other common run modes:
npm run start:debug
npm run start:prod
make dev
make debug
Health check:
curl http://localhost:3000/health
Login (local strategy uses username + password):
curl -X POST http://localhost:3000/login \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data '[email protected]&password=secret'
Token refresh (JWT-protected):
curl -X POST http://localhost:3000/token/refresh \
-H 'Authorization: Bearer <jwt>'
Get available timezones:
curl 'http://localhost:3000/system/available-timezones?search=europe'
List report rules:
curl http://localhost:3000/report-rules/
Version metadata (requires built assets in dist):
curl http://localhost:3000/version
New logins use signed HS256 JWTs containing sub, sid, jti, iat and
exp. With the existing 36-character user UUID and ten-digit timestamps, the
token is exactly 255 ASCII characters, including its full signature, so the
legacy whitelist can persist it in varchar(255). The optional typ header
and duplicated email claim are omitted. Read profile information from the
authenticated GET /users/profile API, not from JWT claims. Both identifiers
use 16 random bytes encoded as 22 base64url characters; clients must treat them
as opaque.
Signature, configured expiry, current database identity/permissions and
revocation checks are unchanged. Refresh preserves sid, rotates jti and
still returns one Redis-elected successor with a fixed 30-second predecessor
overlap. Existing signed tokens remain valid until expiry or revocation.
Refreshing an existing UUID-based sid deliberately preserves it and produces
a 273-character transitional token; a fresh login starts a compact session.
Never truncate tokens or shorten an existing session ID to meet a column limit.
The Flutter FE still renews active sessions and ends them after 30 minutes of
real inactivity. That is browser session policy, not server-side JWT expiry:
background API calls do not count as activity, and JWTs keep JWT_EXPIRATION.
The whitelist's missing renewal logic remains unresolved; a fitting token still
expires normally. It needs a new login after this change, not reuse of expired
stored credentials.
There is no per-account exception or deployment flag. Existing BE versions can verify compact tokens, but an old replica still issues oversized tokens, so whitelist persistence acceptance requires a completed backend rollout. The 255-character contract has no spare capacity for extra claims, different algorithms or longer subjects/timestamps. Tests pin the current format; the durable whitelist fix is wider token storage and proper renewal. Once that upgrade is owned and deployed, storage compatibility no longer constrains the issuer; restoring profile/header fields is a separately reviewed contract change, not a reason to remove session or token-uniqueness protections.
Configuration is loaded from .env through src/configuration.ts.
Core groups:
MQTT_*, AIXPAND_* / ZxAI_*)DATABASE_*, including pool settings)CACHE_*)JWT_*)STORAGE_*)APP_TYPE, DRIVERS_PIPELINE, DELETE_NAMESPACE_PREFIX, cleanup windows, websocket suppression)COMMS_LOG_LEVEL)Mode behavior:
APP_TYPE allowed values: optizone, banksight (banksight is the current internal tag for Preventics).APP_TYPE falls back to any in local/dev, but fails fast in NODE_ENV=staging|production.app.tag and any.DATABASE_DRIVER controls migration set and DB behavior independently of APP_TYPE.DATABASE_DRIVER allowed values are oracle and postgres; when unset it defaults to postgres, and explicit invalid values fail fast in all environments.COMMS_LOG_LEVEL is the primary comms-diagnostics knob:
0: disable backend and jsclient comms diagnostics output1: periodic comms summaries every 120000ms, no NET_MON flow tracing2: high-frequency MQTT/jsclient diagnostics every 30000ms plus NET_MON flow tracingCOMMS_LOG_LEVEL is the only supported comms diagnostics env var; backend [COMMS:Lx] lines and jsclient [COMMS][JSCLIENT] summary cadence are derived from it.COMMS_LOG_LEVEL is unset, the backend defaults to 0.[COMMS:L0], [COMMS:L1], or [COMMS:L2].OPTIZ_VS_PREVX.md.Minimal env switch from a legacy Preventics-on-Oracle deployment to Preventics-on-PostgreSQL:
APP_TYPE=banksight
# Optional: omit DATABASE_DRIVER entirely to use the PostgreSQL default.
# DATABASE_DRIVER=postgres
DATABASE_HOST=<postgres-host>
DATABASE_PORT=5432
DATABASE_USERNAME=<postgres-user>
DATABASE_PASSWORD=<postgres-password>
DATABASE_NAME=<postgres-db>
DATABASE_DRIVER=oracle, change it to postgres or remove it entirely; PostgreSQL is now the default when the variable is unset.APP_TYPE=banksight; APP_TYPE=preventics is not a supported runtime value.npm run build and then npm run typeorm:migration:run before starting the app.This changes runtime wiring and migration selection only. It does not migrate data from Oracle to PostgreSQL by itself.
Primary outputs produced by the backend:
/health).report_entry table) generated from payload rules (report_rule) in ReportsService.logs/ when LOG_TO_FILE is not false.dist/, including copied JSON/YAML assets from src/system.Top route groups:
auth: /login, /password/reset, /password/reset/:token (public), /token/refresh, /password/change (authenticated)identity: /users, /roles, /permissionsclients: /clients, /locations, /clients/schedules, /clients/partitions, /clients/license-plate-lists, /car-registryequipment: /equipment, /equipment/actionsplugins/alerts: /ai, /livestream, /notifications, /alerts, /notifications/live-notificationssystem: /system/*, /translations/*, /storage/*, /blockchain/address, /version, /report-rules, /health.env against src/main.ts mandatory property checks.npm run typeorm:migration:run fails because dist/typeorm.config.js is missing:
npm run build first./version fails with missing file:
npm run build so dist/src/system/assets/store/system/version.json exists.make postgres currently reads DATABASE_USER while app config reads DATABASE_USERNAME.npm test does not run source-adjacent specs:
rootDir: test.PREVX_PGSQL_DB_READY=1 and DB env vars before running npm run verify:migrations:postgres.@UseGuards(...) (for example health, version, report-rules) should be protected by deployment perimeter controls if needed.src/main.ts bootstraps src/main.module.ts.clients: tenants, locations, schedules, partitions, license-plate lists, car registry.equipment: equipment records and action dispatch.identity: users, roles, permissions, password reset.plugins: AI plugin status/control, payload consumers, notifications/alerts/live notifications.system: auth strategies, cache/storage, reports, delete workflows, translations, websocket, version/system utilities.common: guards, decorators, interceptors, pipes, helper utilities, pagination DTOs.Key dependencies used in runtime:
@nestjs/*)typeorm, @nestjs/typeorm, pg, oracledb)ioredis, @songkeys/nestjs-redis)mqtt, @hyfy/jsclient, @hyfy/nestjs-module)passport, passport-jwt, passport-local, passport-custom, bcrypt)nestjs-minio, minio)class-validator, class-transformer)winston, nest-winston, winston-daily-rotate-file)Available commands:
npm testnpm run test:e2enpm run test:covnpm run test:debugnpm run verify:runtime-policynpm run verify:schema-paritynpm run verify:migrations:postgresnpm run verify:prevx:postgresNotes:
npm test is configured with Jest rootDir: test in package.json.test/jest-e2e.json and resolves TS ESM .js imports through moduleNameMapper.x-api-token via MultiAuthGuard.CanGuard + permission scopes.@UseGuards is publicly callable.npm run build compiles TS and copies src/system JSON/YAML assets..github/workflows/semver.yml); the PREVX PostgreSQL verification workflow is currently paused as .github/workflows/verify-prevx-pgsql.yml.paused.CHANGELOG.md.Internal repo sources used for this README:
package.jsonMakefile.env.exampleDockerfilesrc/main.tssrc/main.module.tssrc/configuration.tssrc/common/helpers/runtime.mode.tssrc/common/helpers/comms.log.policy.tssrc/system/version/version.service.tssrc/system/reports/reports.service.tssrc/plugins/schemas/schema.loader.tstest/app.e2e-spec.ts.github/workflows/semver.yml.github/workflows/verify-prevx-pgsql.yml.pausedCHANGELOG.mdExternal references:
UNLICENSED (see package.json).
Content type
Image
Digest
sha256:ae845cc9e…
Size
229.9 MB
Last updated
1 day ago
docker pull aixpand/backend:release-3.53.8