vuer_oss (Operator Side Server)

Role

FaceKom’s operator/admin backend. Handles video identification sessions, document management, workflow engine, face recognition, reporting, archive/export, and all database operations. The largest and most complex service in the FaceKom ecosystem.

PropertyValue
Version1.9.11
RuntimeNode.js >= 22.18.0
RepoTechTeamer/vuer_oss
Path/workspace/vuer_oss
ORMSequelize (@techteamer/sequelize fork v6.30.1)
MessagingRabbitMQ via @techteamer/mq
AuthPassport.js (6 strategies)
Services~80+ registered in service container

Table of Contents


Architecture Overview

vuer_oss runs as 7 separate Supervisor-managed Node.js processes, all sharing the same codebase but with different entry points. All inter-service communication with vuer_css goes through RabbitMQ. Communication with vuer_cv happens over HTTP/WebSocket.

graph TB
    subgraph "vuer_oss Processes"
        MAIN["vuer_oss<br/>server.js<br/>:10080/:10081"]
        CRON["vuer_cron<br/>cron.js"]
        BG["vuer_background<br/>background.js"]
        CONV["vuer_oss_convert<br/>convert.js"]
        MEDIA["vuer_media<br/>media.js<br/>:10079"]
        STOR["vuer_oss_storage<br/>storage.js"]
        ILOG["vuer_integration_log<br/>integrationLog.js"]
    end

    subgraph "External"
        RMQ["RabbitMQ"]
        PG["PostgreSQL"]
        REDIS["Redis (HA)"]
        CSS["[[vuer_css]]"]
        CV["[[vuer_cv]]"]
        JANUS["Janus WebRTC"]
    end

    MAIN --> RMQ
    MAIN --> PG
    MAIN --> REDIS
    MAIN --> CV
    MAIN --> JANUS
    RMQ <--> CSS
    CRON --> RMQ
    CRON --> PG
    BG --> RMQ
    BG --> PG
    CONV --> RMQ
    MEDIA --> PG
    STOR --> RMQ
    ILOG --> RMQ
    ILOG --> PG

Entry Points & Boot Sequence

ProcessEntryPortPurpose
vuer_ossserver.js:10081 (HTTP), :10080 (Socket.IO)Main web + socket server
vuer_croncron.js-Scheduled tasks (19+ possible cron jobs)
vuer_backgroundbackground.js-Long-running jobs (reports, exports, OCR)
vuer_oss_convertconvert.js-Video/audio transcoding (FFmpeg)
vuer_mediamedia.js:10079Authenticated media streaming
vuer_oss_storagestorage.js-File archival between storage engines
vuer_integration_logintegrationLog.js-API integration audit logging with encryption

All processes managed by Supervisor.

Common Boot Sequence

Every process follows the same pattern:

flowchart TD
    A["process-settings()"] --> B["process-listeners()"]
    B --> C["Load config"]
    C --> D["setupServices() — subset per process"]
    D --> E["Connect DB"]
    E --> F["Connect Redis (optional, HA)"]
    F --> G["Connect RabbitMQ"]
    G --> H["initServices()"]
    H --> I["setupQueue() — consumers/producers"]
    I --> J["customization hooks"]
    J --> K["Start — web/cron/queue"]
    K --> L["Emit system.start"]

server.js (Main Server)

  • Instantiates ~80+ services into serviceContainer.service.*
  • Starts both Express web server and Socket.IO server
  • Emits system.start event at the very end, triggering audit log

background.js

  • Handles reports, exports, OCR recognition, archives
  • Subset of services — no socket, no web server, no transport pool
  • RPC server for reports, archive, recognition, room export

cron.js

  • Creates CronJob instances, stores in serviceContainer.cron, starts all
  • 19+ possible cron jobs based on config

convert.js

  • Minimal services — crypto, media file, hash, trusted timestamp, SFTP
  • Consumes from queue-convert
  • Pre-check: runs convert_check.js to verify FFmpeg availability

media.js

  • Full WebServer instance but only with media routes, no Socket.IO
  • Port 10079

storage.js

  • Both server and client for queue-storage

integrationLog.js

  • Creates daily encryption keys, has rate limiting, dumps on exit

Bootstrap & Initialization

process-settings.js

  • Sets process.env.TZ = 'Etc/UTC'

Security: Global TLS Bypass

If config.settings.allowSelfSignedCerts is true, sets NODE_TLS_REJECT_UNAUTHORIZED = '0' — disables all TLS certificate verification globally. See security-audit.

process-listeners.js

  • Registers uncaughtException, unhandledRejection, exit, SIGINT, SIGTERM
  • When emitExitEvents=true (only in server.js), emits system.exit before exiting with 1-second delay
  • Process warnings listener is optional via config

connection/db.js

  • Creates Sequelize connection, runs migrations via CLI exec

Hack

Uses child_process.exec to run sequelize CLI for migrations rather than the programmatic API.

  • Seeds default open hours (Mon-Fri 10:00-16:00) via checkStandardDays()

connection/rabbitmq.js

  • Uses @techteamer/mq ConnectionPool
  • Sets up serviceContainer queue infrastructure (rpcServer, rpcClient, queueServer, queueClient, publisher, subscriber)

Fatal Exit

On RabbitMQ connection close, calls process.exit(2) immediately — no graceful shutdown.

connection/redis.js

  • Only connects if HARedis.config is set
  • Used for HA waiting room
  • Reconnect strategy: max 10 retries at 500ms intervals, then gives up

Service Container & Dependency Injection

File: server/service_container.js

The service container is a singleton module that serves as:

  1. A DI container (serviceContainer.service.*)
  2. An event bus (serviceContainer.emitter — a WildEmitter subclass called ServiceBus)
  3. A registry for all major subsystems (db, dbModels, queue, io, transportPool, etc.)

God Object Pattern

