esign_oss
One-liner (verified from
README.md+package.json:4)“FaceKom eSign operator side server” — the OSS (Operator-Side Server) of the FaceKom eSign product. A Node.js monolith that backs the bank/operator web back-office, the mobile-app-facing endpoints, the external bank webhook API, and the RabbitMQ RPC surface for the rest of the eSign system. Sibling repos referenced from code: the CSS (customer-side server, queue
esign:css-ping), vuer integration (queuesvuer-esign-rpc,esign-vuer-rpc,rpc-esign:external), and the portal.
This doc describes the devel base branch. The checked-out working branch at verification time was update/customization/instacash-2026-05-27 (a customization branch; see customization-branch-catalog); it differs from origin/devel only by a 4-line addition in config.js (an instacash-specific block). package.json is identical to devel. See also architecture-overview, customization-architecture.
1. Purpose & role in FaceKom
esign_oss is the operator-facing half of the FaceKom eSign two-server design. From the entrypoints and routers it provides four independently-bound surfaces (server.js:323-400):
| Surface | Bind | Port | Source | Audience |
|---|---|---|---|---|
Web (back-office UI + /api/*) | 127.0.0.1 | 10181 | server/web/web-server.js | Bank operators / admins (browser) |
| External webhook API | 127.0.0.1 | 10182 | server/external/external-server.js | Bank back-end systems (server-to-server) |
| Socket.IO realtime | 127.0.0.1 | 10180 | server/socket/socket-server.js | Operator browser live updates |
| RabbitMQ RPC/queue | AMQP(S) | — | server/queue/** | CSS, vuer, cron, other services |
All three HTTP servers bind to loopback only — TLS termination / public exposure is handled by nginx in front (nginx_dev.conf, nginx_docker.conf), and processes are supervised by supervisord (supervisor_docker.conf). The domain entities it owns are signing Offers, Contracts, Customers, Signatures, Documents, and the mobile App/Device registry (server/db/models.js:4-30).
.notes/signature-process.md and .notes/rest-api.md document the end-to-end customer signing flow (app registration → SMS token → operator approval → bank-signed offer → push notification → in-app signature with trusted timestamp).
Naming
Code/queues use the literal prefix
esign:for OSS-owned channels andvuer-/rpc-esign:externalfor vuer-integration channels. Thecustomization/tree layers integration-specific behaviour on top of the core (see §7, customization-architecture).
2. Tech stack & runtime
Verified from package.json:
- Language/runtime: Node.js, CommonJS (
require), no TypeScript in app code (TS only as a dev/test dep forts-jest). - Declared engine:
engines.node: ">=22.13.0"(package.json:6-8). - CI Node version:
NODE_VERSION: "24"(.github/workflows/pull-request.yaml:11). > [!warning] Engine vs CI mismatch — manifest floor is 22.13.0 but CI builds/tests on Node 24. Use Node ≥22.13 locally; CI is the source of truth for the tested version. - Package manager: Yarn (classic).
yarn.lockpresent (447 KB);.yarnrcsets--install.ignore-optional true. CI runsyarn install --frozen-lockfile. - Web framework: Express 5 (
express: ^5.2.1). - DB / ORM: PostgreSQL (
pg: ^8.18.0) via Sequelize 6 (sequelize: ^6.30.1,sequelize-cli,umzugfor programmatic migrations). - Messaging:
@techteamer/mq^7.0.1 (RabbitMQ wrapper) overamqps://. - Realtime:
socket.io/socket.io-client^4.6.1. - Templating: server-side
twig^3 (operator pages) +dustjs-linkedin(client bundles, compiled via browserify), email viainky/juice/dustjs. - Crypto / signing:
node-jose(JWE token encryption),jsonwebtoken,@techteamer/timestamp(RFC-3161 trusted timestamps via OpenSSL),@techteamer/cert-utils(seal cert parsing),pdf-lib+@pdf-lib/fontkit(PDF signing),bcryptjs,hashids. - Auth/ACL:
passport(+passport-local,passport-activedirectory,passport-unique-token),@techteamer/acl,express-session+connect-session-sequelize,csurf,helmet,express-basic-auth. - Notifications:
firebase-admin^13.6.0 (FCM push). - Config:
getconfig(env-driven JSON config),dotenv,cloud-config-client(optional Spring Cloud Config),ajv. - Client build toolchain:
browserify,stylus,autoprefixer,@techteamer/poststylus,hideout,chokidar,browser-sync(livereload). - Lint/test:
eslint9 (flat config,eslint-config-standard),jest30.
3. Build & run
package.json scripts (verbatim from package.json:9-21)
| Script | Command | What it does |
|---|---|---|
style | node bin/style/style.task | Compiles client Stylus → CSS bundles into web/css (one-shot). |
script | node bin/script/script.task | Browserify-bundles client *.script.js / *.layout.js → web/js (one-shot). |
watch | node bin/watch/watch | Runs script + style tasks with --watch + livereload (BrowserSync). |
build | node bin/build/build | Runs both script and style tasks (pushes --no-exit); pass --watch to keep watching. |
trans | node bin/test/trans-check | Translation linter: scans client/ui/pages/** twig+script for missing/unused t.t('…') keys vs each page’s *.trans.js. |
lint | eslint . --max-warnings 0 --ignore-pattern "test/*" && echo 'npm run eslint --max-warnings 0' | ESLint the repo (excluding test/), fail on any warning. |
lint:fix | eslint . --fix && eslint --max-warnings 0 . | Auto-fix then re-lint with zero-warning gate. |
credits | node bin/credits > CREDITS.html | Regenerates CREDITS.html dependency-license table via license-checker. |
test | jest --config ./test/jest.config.js --runInBand --forceExit | Full Jest run, serial. |
test:unit | yarn node --experimental-vm-modules $(yarn bin jest) --config ./test/jest.config.js | Unit-test run with ESM VM modules flag (used by CI). |
test:e2e | yarn jest e2e/* --forceExit | E2E tests under an e2e/* path. > [!warning] No e2e/ directory exists in this repo at devel; only test/tests/unit/** is present. This script targets a path that ships in another context/customization. |
Entrypoints (process binaries)
main is server.js. There are three long-running Node processes, all wired by supervisord (supervisor_docker.conf):
| File | Supervisor program | NODE_ENV | Role |
|---|---|---|---|
server.js | esign_oss → node server.js | docker | Web + external + socket + queue RPC servers. Boot chain: setupServices → checkEmail+setupDb → initServices → setupQueue → setupCustomizations → StartWebServer → StartExternalServer → StartSocketServer → checkSeal (server.js:432-445). |
cron.js | esign_cron → node cron.js | docker | Scheduled jobs: delete-expired-shortener-URLs, revoke-expired-offers, delete-old-documents (cron.js:194-211). Registers RPC server esign:cron-ping. |
background.js | esign_background → node background.js | docker | Background worker; instantiates the same service set as server.js plus BackgroundProcessService(true) (worker mode) (background.js:139-143). |
exitcodes=0,2 in supervisord matches the app convention process.exit(2) on fatal startup errors.
No Dockerfile / docker-compose in this repo
A repo-wide search for
Dockerfile*anddocker-compose*(excludingnode_modules) returns nothing. ThedockerNODE_ENV+config/docker.json+nginx_docker.conf+supervisor_docker.confimply the image is built externally (a shared FaceKom base image / orchestration repo), not here.
Start commands (local dev, NODE_ENV=dev)
From the manifests/configs (not a documented runbook in-repo): build the client assets (yarn build), ensure Postgres + RabbitMQ are reachable per config/dev.json, then run node server.js, node cron.js, node background.js. With config.db.syncOnStart=true (dev default), server.js shells out to ./bin/db/sync then sequelize db:migrate on boot (server.js:178-200).
CI (.github/workflows/pull-request.yaml)
Triggered on pull_request. Jobs: Lint (yarn lint), Unit Tests (yarn test:unit --json --coverage), Audit (yarn audit --groups dependencies + improved-yarn-audit --min-severity critical), SonarQube Scan (consumes jest lcov; config in sonar-project.properties), Build (yarn build). All on ubuntu-latest, Node 24, yarn install --frozen-lockfile.
4. Top-level structure
Verified by listing + sampling (ls, find). Excludes node_modules, .git, logs/.
| Path | What |
|---|---|
server.js / cron.js / background.js | The three process entrypoints (§3). |
config.js | Config loader: wraps getconfig, adds config.get()/config.has(), optional Spring Cloud Config, dev host derivation, build-number suffix, CORS hardening. |
config/ | Env config JSON: dev.json, docker.json, roles.json (ACL role→right map). |
server/ | Core backend (services, db, queue, web, external, socket, sms, e-mail, cron). Bulk of the code. |
client/ | Browser front-end source (ui/pages, ui/layouts, services, engine, utils, resources, polyfills) compiled by bin/script + bin/style. |
web/ | Build output + static assets: compiled js//css/ land here; plus font/, icon/, img/, audio/, libs/, favicon.ico, 502.html. |
customization/ | Per-integration override layer mounted via service-bus hooks; mirrors server/ + client/ui substructure. See §7 & customization-architecture. |
engines/ | Reusable build/templating helpers: build/ (browserify+stylus bundler), dust/, twig/, translator/ (Dictionary), util/. |
bin/ | First-party CLI/build helper scripts (§5). |
db/migrate/ | 7 Sequelize/umzug migration files (db/migrate/*.js, flat dir; 2018–2019 era). |
test/ | Jest config + tests/unit/** (§8). |
docs/features/ | Markdown feature docs (Hungarian): eSign user manual, offer-forward, vuer-external RPC, webserver firewall auth, sms-api, access-css. |
.notes/ | Design notes: signature-process.md, signature-algorithm.md, rest-api.md, esign-stats.sql. |
maintenance/ | 34 dated *.md maintenance logs (2023-07 → 2026-05). |
security/ | 34 dated *.md security-audit logs (2023-07 → 2026-05). |
.agents/ | AgentOps workspace (knowledge/plans/research/etc.) — tooling, not app code. |
.github/workflows/ | pull-request.yaml CI. |
seed-test.js | Dev seeder: creates an enabled test customer (masterId 1001), a created offer with a bank-signed PDF, and forges the URL login token (seed-test.js header). |
nginx_dev.conf / nginx_docker.conf | Reverse-proxy configs (front of the loopback servers). |
supervisor_dev.conf / supervisor_docker.conf | Process supervision (the 3 node procs + nginx). |
eslint.config.mjs, .editorconfig, .browserslistrc, sonar-project.properties, .sequelizerc, .yarnrc | Tooling config. |
CREDITS.html, changelog.md, PULL_REQUEST_TEMPLATE.md, README.md | Docs/meta. |
5. First-party bin/ scripts (every file, read)
Located under bin/ (NOT node_modules). Build helpers + DB/ops CLIs.
Build / asset pipeline:
bin/build/build.js— Pushes--no-exitto argv, then runsscript.task+style.taskin parallel; exits unless--watch. Backsyarn build.bin/script/script.task.js— Declares browserify bundles forclient/ui/pages|layoutsandcustomization/ui/pages|layouts*.script.js/*.layout.js→web/js; under--watchwatchesclient/customization **/*.js|*.dustwith livereload. Delegates toengines/build/build.bin/script/script.compiler.js—compileBrowserify: bundles one JS file withbrowserify+browserifyDusttransform +browserify-require-not-found-parentplugin; source maps gated onconfig.build.generateSourceMaps.bin/style/style.task.js— Same shape asscript.taskbut for*.style.styl/*.layout.styl→web/css;--watchwatches**/*.styl.bin/style/style.compiler.js—compileStylus: renders Stylus, injectingclient/resourcesbreakpoints,device-sizes.json, and colors as Stylus globals; auto-importsclient/ui/styles/global.styl; runs autoprefixer via poststylus.bin/watch/watch.js— Pushes--watchto argv andrequires both tasks. Backsyarn watch.bin/credits—#!/usr/bin/env node; runslicense-checkerand prints an HTML license table to stdout (redirected toCREDITS.htmlbyyarn credits).bin/test/trans-check.js—#!/usr/bin/env nodecommanderCLI (--no-missing,-u/--unused,-c/--collapse). For each page underclient/ui/pages, loads its*.trans.jsviaengines/translator/Dictionary, scans the twig template (following{% include %}) + script fort.t('key')references, and reports missing/unused translation keys. Backsyarn trans.
DB / operations CLIs (under bin/db/):
bin/db/create_user—#!/usr/bin/env nodecommander<role> <username> <password> [email] [firstName] [lastName]. Validatesroleagainstconfig/roles.jsonvia@techteamer/acl; refuses ifconfig.activeDirectoryis set; bcrypt-hashes the password (config.security.password.bcryptCost), inserts aUserwithrights:[role], and writes anAuditLoguser/createdevent (fromCli:true).bin/db/sync—#!/usr/bin/env nodecommander-f/--force.sequelize.sync(); with--forceprompts (inquirer) “you will lose all your data?” beforesync({force:true}). Invoked at boot whendb.syncOnStart(server.js:183).bin/db/truncate—#!/usr/bin/env node. Inquirer-confirmed truncate of all models exceptUser,OpenHourStandard,OpenHourException;cascade:true, disables FK checks on MySQL.bin/db/migrate-data—#!/usr/bin/env node. Umzug-based old-DB → new-DB data migration tool: authenticates an old DB by URL, force-syncs +umzug.up()a new DB (fromserver/db/sequelize), andtruncates tables before copying. (Glob./db/migrate/*.js.)bin/db/pg_sanity_check—#!/usr/bin/env node. Postgres-only introspection: dumps JSON of everypublictable with row counts, sizes (pg_size_pretty), columns, FK relations, other constraints, and index names. Read-only.bin/db/fetchCustomerDataAndExtendCSV.js— Node script (no shebang). Reads a CSV whose first column is a vuer_osscustomerId/external id, looks up customer data from the DB, and writes an extended CSV; ensures the output dir exists.commander-driven.
Other:
bin/attachment.js—#!/usr/bin/env nodecommanderexportscommand (-o/--output,-i/--idcsv). ExportsAttachmentrows namedScreenShotfor the given customer id(s) to<output>/customer-<id>/<id>-<name>-<category>.<ext>.bin/sms-api—#!/usr/bin/env nodecommander(-f/-tdatetime range,-ssource CSV,-ddest CSV,-eextended). Joins SMS-provider CSV export againstSmsLogrows in[from,to]and computes delivery-delta columns (status-date − createdAt; extended adds SMSAPI-TSP / OSS-SMSAPI deltas). Documented indocs/features/bin/sms-api.md.
6. Key modules / services / entities
Service container & boot wiring
server/serviceContainer.js— Exports a singleton{ emitter }whereemitteris aServiceBus extends WildEmitter. The central DI + hook bus:addHook/callHooks/callOnlyHook(promise fan-out over named tags likeservices,queue,routes,cron,webserver:setup) andregisterOverride/callOverride. Everything (serviceContainer.service.*,.queue,.db,.dbModels,.io, …) is hung off this object at boot.server/logger.js— log4js config. Channels:esign,sql,express,csp,background,cron; appendersconsole(always) + optionalfile/syslog/papertrail(gated onconfig.logging.*). Default channel chosen from the entry script name (server.js→esign,cron.js→cron, etc.). Throws if an unsupported appender is configured.server/acl.js— Loadsconfig/roles.jsoninto a@techteamer/aclACLServicesingleton.server/auth.js—isAuthorized/hasRightplusdoIfAuthorized/doIfHasRightwrappers used by socket/web handlers; reloadsclient.userbefore invoking the callback.server/gcm.js— AES-256-GCM authenticated-encryption stream (Transform) + PBKDF2 key/salt helpers (used for at-rest data protection).server/diagnostic.js,server/auditlog.js,server/SocketTokenStorage.js,server/child_process_promise.js— diagnostics round-trips, audit-log writer, socket token store, promisifiedexec.
Services (server/service/, 28 files; instantiated in server.js:112-153 / background.js)
Most important (read):
OfferService.js(28 KB) — Offer lifecycle: create,receiveBankSignedOffer, packaging/zip (archiver), forwarding to bank via HTTPS agent (cv.rejectUnauthorized), JWT-signed links (config.jwt).CustomerService.js(23.5 KB) — Customer registration/bootstrap/approval/data.SignatureService.js(16.7 KB) — Core signing state machine:processCustomerPublicKeyMessage(m1 ts1Data/ts1/ts1JSON),cancelSignatureAttempts,createSignature, two-factor token,SignatureValidator; shells out to OpenSSL (execFile).AppService.js(17.4 KB) — Mobile app/device registration, version compatibility (semver), FCM push (e.g. oncontract:sealedhook).ContractService.js(10.9 KB),DocumentService.js,DealService.js,ActivityService.js— contract sealing, document storage, deal grouping, activity log.TrustedTimestampService.js— wraps@techteamer/timestamp(TrustedTimestampServiceLib('short', config.trustedTimestamp, …)):createTimestampToken(digest, hashAlgorithm, dataSize),verifyTsr,getTimestampInfo,testService(validates OpenSSL setup at boot).TokenService.js—node-joseJWE encrypt/decrypt using thefacekomkey fromconfig.jwt.keystore.SettingsService.js— DB-backed (Settingmodel) runtime settings with in-memoryMap+ defaults;init()runs at boot.BackgroundProcessService.js(13.3 KB) — background job runner (worker mode inbackground.js).- Others:
FcmService,SmsService(server/sms/),EmailService(server/e-mail/),HashService,RsaService,CryptoService,PasswordService,ShortenerService(hashids URL shortener),IpFilterService,OnlinePresenceService,SocketService,DisasterModeService,JWTService,LiveUpdateService,SignatureTemplateService(+server/signature-template/SignatureTemplateHandler.js),TempFileService,ClientErrorLogService,diagnostic.
Persistence (server/db/)
server/db/sequelize.js— SingleSequelizeinstance fromconfig.db.url(+config.db.options), pool max default 20, SQL logging only indev. AddsbeforeFind/beforeCounthooks that stripundefinedWHERE keys (and warn) — a guard against accidental full-table queries. A 5s interval logs pool-usage (info/warn/error at 0.4/0.6 thresholds).server/db/models.js— Registers ~27 models fromserver/db/model/*.jsand wires associations. Core graph:CustomerhasManyOffer/Contract/Signature/Document/CustomerData/Activity/App/SmsLog/EmailLog;ContractbelongsToCustomer/Signature/Offer/TimestampToken;SignaturebelongsToCustomer/App/Offer, hasManySignatureData;AppbelongsToCustomer/FcmInfo/Device. PlusUser,AuditLog,Setting,Shortener,Cert,ClientErrorLog,BackgroundProcess(+Log),Attachment,VerificationToken,Session(connect-session-sequelize).server/db/model/*.js(26 model defs) +server/db/translations/*.trans.js(21 enum/label translation maps; flat dir) +helpers.js,migrationHelpers.js,SignatureValidator.js.db/migrate/*.js— 7 umzug migrations.
HTTP surfaces
- Web
server/web/web-server.js(WebServerclass) — Express 5 app: per-request nonce, fully config-driven helmet + a hand-built CSP (script'self'+nonce,connect wss://host, sandboxed, CSP exempt for/api/document/*&/api/screenshot/*,allow-downloadson/offer/*), body/cookie parsers, log4js connect logger,locale. Chained setupsetupLocale/Session/Flash/Twig/Routes/CSPReportViolation/404/Disaster/ErrorHandler(server.js:325-344).server/web/routes.js— back-office GET pages (/,/customerlist,/offerlist,/contractlist,/signature/:id,/auditlog,/users,/systemsettings,/eseal, …, each ACL-gated viaisAllowed/anyAllowedagainstconfig/roles.json) +/api/*(document/attachment/signature/screenshot, offer upload/revoke/forward, cert upload, customer approve/disable, role-switch, sentry). Many routes are feature-flagged onconfig.features.*/config.seal/config.certManager.server/web/api/{admin,common}/(16 files),server/web/routes/*.endpoint.js(20 files),server/web/{session,flash,Template,WebServerAuth}.js.
- External
server/external/external-server.js— separate Express app (helmet, noCache, body/cookie parsers, disaster-mode guard).server/external/routes.jsmounts bank webhooks, each individually toggled byconfig.webHooks.*and optionally Basic-Auth’d:POST /offer/upload,/offer/revoke,/contract/upload,/signature/verify,/customer/bootstrap,/customer/send-association-token,/customer/approve,/app/notification. (server/external/auth.jsis a no-op placeholder; real auth is per-route basic-auth + theexternal:routeshook.) - Socket
server/socket/socket-server.js+server/socket/events/{acl,auth,headerinfo,pagevisit,ping}.js,client.js.
Queue (server/queue/) — see §9.
7. Configuration
- Loader:
config.jsrequiresgetconfig(selectsconfig/<NODE_ENV>.json; e.g.dev→config/dev.json,docker→config/docker.json). On a JSONSyntaxErrorit parses the offending file/offset and prints a context window beforeprocess.exit(2). Adds:config.get('a.b.c', default=null)andconfig.has('a.b.c')accessors (config.js:115-152).- Build-number suffix: appends
.${ESIGN_BUILD_NUMBER}from./.envtoconfig.version(config.js:104-112). - Optional Spring Cloud Config (
config.springCloudConfigServer): loads remote config viacloud-config-clientwithpromise-retry, dot-merges intoconfig; result onconfig.loaded(config.js:73-99). Otherwiseconfig.loaded = Promise.resolve(). - Dev host derivation (
NODE_ENV==='dev'): fillshosts.css/oss/api+portal.urlfromDEV_DOMAINor/etc/hostname(config.js:41-62). - CORS/socket hardening: rewrites
web.cors.origin: '*'/web.socketorigins to the actualhosts.oss(config.js:154-172).
- Config files:
config/dev.json(~320 lines) — the canonical full schema sample. Top-level keys:portal,demo,hosts,jwt(secret + JWEkeystore),web(session,socket,socketioSettings,trustedProxy,cors),app.compatibility,shortener,trustedTimestamp(PdfSigner),security(password.bcryptCost,cookie,twoFactorAuth,loginthrottling,ipFilter),features(disasterMode, offerUpload/Forward/Revoke/Package, approveCustomer, roleSwitch, …),seal(pfx path+password),customizations,signatures(templates),certManager.cryptoKey,db(url,syncOnStart),fcm.serviceAccount,email.transport.SMTP,sms(senderSmsApiCom),queue(amqpsurl + mTLScert/key/ca,rpcTimeoutMs,rpcQueueMaxSize),locales,logging,diagnostic,settings,build(generateSourceMaps,liveReloadSettings),timeouts(signOffer,deleteDocumentswith cron schedules),version,externalApi,webHooks,backgroundProcess.config/docker.jsonis the production-shaped equivalent.config/roles.json— ACL role→rights.adminhas ~14 rights (auditLog.view, customers.documents/attachments/signatures.view, disasterMode.change, electronicSeal.view, systemSettings.view, users.create/list/change.*, cert.upload, email.preview);operatorhas onlyusers.list,cert.upload.
.sequelizerc— points sequelize-cli atconfig.db.url, migrationsdb/migrate, modelsserver/db/model.- Env vars (observed in code):
NODE_ENV(getconfig file + dev branches),DEV_DOMAIN,ESIGN_BUILD_NUMBER(via.env),TZ(forced toEtc/UTCat boot),NODE_TLS_REJECT_UNAUTHORIZED(set to0whensettings.allowSelfSignedCerts). Supervisor injectsNODE_ENV=docker,DOCKER_USER,APP_HOME. - AJV:
ajvis a dependency and aresolutionspin (umzug/**/ajv: >=8.18.0); no first-party top-level AJV schema files were located in the surveyed source (validation usage, if any, lives inside services/customization not exhaustively read — see gaps).
Secrets committed to
config/dev.json
config/dev.jsoncontains real-looking dev secrets: a Firebase service-account private key, JWT/session/shortener secrets, an SmsApiCom AuthToken, a seal pfx password (techteamer), and mailtrap creds. These are dev fixtures, but treat the file as sensitive and never copy its values to non-dev environments.
8. Tests
- Framework: Jest 30 (
jest,ts-jest,@types/jest). - Config:
test/jest.config.js—rootDir= repo root; ignoresnode_modules,web/,yarn-offline-cache/; coverage on (v8,lcovonly→test/coverage/jest),testTimeout: 30000, emptytransform(no Babel). - Location:
test/tests/unit/:web-server-auth.test.jsservices/signature-service.test.jswebfolder/api/common/cert-upload.test.jscustomization/server/queue/vuer-external.test.js
- Run:
yarn test(jest … --runInBand --forceExit) oryarn test:unit(ESM VM modules, used by CI).yarn test:e2etargets a non-existente2e/*here (see §3 warning).
9. Dependencies on other FaceKom services (evidenced in code)
RabbitMQ (@techteamer/mq, config.queue.url amqps://, mTLS)
server.js:223-317 (setupQueue) wires the OSS queue topology. cron.js:132-192 and the customization/customization.js queue hook add more.
RPC servers exposed by OSS (esign:rpc-* etc.):
esign:rpc-app, esign:rpc-customer, esign:rpc-timestamp, esign:rpc-document, esign:rpc-contract, esign:rpc-offer, esign:rpc-signature, esign:rpc-signature-check. (cron adds esign:cron-ping.) Customization adds esign-vuer-rpc and rpc-esign:external (customization/customization.js).
RPC clients OSS calls out on:
esign:css-ping(PingRPCClient) → CSS (customer-side server) liveness.esign:cron-ping(PingRPCClient) → cron process.esign:rpc-system-oss(SystemOssRPCClient).vuer-esign-rpc(EsignRPCClient, customization) → vuer integration.
Queue servers (consumers): esign:queue-revoke-expired-offers, queue-clienterror-log.
Queue clients (producers): esign:queue-service-bus (sends 'started' after socket boot, server.js:398), esign:queue-customer, esign:queue-contract.
Publishers/subscribers: esign:settings-change, and (when config.backgroundProcess) esign:background-process.
On RabbitMQ connection close the process exits with code 2 (server.js:233-237) so supervisord restarts it.
PostgreSQL
Required. config.db.url (postgres://…); Sequelize 6 pool (max 20). Migrations via sequelize-cli/umzug. See §6.
HTTP integrations
- Bank back-end — inbound via the External webhook API (§6) and outbound via
OfferServiceHTTPS calls +config.externalApi.*/config.portal.callbackApi(offer-timeout report, signed-offer endpoint, customer login/auth/data endpoints inconfig/dev.json). - TSA (trusted-timestamp authority) —
config.trustedTimestamp.providers[].url(e.g.https://bteszt.e-szigno.hu/tsa) via@techteamer/timestamp. - Firebase / FCM —
firebase-adminfor push (config.fcm). - SMSAPI.com —
config.sms.sender.SmsApiCom.baseUrlfor SMS. - CSS config —
POST /api/admin/css-configweb route pushes config to the customer-side server.
No Redis dependency was found (no redis/ioredis in package.json; sessions use Postgres via connect-session-sequelize).
10. Verified gotchas
All HTTP servers bind to loopback (
127.0.0.1)Web (10181), External (10182), Socket (10180) are not directly reachable off-box — nginx (
nginx_*.conf) must front them. (server.js:350,364,380.)
Fatal-startup convention is
process.exit(2)server/cron/background all exit 2 on boot failure or RabbitMQ disconnect; supervisord whitelists exitcodes
0,2andautorestart=true.
db.syncOnStart=trueruns schema sync + migrate on every bootIn dev,
server.jsexecs./bin/db/syncthensequelize db:migrateat startup (server.js:178-200). Safe for dev DBs; do not enable against a DB you can’t lose.
bin/db/truncateandbin/db/sync --forceare destructiveBoth wipe data (truncate keeps only
User/OpenHour*;sync --forcedrops everything). Inquirer-guarded, but irreversible.
Sequelize
undefined-WHERE guard
server/db/sequelize.jsdeletesundefinedkeys from everywhere(and logs a warning) before find/count. A query built with anundefinedfilter value silently loses that condition — check logs for “WHERE parameter … invalid ‘undefined’ value”.
Customization via service-bus hooks
customization/{customization,cron-customization,background-customization}.jsregisterservices/queue/routes/cron/webserver:setup/sockethooks onserviceContainer.emitter. Theinstacashbranch builds on this; the corecustomization.jsalready wires vuer RPC + a customization-layerCustomerService/ExternalServiceand core listeners (customer-bootstrap,customer-auth-token, etc.). See customization-architecture, customization-branch-catalog.
config/dev.jsonis the de-facto config schemaThere is no JSON-schema/AJV contract file in-repo;
config/dev.json+config/docker.jsonare the reference for valid keys. New config keys are read defensively viaconfig.get(path, default).
Unverified / gaps
- Large subtrees surveyed structurally (listed + key files sampled), not line-by-line:
server/web/api/{admin,common}/(16 files) andserver/web/routes/*.endpoint.js(20 files) — router wiring read viaserver/web/routes.js; individual endpoint handlers not all read.server/queue/**(23 files) — topology read fromserver.js/cron.js; individual RPC/queue handler bodies (e.g.rpc_server/Signature.js) not read line-by-line.client/**front-end source — structure mapped; only the build wiring (bin/script,bin/style,engines/build) was read, not page scripts/templates.customization/**(api/external/server/listeners/portal/sms/translations/ui) — entrypoints (customization.js,cron-customization.js,background-customization.js) read; integration sub-modules and theinstacashbranch overrides not exhaustively read (covered by customization-architecture/customization-branch-catalog).server/db/model/*.js(26 model defs) +*.trans.js— registration + associations read frommodels.js; per-field column definitions not enumerated.maintenance/(34) andsecurity/(34) dated logs — listed, not read.
- Service internals: of the 28 services, the largest (Offer/Customer/Signature/App/Contract/Background) were read at the top/representative level, not in full.
DealService,IpFilterService,OnlinePresenceService, etc. read only as headers/sizes. - AJV usage: confirmed as a dependency; no top-level first-party schema file found. Whether services validate payloads with AJV at runtime was not traced into every handler.
- Branch scope: documented
devel(working tree =update/customization/instacash-2026-05-27, +4 lines inconfig.jsvsdevel). Other 40+ customization/feature branches not inspected here. - Deployment image: no Dockerfile/compose in-repo; the actual container build and how nginx+supervisor+certs are assembled live outside this repo (not verified).
Sources
Files/dirs actually read:
package.json,README.md,changelog.md,.sequelizerc,.yarnrc,config.jsserver.js,cron.js,background.js,seed-test.jsconfig/dev.json,config/roles.jsonsupervisor_docker.conf,.github/workflows/pull-request.yamlbin/attachment.js,bin/credits,bin/sms-api,bin/build/build.js,bin/script/script.task.js,bin/script/script.compiler.js,bin/style/style.task.js,bin/style/style.compiler.js,bin/watch/watch.js,bin/test/trans-check.jsbin/db/create_user,bin/db/sync,bin/db/truncate,bin/db/migrate-data,bin/db/pg_sanity_check,bin/db/fetchCustomerDataAndExtendCSV.js(head)server/serviceContainer.js,server/logger.js,server/acl.js,server/auth.js,server/gcm.js(head)server/db/sequelize.js,server/db/models.js(head)server/service/SignatureService.js(head),server/service/OfferService.js(head),server/service/AppService.js(head),server/service/TrustedTimestampService.js(head),server/service/TokenService.js,server/service/SettingsService.js(head)server/external/external-server.js,server/external/routes.js,server/external/auth.jsserver/web/web-server.js(head),server/web/routes.jsengines/build/build.js(head)customization/customization.js,customization/cron-customization.js,customization/background-customization.js,customization/RELEASE.mdtest/jest.config.js,.notes/signature-process.md(head),.notes/rest-api.md(head)- Directory listings: repo root,
server/(+ all subdir file counts),server/service/,server/queue/,server/external/,server/web/{api,routes},server/db/{model,translations},server/socket/,server/sms/,server/e-mail/,server/signature-template/,config/,customization/(depth 2),db/migrate/,docs/features/,.notes/,engines/,test/,bin/ - Git:
git -C … branch -a,git -C … log(devel + working branch),git -C … diff --stat origin/devel