The service container holds everything — 80+ services, DB, queue, socket, transport, etc. This is both the strength (easy to access anything) and the weakness (tight coupling, hard to test, hard to reason about lifecycle). See tech-debt.

ServiceBus

Extends WildEmitter with:

MethodBehavior
addHook(tag, handler)Register hook handler
callHooks(tag, ...params)Promise.all execution of all handlers for tag
callOnlyHook(tag, ...params)Calls first registered hook only
registerOverride(name, fn)Single-function override
callOverride(name, ...args, default)Call override or default

Used for extensibility via customization/ directory.

Key Properties on serviceContainer

PropertyContent
logger, auditLog, diagnosticInfrastructure
db, dbModels, dbHelpersDatabase layer
HARedisClientRedis (HA waiting room)
queue, queueConnectionPoolRabbitMQ
rpcServer.*, rpcClient.*RPC pattern
queueServer.*, queueClient.*Queue pattern
publisher.*, subscriber.*Pub/Sub pattern
transportPool, roomTransportStorageTransport layer
ioSocket.IO server
webServer, webServerAuth, sessionStoreWeb layer
service.*~80+ business services
cron.*Cron jobs (cron.js only)

Configuration System

File: config.js

  • Uses getconfig library (reads from config/*.json based on NODE_ENV)
  • Optional Spring Cloud Config Server integration with retry
  • Custom config.get(path, default) and config.has(path) methods
  • config.getSecureConfig(): Masks sensitive fields defined in security.sensitiveConfigFields
  • config.traceConfig(): Flattens entire config to sorted string list for debugging
FeatureDetails
Dev modeAuto-generates hostnames from /etc/hostname
Travis CI modeHardcodes RabbitMQ to localhost
VersionAppends build number from .env file
CORSSecure-by-default — replaces * with actual hostname
DB CA certReads CA cert from file if path is provided
Custom type: Types.fileReads file contents from disk as config value
Legacy migrationVerbose warnings for old Janus config format

Configuration Access

config.get('path.to.key', defaultValue)
config.has('key')

Database Layer

sequelize.js

  • Creates Sequelize instance from config
  • Default pool max: 100 connections
  • Pool monitoring: 5-second interval checks utilization, warns at 40%, errors at 60%
  • SQL logging only in dev mode

Monkey-Patches

  • beforeFind/beforeCount hooks strip undefined values from WHERE clauses (workaround for Sequelize v6 breaking change)
  • SIGUSR1 dumps connection pool loans, SIGUSR2 releases connections borrowed for >30 seconds

models.js

  • 65 models instantiated with ~200+ associations
  • Returns flat object of all model classes
  • All models defined as factory functions: module.exports = (sequelize, DataTypes) => { ... }

Key Models & Relationships

ModelRelationships
Roombelongs to Customer, User; has many Activity, Feedback, MediaFile, Document
SelfServiceRoomParallel to Room but for self-service flow
CustomerCentral entity; has many Room, SelfServiceRoom, Document, CustomerHistory
UserOperator; has many Room, Cert, Download, PasswordHistory, WebAuthnCredential, TotpKey
Flowbelongs to FlowProto, Customer, Room/SelfServiceRoom; has many Task
FlowProtoWorkflow template; has many TaskProto, FlowScope, FlowResult, FlowTranslation
AttachmentScreenshot/file storage; can be encrypted (belongs to Encryption)
EncryptionTracks encryption keys per customer/room
BackgroundProcessbelongs to User, Customer, Room, Flow, Task, Attachment, Document, MediaFile, Partner, PartnerService

helpers.js (~960 lines)

Shared DB helper functions used across the application:

FunctionPurpose
getActivityLog(), getLastActivity()Query activity logs
addCustomerActivity(), addOperatorActivity()Create activity records
findRoomByOperator(), findRoomByCustomerId()Room lookups
getOperatorRoomData()Massive function assembling all data for video chat
getReplayData()Even larger — complete replay data with all activities, flows, OCR
createAttachment()Creates attachment with optional encryption
getDecryptedAttachmentBuffer()Attachment retrieval with decryption
getFlowData()Assembles flow data with tasks, scopes, results, actions
checkStandardDays()Seeds default open hours for all calendars
switchActiveCert()Switches active signing certificate for a user

Migrations

  • Located in db/migrate/ using Umzug, numbered by timestamp
  • Config files: .sequelize-config.js, .sequelizerc, .sequelizercBefore
  • Pre-migration hooks in db/beforeMigrate/
  • Also see server/db/migrationHelpers.js for migration utilities

See database-schema for full entity documentation.


Web Server & Routes

WebServer.js

Express application with extensive security middleware chain:

OrderMiddlewarePurpose
1IP filterOptional IP blocking
2Host header validationInjection protection (validates against config.hosts)
3Nonce generationcrypto.randomUUID() per request
4User-Agent parsingua-parser-js
5Helmet.jsCSP, HSTS, referrer policy, etc.
6No-cache headersCache control
7Per-path CSPNonce-based script/style sources
8Body parserURL-encoded, JSON, CSP reports
9Cookie parserCookie handling
10Log4jsExpress request logging
11Locale detectioncookie > query param > Accept-Language

CSP Relaxation

CSP is turned off for /api/document/ and /import-data/ paths. Dev mode adds unsafe-eval for Istanbul coverage.

Key WebServer Methods

MethodPurpose
setupSession()Sequelize-backed session store, auto-destroy old sessions on login
setupSessionACLHandler()Session-based ACL rules (path-to-permission mapping)
setupResourceAccessBypass()RAB token system for accessing resources without full auth
setup405Handler()Checks route methods, returns 405 for wrong HTTP method
setupDisasterHandler()Maintenance mode that blocks all access except admin

routes.js (~350 lines, 70+ routes)

Routes cover: dashboard, login, password change, 2FA, WebAuthn, TOTP, video chat, replay, flows (list/view/editor/task/result CRUD), rooms, self-service rooms, customers, import data, callback requests, waiting list, appointments, open hours, audit log, feedbacks, reports, users (list/create/edit/disable/enable/password reset), system settings, documents, disaster mode, client errors, cron manager, archive/restore, media content, various API endpoints.

Security

Every route has CSRF protection (csurf) and ACL checks (isAllowed/anyAllowed). Many routes are conditionally registered based on config feature flags.

session.js

FunctionPurpose
listSessions()Finds all sessions for a user by parsing stored JSON
closeSession()Destroys session by SID
onExpressSessionExpiry()Monkey-patches SequelizeStore to emit events on session expiry

Performance

listSessions() iterates ALL sessions and parses JSON to find ones belonging to a specific user — O(n) scan with no index. See tech-debt.


Authentication System

File: server/web/WebServerAuth.js (~700 lines)

See authentication for full documentation.

Passport Strategies (6 total)

StrategyDetails
LocalStrategyUsername/password with rate limiting, account lockout, password expiry, audit logging, 2FA redirect
ActiveDirectoryStrategyLDAP/AD auth; multiple AD configs; maps AD groups to roles; falls through on failure
SamlStrategySAML 2.0 SSO via @node-saml/passport-saml; extracts email, username, names from SAML attributes
WebAuthnStrategyFIDO2/WebAuthn via passport-fido2-webauthn; challenge store in session; supports credential registration
TotpStrategyTime-based OTP via passport-totp; paired with local auth as second factor
UniqueTokenStrategyCustom token-based API auth: JWE (encrypted via JOSE keystore), JWT (signed), One-Time Login

Auth Flows

flowchart LR
    A["Login Request"] --> B{"Auth Type?"}
    B -->|Interactive| C["Local / AD / SAML"]
    B -->|Token| D["JWE / JWT / OTL"]
    C --> E{"2FA Required?"}
    E -->|Yes| F["SMS / TOTP / WebAuthn"]
    E -->|No| G["Session Created"]
    F --> G
    D --> G

auth.js (Socket-level)

Helper functions: isAuthorized(), hasRight(), doIfAuthorized(), doIfHasRight(), doIfHasRoom()

SocketTokenStorage.js

  • JWT-based token for socket authentication
  • Creates 2-minute tokens with userId, role, rules
  • Verified on socket connection

Socket.IO Server

File: server/socket/socket-server.js

Creates Socket.IO server with config-based options. Registers 13+ event modules on each connection. Supports recovered connections (socket.io v4 feature).

Event Modules

ModulePurpose
client.jsClient connection/disconnection handling
auth.jsSocket authentication via JWT token
acl.jsAccess control for socket events
pagevisit.jsPage visit tracking
echotest.jsWebRTC echo test
ping.jsLatency measurement
videochat.jsCore video chat events
videochat.validation.jsCustomer validation during video chat
videochat.customerDataChange.jsLive customer data editing
videochat.flow.jsFlow execution during video chat
videochat.presentation.jsDocument presentation mode
headerinfo.jsHeader information updates
webrtclog.jsWebRTC logging
cert.jsCertificate management
waitinglist.jsWaiting list management
flow.jsFlow management (optional, ACL-gated)
cronManager.jsCron job management (optional, ACL-gated)
customerdata.jsCustomer data changes (optional, ACL-gated)

RabbitMQ Queue System

Uses @techteamer/mq library with 4 messaging patterns. See rabbitmq-communication for full queue documentation.

Architecture

PatternCountDescription
RPC Servers30+Request-response (server.js hosts most)
RPC Clients15+Callers for RPC servers
Queue Servers15+Async consumers
Queue Clients10+Async producers
Publishers3Fanout: CustomerKey, SettingsChange, BackgroundProcess
Subscribers3Fanout consumers (same 3)

Connection Management

  • ConnectionPool with named connections
  • Default connection for most queues
  • Optional separate connection for esign module
  • Optional connections marked as optional won’t crash on ECONNREFUSED

RPC Servers (30+)

Queue NamePurpose
rpc-create-customerCustomer creation from CSS
rpc-customer-portal-dataPortal data lookup
rpc-jwt-authJWT authentication for CSS
rpc-device-changeDevice change handling (short/long tokens)
rpc-get-customerCustomer retrieval
rpc-waiting-roomWaiting room management
rpc-videochat-ossVideo chat operations
rpc-callback-requestCallback request handling
rpc-openhours / rpc-openhours-calendarsOpen hours
rpc-partner-servicePartner service operations
rpc-custom-contentCustom content
rpc-selfservice-actionsSelf-service actions
rpc-selfservice-uploadSelf-service file upload
rpc-selfservice-v2Self-service v2 (JWT tokens, SMS, flow management)
rpc-vuer-portalPortal operations
client-gateClient gate verification
rpc-system-checkSystem health checks
rpc-jwt-kiosk-authKiosk JWT auth
rpc-kiosk-alive-checkKiosk heartbeat
rpc-media-contentMedia content serving
rpc-identification-routerIdentification routing (TODO: incomplete)
rpc-device-compatibility-checkDevice compatibility
backgroundBackground process management
rpc-appointmentAppointment management
rpc-document-upload/deleteDocument operations
rpc-customer-documents / rpc-flow-documentsDocument queries
rpc-presentationPresentation mode
flow-autoclearAutomatic flow clearing
rpc-transport-ossTransport layer (bidirectional with CSS)

RPC Clients

Queue NamePurpose
css-ping, convert-ping, cron-ping, background-ping, media-pingHealth checks
rpc-system-ossSystem operations
background-reportsReport generation
background-archiveArchive operations
kiosk-document-scanKiosk document scanning
rpc-portal-vuerPortal queries
integration-logIntegration logging
background-recognitionOCR recognition
rpc-esign:externalE-signature (optional separate connection)
cronManagerCron management
rpc-xml-report / rpc-xlsx-reportReport generation
rpc-transport-cssTransport layer

Queue Servers (Consumers)

Queue NamePurpose
queue-feedbackCustomer feedback
queue-videochat-ossVideo chat events
queue-customer-historyCustomer history
queue-webrtc-logWebRTC logs
queue-clienterror-logClient error logs
queue-convert-stateConversion status
queue-customerCustomer events
queue-job-status-changeJob status changes
queue-storage-stateStorage status
css-client-ping-resultCSS client ping results
kiosk-queue-document-scanKiosk scanning
queue-selfservice-eventsSelf-service events
queue-selfservice-cronSelf-service cron
queue-selfservice-v2Self-service v2 events
queue-room-cronRoom auto-close
queue-transport-ossTransport messages from CSS

Queue Clients (Producers)

Queue NamePurpose
queue-service-busService bus messages
queue-waiting-roomWaiting room events
queue-videochat-cssVideo chat to CSS
queue-convertConversion requests
queue-job-status-changeJob status
queue-storageStorage operations
queue-selfservice-css / queue-selfservice-v2-cssSelf-service to CSS
queue-transport-cssTransport messages to CSS

SelfServiceV2 Queue

Signs JWT tokens for self-service sessions using config.jwt.secret. Masks credentials in queue messages: item.credential = 'secret'.


Transport Layer

Bidirectional communication layer between vuer_oss and vuer_css.

TransportPool.js

  • Manages TransportSession instances in a Map
  • Supports three operations: register, transaction (RPC), send (fire-and-forget)
  • Auto-register: dynamically creates session instances from class name
  • Path validation: checks that session class path is within /session/ directory to prevent path traversal

TransportSession.js (Base Class)

  • Extends EventEmitter
  • Methods: send(), transaction(), consume(), react(), destroy(), terminate()
  • Uses UUID for session ID

Session Types

TypePurposeSize
RoomTransportSessionVideo chat room transport750+ lines
SelfServiceTransportSessionSelf-service transport-
EchoTransportSessionEcho test transport-

Storage Types

TypePurpose
RoomTransportStorageMaps room IDs to transport sessions
SelfServiceTransportStorageMaps self-service room IDs to transport sessions

Computer Vision Integration

Integration with vuer_cv for ML-powered identity verification.

CVApi.js (Base Class)

  • Manages output classes, result validators, detection validators
  • Default validators: confidence, lowestConfidence, averageConfidence, detectionCount
  • Pattern: instruction API call output validation

VuerCVWebSocket.js

  • WebSocket client to vuer_cv
  • Supports WebRTC signaling (offer/answer)
  • Message types: webrtc, debug, general messages
  • Logs all messages for debugging

VuerCVSession.js

Session lifecycle:

  1. Connect to CV server via WebSocket
  2. Initialize task
  3. Connect Janus (if video room plugin available)
  4. Handle debug messages (worker info)
  5. Handle CV messages
  6. Handle close/error

Vision APIs

APIPurpose
BarcodeDetectionApi / BarcodeDetectionV2ApiBarcode reading
DocumentRecognitionApiDocument recognition
FaceCompareApiFace comparison
FaceDetectionApiFace detection
FaceExtractionApiFace extraction
MRZDetectionApiMRZ (Machine Readable Zone) detection
SharpnessDetectionApiImage sharpness check

VuerCVPADService.js

  • Presentation Attack Detection service (anti-spoofing)

CV Task Types

ActionTask, DocumentTask, FaceTask, HoloTask, HoloV2Task, LivenessTask, LivenessV2Task, MRZTask, PadTask, SpeechTask

CV Internals

ModulePurpose
CVConfidenceScaleConfidence scoring
CVConstantsError codes, recognition statuses
CVThresholdThreshold management
CVValidation / CVValidatorValidation logic

OCR & Recognition

OCRRecognitionClient.js

  • Central OCR client managing engines and document types
  • Registered engines: VuerCVMRZDetector, VuerCVOCRRecognition
  • Document types loaded from customization/ocr/documents/
  • Pipeline: dispatchRecognition() engine parseRecognition() validate
  • Backward compatibility: maps old MrzDetector engine name to VuerCVMRZDetector

Engines

EnginePurpose
VuerCVMRZDetectorMRZ detection via vuer_cv
VuerCVOCRRecognitionGeneral OCR via vuer_cv

MRZ Processing

FilePurpose
MRZService.jsMRZ parsing and validation
MRZData.jsMRZ data structure
MRZDataField.jsIndividual MRZ field

Recognition Pipeline

FilePurpose
RecognitionJob.jsIndividual recognition job
RecognitionProcessor.jsProcesses recognition requests
RecognitionDocument.jsDocument recognition result
RecognitionField.jsIndividual recognition field
RecognitionResults.jsAggregated results
CharacterQuality.jsCharacter quality assessment
FieldPosition.jsField position tracking
RecognitionFieldValidation.jsField-level validation rules

Face Recognition

VuerCVFaceRecognitionEngine.js

  • HTTP client to vuer_cv REST API
  • Operations: uploadImage(), faceDetect(), faceDraw(), imageDownload(), faceCompare()
  • Uses fetch() API (Node.js built-in)
  • Supports additional face data for multiple faces in an image

Performance Concern

getHttpsAgent() creates a new agent per call — no connection reuse/pooling. Potential resource exhaustion under load. See tech-debt.

faceRecognitionHooks.js

  • Hook registration for face recognition events
  • TODO: videochat flow controlled screenshot + face compare

Flow Engine

Task-based workflow system with conditional routing and state management.

FlowService.js

  • Central flow management service
  • Loads flow handlers from customization/flow/{type}/{type}.flow.handler.js
  • registerFlowHandlers() — sequential registration of all flows
  • Access control: view.any, view.own, view.other with hook-based custom logic
  • Uses ResourceLocker to prevent concurrent flow starts

FlowHandler.js (Base Class)

  • Loads proto definitions from customization/flow/{name}/{name}.flow.proto.js
  • Loads translations from customization/flow/{name}/{name}.flow.trans.js
  • register() — creates FlowProto, TaskProto, FlowScope, FlowResult, FlowTranslation in DB
  • Registers lifecycle hook: flow:{name}:create

Supporting Files

FilePurpose
FlowScopeMap.jsMaps flow scopes to user roles
FlowResultOptions.jsFlow result option management
FlowEditor.trans.jsTranslation for flow editor UI
Flow.trans.jsTranslation for flow UI

Predefined Flows

14 predefined flows in customization/flow/ (self-service, online verification, esign, etc.)


Cron Jobs

Base class: server/cron/CronJob.js

  • Uses cronosjs for cron scheduling
  • Supports timezone configuration
  • States: stopped, scheduled, running
  • Audit logging on each run (if configured)

Available Cron Jobs (19)

#JobPurpose
1CleanupExpiredDownloadsCronJobCleanup expired downloads
2ArchiveCronJobArchive old rooms
3DeleteExpiredURLCronJobDelete expired shortened URLs
4DeleteExpiredOneTimeLoginCronJobCleanup OTL tokens
5CloseExpiredSelfServiceRoomsCronJobClose stale self-service sessions
6SelfServiceAutoAbortUnattendedCronJobAuto-abort unattended sessions
7DeactivateInactiveUserCronJobDeactivate inactive users
8CertExpiryCronJobHandle certificate expiration
9LtvReTimestampCronJobRe-timestamp expired LTV documents
10CleanUpExpiredAppointmentsCronJobCleanup old appointments
11SendUsersXmlReportCronjobEmail XML user reports
12AuditLogForwardCronJobForward audit logs
13CreateDailyIntegrationLogKeyJobCreate daily encryption keys
14DropIntegrationLogKeyAndPayloadJobPurge old integration log keys
15PreviousNoonRememberEmailAppointment reminder emails (noon)
16PreviousHalfHourRememberEmailAppointment reminder emails (30 min)
17TemporaryFileCleanupCronJobCleanup temp files
18StorageUploadCronJobUpload files to external storage

Extensibility

Additional cron jobs can be registered via customization/cron/ hooks.


Background Processes

Handler: server/backgroundProcess/BackgroundProcessHandler.js

Process Types

ProcessPurpose
checkSanctionedPerson.process.jsSanctions list checking
emrtd.process.jseMRTD processing (spawns Java process with LANG/LC_ALL/JAVA_HOME env vars)
importedRoomExport.process.jsExport imported rooms
mergeAudioFile.process.jsMerge audio files (TODO: handle single-side case)
roomExport.process.jsExport room data
selfServiceRoomExport.process.jsExport self-service room data

Portal & Data Match

PortalDataBase.js

  • Central customer data management class
  • Field definitions (PortalFieldDefinition), section definitions (PortalSectionDefinition)
  • Dynamic search fields
  • Data display with translations
  • TODO: implement dynamic fields in field definitions

Data Match

FilePurpose
DataMatchField.jsField-level data matching
DataMatchRow.jsRow-level data matching

Supporting Files

PortalField.js, PortalFieldDefinition.js, PortalSectionDefinition.js, helpers.js


Partner Integration

PartnerServiceLogic.js

  • Partner service business logic
  • Tasks: videochat, waitingRoom, lobby
  • hasVideochat() — checks if customer has active room
  • hasFlow() — checks if customer has active flow
  • Uses geoip-lite for IP geolocation
  • Uses google-libphonenumber for phone number validation

Services Layer

~80+ services organized by domain. Each is registered in the service container during boot.

Customer & Identity

ServicePurpose
CustomerServiceCustomer CRUD
CustomerDataServiceCustomer data management
CustomerDataLiveUpdateServiceReal-time customer data updates
CustomerDeleteServiceCustomer deletion (GDPR)
CustomerFilterServiceSearch/filter
CustomerHistoryServiceChange history
CustomerKeyStorageServiceEncryption key management per customer
ContactValidationServiceEmail/phone validation

Room & Session

ServicePurpose
RoomServiceRoom lifecycle management
SelfServiceRoomServiceSelf-service room management
SelfServiceV2Servicev2 self-service (1500+ lines, multiple TODOs)
SelfServiceCheckerServiceValidation checks (TODO: mock implementations)
VideoChatServiceVideo chat management
WaitingRoomServiceWaiting room (Redis-backed for HA)
DurableWaitingRoomServicePersistent waiting room
SocketServiceSocket connection management
SocketSessionServiceSocket session debugging

Flow & Workflow

ServicePurpose
FlowServiceCore flow engine (see )
FlowLiveUpdateServiceReal-time flow updates
FlowFilterServiceFlow search/filter

Documents & Files

ServicePurpose
DocumentServiceDocument management
MediaFileServiceMedia file operations
MediaContentServiceMedia content serving
FileValidatorServiceFile validation (TODO: implement other file types)
TempFileServiceTemporary file management
SystemDocumentServiceSystem-level documents

Export & Reporting

ServicePurpose
ExportRoomPageServiceRoom export
ExportImportedRoomPageServiceImported room export
ExportSelfServiceRoomPageServiceSelf-service room export
ExportScreenshotsServiceScreenshot export
ExportRawRoomVideoFilesServiceRaw video export
ReportsServiceReport generation
CallsReportServiceCall reports
UsersReportServiceUser reports
FeedbackReportServiceFeedback reports
SmsReportServiceSMS reports
XlsxReportServiceExcel report generation
XmlReportServiceXML report generation
PDFBuilderServicePDF generation with components

Security & Auth

ServicePurpose
PasswordServicePassword policy, hashing, temporary passwords
TokenServiceJWT/JWE token management with JOSE keystore
RabServiceResource Access Bypass tokens
RateLimiterServiceIP-based rate limiting
IpFilterServiceIP filtering and monitoring
JWETokenStrategyServiceJWE token auth
JWTTokenStrategyServiceJWT token auth
OneTimeLoginServiceOne-time login links
TurnPasswordServiceTURN server credentials

Crypto Services

ServicePurpose
CryptoServiceBase crypto operations (key management)
MediaCryptoServiceMedia file encryption
CertCryptoServiceCertificate encryption
AttachmentCryptoServiceAttachment encryption
DataCryptoServiceData field encryption
TranslationCryptoServiceTranslation encryption
SignatureServicePDF signing (spawns Java process)
HashServiceHashing utilities
LtvServiceLong-Term Validation for timestamps
TrustedTimestampServiceRFC 3161 trusted timestamps
TrustedTimestampRoomServiceTimestamps for rooms

Infrastructure

ServicePurpose
SettingsServiceSystem settings (DB-backed)
DirectoryServiceMedia directory management
StorageServiceExternal storage engine integration
SFTPServiceSFTP file transfers
JanusServiceJanus WebRTC gateway management
AppointmentServiceAppointment scheduling
CallCenterServiceCall center routing
DashboardServiceDashboard data
DisasterModeServiceMaintenance mode
HeaderUpdateServiceHeader info updates
OpenHourServiceBusiness hours management
OnlinePresenceServiceUser online status
CompatibilityServiceBrowser compatibility checks
ShortenerServiceURL shortening

Face Recognition & Comparison

ServicePurpose
FaceRecognitionServiceFace recognition (TODO: rework for videochat)
FaceComparisonServiceFace comparison between images

Background & Process

ServicePurpose
BackgroundProcessServiceBackground process orchestration
JobServiceJob management
MergeAudioFileServiceAudio merging
ResourceLockerServiceDistributed locking (in-process Map-based)

Integrity & Sanctions

ServicePurpose
DeviceIntegrityCheckServiceDevice attestation
GooglePlayIntegrityCheckServiceGoogle Play integrity
AppleIntegrityCheckServiceApple App Attest
DeviceCapabilitiesCheckServiceDevice capability checks
DeviceChangeServiceDevice change handling
SanctionedPersonCheckerServiceSanctions list checking

Audit & Logging

ServicePurpose
IntegrationLogServiceIntegration API logging
IntegrationLogSaveServiceIntegration log persistence
IntegrationLogExportServiceIntegration log export
ClientErrorLogServiceClient-side error logging
CommunicationLogServiceCommunication logging
UserActivityServiceUser activity tracking
RoomActivityServiceRoom activity tracking

Import & Portal

ServicePurpose
ImportServiceData import from external systems
ImportedCustomerDeleteServiceImported customer deletion
PortalServicePortal data management

Cryptography & Security

AES-256-GCM Implementation (server/gcm.js)

FeatureDetails
AlgorithmAES-256-GCM
Key derivationPBKDF2 with SHA-256, 5000 iterations, 32-byte key
EncodingBase62
StreamingEncryptionStream / DecryptionStream (Transform streams)
Buffer opsencryptBuffer() / decryptBuffer()
String opsencrypt() / decrypt()
Key protectionDO_NOT_GENERATE_ENCRYPTION_KEY env var

Duplicate Operations

The encrypt() function creates cipher, updates, and finals, then calls encryptBuffer() which does the same thing again. See tech-debt.

Crypto Services Architecture

  • CryptoServiceBase — base class
  • Per-domain crypto services: Media, Cert, Attachment, Data, Translation
  • Each handles encryption/decryption for its domain using customer-specific keys
  • Keys stored in Encryption model, managed by CustomerKeyStorageService

UniqueTokenStrategy.js (Custom Passport Strategy)

  • Searches token in: body, query, params, cookies, headers
  • Case-insensitive by default
  • Supports JWE encryption for token content

Logging & Diagnostics

logger.js

Log4js-based logging with multiple channels:

ChannelPurpose
vuerMain application log
auditAudit events
convertMedia conversion
sqlSQL queries (dev only)
janusJanus WebRTC
expressHTTP requests
cspContent Security Policy reports
backgroundBackground processes
mediaMedia operations
cronCron jobs
migrationDB migrations
emailEmail sending
auditAccessAccess audit
  • Channel auto-detection based on entry script name
  • Appenders: custom (ECS), file, syslog, papertrail
  • logger.shutdown() for graceful shutdown

diagnostic.js

Real-time health monitoring:

MetricDetails
RPC round tripsPings CSS, convert, cron, background, media
Socket round tripsPings all connected clients
RabbitMQ queue depthAlerts at 5x prefetch count
Sequelize pool statsConnection pool utilization
Event loop delaymin, max, mean, percentiles
CV server availabilityAvailability percentage
CSS client ping resultsClient-side ping data
  • Emits diagnostic:updated events at configurable intervals

Audit Logging

File: server/auditlog.js (~365 lines)

Event-driven audit logging system listening to 50+ event types on serviceContainer.emitter.

Categories

system, user, openhour, room, selfServiceRoom, flow, settings, document, systemdocument, encrypt, timestamp, callcenter, cronjob, customer, access, report, webAuthnCredential, totpKey

  • All events written to both log4js audit channel and AuditLog DB table
  • Extensible via serviceContainer.emitter.callHooks('auditlog', { em, writeLog })

Email & SMS

Email (server/e-mail/)

FilePurpose
EmailService.jsEmail sending service (Nodemailer + MJML)
EmailApiBase.jsBase email API
Letter.jsEmail template/content model

SMS (server/sms/)

FilePurpose
SmsService.jsSMS sending service
SmsApiBase.jsBase SMS API
SmsMessage.jsSMS message model

Media & Conversion

server/convert/

FilePurpose
convert_check.jsVerifies FFmpeg availability
Converter.jsFFmpeg conversion wrapper (fluent-ffmpeg)
JanusConvertProcess.jsJanus recording conversion
JanusMetaProcess.jsJanus metadata processing

Room Inspector

server/room-inspector/

FilePurpose
RoomInspector.jsRoom state inspection
RoomInspectorService.jsRoom inspection service
VideoRoomInspectorJanusPlugin.jsJanus video room inspection plugin

Utility Modules

server/util/

ModulePurpose
CallCounter.jsCall counting utility
fs-utils/Filesystem utilities (copy, exists, ensure-directory, file-type, move, move-directory-content)
isUserVerificationEnabled.jsUser verification config check
magic.jsUnknown utility
mediaContentUtil.jsMedia content helpers
pdf.jsPDF utilities
regexParser.jsRegex parsing utility
StreamTransform.jsStream transformation utility
systemEnv.jsSystem environment detection
UniqueTokenStrategy.jsCustom Passport strategy (see )
validateReportBody.jsReport body validation

taskCompatibility.js

Maps self-service task types to SDK compatibility (mobileSDK / webSDK). Known types: 2-factor, consent, portraits, liveness, ID front/back, hologram, eMRTD, proof-of-address, data-confirmation, client-gate, video, key-enrollment. Unknown types default to mobileSDK-compatible.


Listeners & Event System

server/listeners/

FilePurpose
background-process.jsBackground process event handlers
env-data.jsEnvironment data event handlers
kiosk-listener.jsKiosk device event handlers
user-listeners.jsUser lifecycle event handlers

Hook System

Extensibility via customization/listeners/:

emitter.addHook('queue', cb)           // Queue setup
emitter.addHook('services', cb)        // Service registration
emitter.addHook('webserver:setup', cb) // Web server config
emitter.addHook('cv:setup', cb)        // CV setup
emitter.addHook('system.start', cb)    // Boot complete
emitter.addHook('routes', cb)          // Route registration
emitter.addHook('cron', cb)            // Cron registration
emitter.addHook('auditlog', cb)        // Audit log extension

Error Handling

Custom Error Classes (server/errors/)

ClassPurpose
AuthenticationErrorAuthentication failure with HTTP code
FlowFrontendErrorFlow-related frontend errors

Error Handling Patterns

  • Most services catch errors, log them, and re-throw
  • Express error handler catches:
    • AuthenticationError — emits access.failed
    • 403 errors — renders template
    • InvalidCredentialsError — flashes + redirect
  • Fallback: 400 “Something broke into 400 pieces!”
  • process.exit(2) used for fatal errors (DB connection, RabbitMQ close, etc.)

Hacks, Workarounds & Code Smells

Technical Debt

See tech-debt for tracking and prioritization.

Configuration

#IssueLocation
1SyntaxError parsing hack — manually parses error position from exception message stringconfig.js:27-52
2Spring Cloud Config integration with promise-retry — complex and potentially slow startupconfig.js

Database

#IssueLocation
3Global Sequelize hook to remove undefined WHERE values (v6 workaround)sequelize.js:36-58
4SIGUSR1/SIGUSR2 debug hooks use global.console.log (bypasses logger)sequelize.js:100-115
5listSessions() loads ALL sessions and parses JSON — O(n) scan with no indexsession.js:4-17
6Shells out to sequelize CLI for migrations instead of programmatic APIconnection/db.js:19

Security

#IssueLocation
7NODE_TLS_REJECT_UNAUTHORIZED=0 — global TLS bypassprocess-settings.js:7
8Hardcoded 'temppassword' for all temporary passwords in test modeserver.js:290-292
9unsafe-eval in CSP in dev/CI mode for Istanbul coverageWebServer.js:178
10Duplicate cipher operations in encrypt() — creates cipher then calls encryptBuffer() which does samegcm.js:237-255

Service Container

#IssueLocation
11Typo deprecation proxy: contactValidatoin (typo) proxied to throw deprecation errorserver.js:163-167
12God Object pattern: serviceContainer holds everythingservice_container.js
13Duplicate flowFilter service creationbackground.js:87-88

Code Quality

#IssueLocation
1450+ TODOs scattered throughout codebaseVarious
15Inconsistent naming: CryptoService (PascalCase) vs cryptos.media (camelCase)serviceContainer
16WebRTC and client error logs not sortedselfservice-room.endpoint.js:251,257
17Possible dead end in workflowSelfServiceV2Service.js:737
18”TODO: remove this madness and replace it with a map call everywhere”reportUtils.js:149
19”TODO: now only a mock”SelfServiceCheckerService.js:166

Architecture

#IssueLocation
20process.exit(2) on RabbitMQ close — no graceful shutdownrabbitmq.js:17
21rpcServer.documentUpload overwritten by Presentation RPC server when presentationMode enabledserver.js:409
22Service duplication across processes: each entry point re-instantiates many of the same servicesAll entry points

Security Concerns

See security-audit for full assessment.

Critical

Critical Security Issues

  1. Global TLS bypass: NODE_TLS_REJECT_UNAUTHORIZED=0 disables ALL certificate validation when allowSelfSignedCerts is true (process-settings.js)
  2. JWT secret from config: config.jwt.secret used for socket tokens, self-service tokens — if leaked, allows session hijacking (SocketTokenStorage.js, SelfServiceV2 RPC server)

Medium

Medium Security Issues

  1. Session scanning: All sessions loaded into memory to find user’s sessions (session.js) — DoS vector if many sessions exist
  2. HTTP agent per request: VuerCVFaceRecognitionEngine creates new HTTPS agent per call — no connection pooling, potential resource exhaustion
  3. Credentials in queue messages: SelfServiceV2 queue server masks credentials with 'secret' but only after receiving them through the queue

Low

  • CSP relaxation on multiple paths (/api/document/, /import-data/)
  • Error message exposure: “Something broke into 400 pieces!” (humorous but potentially information-leaking)

Positive Security Features

  • Helmet.js with configurable CSP
  • CSRF protection on all routes
  • ACL-based access control
  • Host header injection mitigation
  • IP filtering and rate limiting
  • Session-based ACL rules
  • Audit logging for all security events
  • Encryption at rest for attachments, media, data
  • Trusted timestamps (RFC 3161)
  • Multiple auth strategies (Local, AD, SAML, WebAuthn, TOTP)
  • Certificate management
  • Resource Access Bypass tokens (short-lived, path-specific)
  • No eval() or Function() — no dynamic code execution found
  • getSecureConfig() properly masks sensitive fields for logging/display

Architecture Patterns Summary

PatternImplementation
Dependency InjectionService Container (singleton module), not a true DI container but serves the purpose
Event-DrivenServiceBus (WildEmitter-based) for system-wide events
Message-Oriented MiddlewareRabbitMQ for all inter-process communication (RPC, Queue, Pub/Sub)
Repository (implicit)Sequelize models act as repositories; dbHelpers provides shared query logic
StrategyAuth strategies (Passport), OCR engines, face recognition engines, storage engines, crypto variants
Template MethodCronJob.run(), TransportSession.terminate(), CVApi.onCallVisionApi()
ObserverEventEmitter throughout (TransportSession, VuerCVWebSocket, ServiceBus, Socket.IO)
Middleware ChainExpress middleware stack, Socket.IO event modules
Feature FlagsExtensive config.get() to conditionally enable services, routes, queues, cron jobs
Customization Layercustomization/ directory provides extension points for API routes, flow handlers, email templates, cron jobs, listeners, portal data, OCR documents

Project Structure

server/
  web/              Express app, routes, middleware, API endpoints
  socket/           Socket.io server and event handlers
  queue/            RabbitMQ RPC servers/clients and queue handlers
  service/          Business logic services (80+)
  db/               Database models (65), relationships, helpers
    model/          Sequelize model definitions
    models.js       Model instantiation and relationships
  flow/             Workflow execution engine (tasks, conditions, branching)
  cron/             Scheduled task definitions (19+)
  convert/          Media conversion workers (FFmpeg)
  e-mail/           Email service (Nodemailer + MJML templates)
  sms/              SMS service
  cv/               Computer vision (face detection, MRZ recognition)
  ocr/              OCR recognition engines and processing
  faceRecognition/  Face recognition engine and hooks
  webrtc/           WebRTC/Janus gateway integration
  transport/        Bidirectional oss<->css transport layer
  portal/           Portal data management and data matching
  partner/          Partner integration logic
  listeners/        Event listeners
  backgroundProcess/ Background process handlers
  room-inspector/   Room state inspection
  bootstrap/        App initialization (DB, Redis, RabbitMQ, process settings)
  acl/              Access control list
  errors/           Custom error classes
  logger/           Log4js structured logging
  util/             Utility modules
  service_container.js  DI container (God Object)
  auth.js           Passport.js strategies (local, SAML, AD, FIDO2, TOTP)
  auditlog.js       Event-driven audit logging (50+ events)
  diagnostic.js     Real-time health monitoring
  gcm.js            AES-256-GCM encryption implementation

client/
  engine/           Custom MVC framework (View, Controller, Service, Metadata)
  features/         Feature modules (auth, videochat, socket, flow, etc.)
  ui/               UI templates, components, styles (Stylus)
    elements/       60+ reusable UI elements
    pages/          50+ page types (admin, reports, appointments, video)
    layouts/        Layout templates
    styles/         Stylus CSS

customization/      Extension hooks (white-label)
  api/              API extensions
  flow/             14 predefined flows (self-service, online verification, esign)
  email/            Email template overrides
  cron/             Cron job extensions
  listeners/        Event listener hooks
  ocr/              Country-specific OCR (HU, RS, SLO IDs/passports/licenses)

engines/            Specialized engines
  worker/           Worker pool executors
  translator/       Translation/i18n engine
  storage/          Storage drivers (local, S3)
  build/            Build utilities
  twig/             Template engine

db/                 Database migrations
  migrate/          Sequential migration files (timestamp-named)
  beforeMigrate/    Pre-migration hooks

workers/            Background workers (bcrypt.js password hashing)
web/                Compiled static assets (DO NOT edit)
config/             Environment configs (dev.json, docker.json, local.json, roles.json)
test/               Test suites (unit, e2e, integration, regression)
docs/               Documentation and config schemas (40+ feature docs)
bin/                CLI utilities and build scripts

Testing

yarn test:unit                     # Jest unit tests
yarn test:e2e                      # Playwright E2E tests (WARNING: can erase DB!)
yarn jest test/tests/unit/         # Specific directory
yarn jest sometest.test.js         # Single file
  • Jest: V8 coverage, 30s timeout, no transform
  • Playwright: Desktop Chrome, single worker, 1720x1080, camera/mic permissions
  • E2E requires: both vuer_oss AND vuer_css built and running
  • Test configs: test/testconfigs/test-config-ci.json (OSS), test-css-config.json (CSS)
  • Shared fixtures: /workspace/test_resources

Development

yarn dev    # Live reload with automatic file rebuilding
yarn build  # Production build (esbuild)

Known Gotchas

GotchaDetails
Mixed JS/TSJavaScript files require() TypeScript files with explicit .ts extension
No TS runtimeNo ts-node/tsx; relies on Node.js --experimental-transform-types or similar
models.ts is criticalserver/db/models.ts imported by 35+ files; single point of failure
Mixed module syntaxESM import + CJS module.exports in same file (models.ts)
Crash loop riskMissing model files cause immediate crash; Supervisor rapidly restarts

Recent Debugging (March 2026)

Crash Loop - Missing Model Module (FKITDEV-7855)

  • Symptom: ERR_MODULE_NOT_FOUND for server/db/model/room, Supervisor cycling PIDs
  • Root cause: Missing callbackrequest model + .ts extension resolution issues
  • Fix: Added .ts extensions to require statements across 38 files
  • Lesson: models.ts is the critical hub; always verify module paths

Sequelize Import Error

  • CreationOptional TypeScript type used in runtime without transpilation
  • Part of broader TS/JS compatibility issue in the codebase

See debugging-log for full details.