For Agents
Living index of themes for the FaceKom KYC platform (vuer_oss / vuer_css / vuer_cv). Each H2 is a topic; bullets are wikilinks to related notes. Updated by obsidian-documenter when documenting work. Read by historian at bootstrap. Topics kept alphabetical.
Build / probe-build workflow (UBI10)
- FKITDEV-8252 — podman + libkrun on macOS Apple Silicon for emulated linux/amd64 builds; needs 8 GiB RAM minimum (4 GiB OOMs on gcc-c++ family installs), 6 CPUs sufficient; iteration counts as complexity proxy (portal_css 3, vuer_css 3, vuer_oss 5, janus 7, vuer_cv 7); subagent Bash allowlist is more restrictive than main-session shell — plan Phase B with this in mind
CI / build gates
- depcheck-false-positive-minified-bundle — depcheck can report a CI-only false positive because it fails OPEN on unparseable files. vuer_css CI flagged
@emotion/is-prop-validas unused while the identical pinneddepcheck@1.4.7+ lockfile was clean locally and in a Linux container. The only reference is a literalrequire("@emotion/is-prop-valid")in a try/catch atweb/sdk/web-sdk.js:205, andweb/sdkis not inignore-patterns— CI’s depcheck evidently can’t parse the 865 KB minified vendor bundle (OOM/timeout on the self-hosted runner) and then treats the file as containing no requires. Do NOT remove the dependency — it flips depcheck to reporting it missing. Fix = add toignoresin.depcheckrc.json. Generalized triage rule: a depcheck diff between CI and local with identical version+lockfile points at a parse failure on a big minified/vendored file, not a real dependency change. First hit on FKITDEV-8387; job introduced by FKITDEV-8239 - FKITDEV-8239 — SonarCloud “Security Rating on New Code” gate fix (2026-06-23): after the depcheck PRs opened, the gate FAILED on 4/5 PRs because the new workflow lines tripped SonarCloud’s GHA supply-chain rules —
npx(on-demand install; confirmed sole driver on vuer_css),yarn install(lifecycle scripts), unpinnedactions/*@v6(use full commit SHA); the existing jobs use the same patterns but are grandfathered as old code, only the PR’s new lines are gated. Profiles differ per repo (vuer_css=npx only; portal_css=all three). Fix (3 options considered): appended.github/**tosonar.exclusionsin eachsonar-project.properties(already present insonar.coverage.exclusions); pushed solo-authorandras.lederer(vuer_ossc2b5cfcb3f, vuer_css93c9d976e, portal_css7ee62cbd, esign_oss4e96053, esign_css9f9b862).gh pr checks: initially 4/5 green (vuer_css #3076, portal_css #703, esign_oss #353, esign_css #253); vuer_oss #8001 was red but NOT sonar/NOT this change — pre-existing self-service-room-archive Unit Tests failure (2 tests, async-leak; 3512 pass/2 fail) that also failed ondevel, sonar/build skipped behind the test job. RESOLVED 2026-06-23: colleague merged the test fix to vuer_ossdevelin PR #8003 (commitcfdc116543); mergedorigin/develinto the depcheck branch (clean, no conflicts — devel only touched CODEOWNERS + the test file; merge commit3717e30b91solo-author) and #8001 re-ran fully green. All 5 FKITDEV-8239 PRs now green and ready to merge (#8001/#3076/#703/#353/#253). Reusable gotcha → SonarCloud “Security Rating on New Code” can fail on new CI workflow lines - FKITDEV-8239 — adversarial deep-review verdict (2026-06-23): NO bugs, ship as-is.
actionlintv1.7.12 clean (exit 0) on all 5 workflows (full Actions schema + expression validation); all 5 diffs purely additive vsorigin/devel(31 insertions/0 deletions);${{ env.NODE_VERSION }}=“24” resolves in all 5; barenpx -y depcheck@1.4.7auto-discovers.depcheckrc.json; the 5 job blocks byte-identical except the intended install spelling (yarn --frozen-lockfilevuer_oss vsyarn install --frozen-lockfile×4); depcheck warn-only (exit 255 absorbed bycontinue-on-error),unused_devDeps=[]; extra finding — portal_css has a genuine missing devDependencyistanbul-lib-coverage. Merge-time op rule: do NOT add theUnused Dependenciesstatus check to branch-protection required checks or it stops being warn-only - FKITDEV-8239 — warn-only depcheck CI job across all 5 repos (vuer_oss/vuer_css/portal_css/esign_oss/esign_css);
continue-on-error: true, not in anyneeds:graph → never blocks a PR; tool pinnednpx -y depcheck@1.4.7(correct on both CI and macOS npm v10);.depcheckrc.jsonignores build/lint/test tooling + dynamically-loaded runtime deps (pg/pg-hstore via Sequelize dialect, postcss via build pipeline) + vendored asset paths; Yarn Constraints NOT implemented (Yarn Classic v1 — Berry-only feature); candidates surfaced: vuer_osssoap/umzug, vuer_cssadd, portal_csslodash/tmp/tough-cookie, esign_ossajv/fast-xml-parser/inquirer/jsdom/protobufjs/umzug, esign_csslicense-checker/postcss; portal_css over-suppression bug found+fixed (those 3 were genuinely unused — adding to ignores hid the signal the ticket exists to surface); all LOCAL/uncommitted onchore/FKITDEV-8239-depcheck-ci - FKITDEV-8887 — reading SonarCloud PR issues without a Sonar token (reusable, vuer_css projectKey
vuer-css, orgtechteamer): SonarCloud posts every issue as a GitHub check-run annotation on the PR head commit (gh pr view <n> --json statusCheckRollup,headRefOid→ find “SonarCloud Code Analysis” + head SHA →gh api repos/o/r/commits/<sha>/check-runsfor the run id →gh api repos/o/r/check-runs/<id>/annotations);sonarqubecloudbot also leaves a PR summary comment. Gate gotchas: a passing Quality Gate ≠ zero issues (gate checks only new-code threshold metrics — coverage/duplication/rating — so it’s GREEN with many code-smell “New issues”); no analyzeddevelbaseline (onlypull-request.yamlruns Sonar) → Sonar attributes pre-existing smells in a touched file to the PR, confirm authorship withgh pr diff <n>; annotation_levelfailure= issue severity, not a gate failure. Full recipe in 10. Verified gotchas - SonarCloud “Security Rating on New Code” can fail on new CI workflow lines — adding NEW lines to a SonarCloud-scanned GitHub Actions workflow can fail the “Security Rating on New Code” gate via GHA supply-chain rules (
npxon-demand install,yarn install/npm installlifecycle scripts, unpinnedactions/*@vNSHAs) — even when the rest of the CI already uses those same patterns (grandfathered as old code; only the PR’s new lines are gated). Profiles differ per repo. Resolutions: (a) exclude.github/**viasonar.exclusions(TechTeamer repos already exclude it fromsonar.coverage.exclusions); (b) run CLI tools via a pinned devDependency instead ofnpx+ pin actions to full commit SHAs. The issue/rule REST APIs need auth for these private projects, but the per-PR findings are readable via GitHub check-run annotations (gh api repos/<repo>/check-runs/<id>/annotations— full recipe in FKITDEV-8887). First hit on FKITDEV-8239 - ci-github-branch-audit-chronically-red — the “Github CI - Branch” workflow (
.github/workflows/audit.yaml:33in vuer_oss) is chronically RED on customization branches and is NOT a regression:improved-yarn-audit --min-severity critical --exclude <GHSAs>exits 4 on any critical advisory in a transitive dep not on the--excludeallowlist (as of 2026-06-04:twig>locutus,@techteamer/timestamp>…>basic-ftp,@kafkajs/confluent-schema-registry>protobufjs,request>form-data). Base branchcustomization/raiffeisenhas failed it on every push since ≥April 2026; team merges through it and clears it by appending triaged GHSAs to--exclude(security acceptance) or remediating. Triage rule: commit didn’t touchpackage.json/yarn.lock+ base already red ⇒ not your change. The real per-change gates are lint (yarn lint,--max-warnings 0, ignorescustomization/test/*) and unit tests (yarn jest <file>) - customization-branch-ci-pipeline-inheritance — systemic, will recur: legacy partner branches ran a single CI job (
lint-and-build, old.github/workflows/pull-request.yamlblobec0a1244); devel’s current workflow (blobdda79403) runs lint / test / audit / depcheck / sonar / build. So the first devel→customization merge makes four jobs run on that branch for the very first time, surfacing years of latent breakage in one PR. On cofidis (FKITDEV-9059): 5 failure clusters, only 2 merge-introduced, the rest dating 2017–2024. Two structural amplifiers: partners fork core source files in place (no override layer, e.g.server/service/FlowLiveUpdateService.js→ forked file violates the core unit test), and there is no customization-aware unit-test layer (jest.config-unit.jsmatches onlytest/tests/unit/**, no per-partner test dir) so fixing a partner-specific test failure means diverging a shared core test file that then conflicts on every subsequent devel merge — a recurring tax, not a one-off - cve-2025-7783-form-data-via-request — Audit-job debugging trap:
ERROR: Unable to parse yarn audit output: SyntaxError …and Node 24’sDEP0169 url.parse() DeprecationWarningare cosmetic red herrings —improved-yarn-auditmerges child stdout+stderr into one NDJSON stream so the deprecation warning corrupts lines, and the tool silently skips unparseable ones. Identical errors appear on green devel runs (proof: vuer_oss PR #8062, job87891787317,Found 0 vulnerabilities, conclusion success). The exit code comes solely from the genuine advisory count — don’t chase the parse error, find the real advisory - nusz-devel-update-2026-06-16-lint-merge-fix — concrete case of the lint gate catching a bad merge:
yarn lint(eslint . --max-warnings 0 --ignore-pattern "test/*") failed the NÚSZ devel-update merge with 1n/no-missing-requireerror (cron.js:46, extensionless require of a module devel had renamed.js→.ts); merge correctly held back uncommitted until fixed - FKITDEV-8981 — move PR checks off
ubuntu-latest→ self-hosted[self-hosted, node]across 7 repos’ single PR-check workflow.github/workflows/pull-request.yaml: 33 identicalruns-onedits (vuer_oss/vuer_css/esign_oss/portal_css/mq 5 each, esign_css/janus-api 4 — they omit thetestjob; jobs ∈ {lint,test,audit,sonar,build}). Repo resolution:@techteamer/mq→TechTeamer/mqdefaultmaster;janus_api→TechTeamer/janus-api(hyphen)master(TechTeamer/janus_apidoes not exist); css/oss baseorigin/devel, mq+janus-apiorigin/master. Scope: portal_csspr-title-lint.yamlalready removed on devel (PR FKITDEV-8976) and push-triggeredrelease-caller.yaml(reusablenode-semantic-release.yaml@master, noruns-on) is out of scope ⇒ onlypull-request.yaml— re-scope against post-fetch devel. Job NAMES unchanged ⇒ branch-protection required-status-checks stay valid. Worktrees<repo>-FKITDEV-8981onchore/FKITDEV-8981-self-hosted-runners; verified (numstat 5/5/5/4/5/5/4, zeroubuntu-latestresidue, YAML parses) but NOT committed/pushed, NO PRs. Hard dependency/risk: inert + dangerous without onlinenode-labelled (+ implicitself-hosted) runners carrying git + Node/yarn (setup-node@v6 cache: yarn) +SonarSource/sonarqube-scan-action@v6(sonar = likeliest self-hosted gotcha); if none online at merge, every PR check queues forever and ALL PRs in these repos block. “Build-green ≠ runs” — true validation needs a live PR hitting anoderunner. Precedent: vuer-releaseautobuild.ymlalready on[self-hosted, docker]. Commit-msg stylechore: [fkitdev-8981] run PR checks on self-hosted runners - FKITDEV-8533 — SonarCloud “Maintainability Rating on New Code” gate FAILED on vuer_oss PR #8013 (the Janus CVO un-gate fix, branch
fix/FKITDEV-8533-videoorient-ungate; rated C, then D after a refactor) — and it is pre-existing-debt mis-attribution, NOT the fix (2026-06-29). All 20 flagged issues are pre-existing (git blame2018→Jan 2026; authors Jordán/Bence/jurki/kzsolt/Makkai; SonarCloud issue keys e.g.AZ8A1W4d…/AZ8A1W6o…identical before & after a PR refactor); decisive control = the co-modifiedserver/db/model/customer.jscarries zero flags, proving the diff is innocent — the gate counts legacy smells in any touched file, most likely becausedevelhas no SonarCloud baseline analysis (projectvuer-ossis private; New Code config unconfirmable without a token). Gotcha: any PR touchingvideochat.js/RoomTransportSession.js/SelfServiceTransportSession.js/VuerCVListenerSession.js(legacy optional-chain/.find/async smells) re-trips this → waive (mark issues Accept / admin-merge) or fix the baseline (Project Settings → New Code → Reference branch =devel, ensure devel is analyzed); do NOT bloat a targeted PR by “fixing” the unrelated debt — esp. the 2[failure]-severityVuerCVListenerSession.jsitems (async-in-constructor + await-non-Promise, behavioural CV refactors). Decision (user, 2026-06-29): waive as pre-existing debt. Fix final state: helperserver/transport/videoOrientExt.jsrefactored intoCustomer.prototype.videoOrientExtEnabled()calledX.customer?.videoOrientExtEnabled() ?? trueat the 4 sites; commit1815f693fe(amended overd27d4cc990), solo-author, force-with-lease pushed; device test still pending - mjml-v5-esm-breaks-commonjs-email-templates — “green CI, broken runtime”: unit tests never boot
EmailService, so the MJML-v5 ESM regression on FKITDEV-9059 cofidis (ReferenceError: require is not definedatEmailService.init; the letter type never registers so its email never sends) passed all CI and only failed when the service actually started on fk-dev. Same class as FKITDEV-8981’s “build-green ≠ runs” and the FKITDEV-9059 innerHTML /web/-404 bugs; detection is runtime-only (deploy + restart, watch letter-registration errors: 3/boot → 0 after the fix)
Container health / images (dev-box)
- dev-box-esign-container-startup-failures-2026-06-01 —
esign_css/esign_osscame upunhealthybecause nginx (non-roottechteameruid 1000) couldn’t write its PID: bakednginx.confline 6pid /run/nginx.pid;but/runisroot:root→[emerg] open("/run/nginx.pid") failed (13: Permission denied)→ nginx FATAL → unhealthy (app/redis/cron all RUNNING; image regression, not the InstaCash update); imagesesign_{css,oss}:2024.4.1-20240614were rebuilt ~2025-12-08 w/ nginx 1.28 (tag date misleading); ephemeral fixsedPID →/tmp/nginx.pid+supervisorctl restart nginx(lost on recreate,/etc/nginxnot bind-mounted) → durable fix = bake the PID path into the images. Healthcheck/usr/local/bin/supervisor-health-check.sh: unhealthy if any supervisord prog ≠ RUNNING or uptime0:00:[0-5][0-9](< 60s anti-flap) → ANYsupervisorctl restart= ~60s unhealthy then auto-recovers (interval 60s, retries 3, start-period 60s)
Container migration / UBI10
- FKITDEV-8252 — fleet-wide UBI8/UBI9 → UBI10 migration ahead of RHEL 9 EOL; Phase A.6.1 DONE (all 5 base images probe-build green; 2 new commits
f38c8e2+b984006; branch 17 ahead oforigin/main, not pushed); Phase A.6.2 (remaining 3 base/* likely undercommon/*), Phase B (vuer-release62 Dockerfiles), Phase C (vuer_dockerPR #203) still open; vuer_cv now in-scope (5.93 GB UBI10 base added) - FKITDEV-8252 — RUNTIME fixes (build-green ≠ runs): four ubi10-minimal startup gotchas masking each other (supervisor 4.2.5
pkg_resourceson Py3.12 → pin 4.3.0; supervisord logfile hidden by/var/logbind-mount → log to root; rabbitmq needs/bin/su→microdnf install util-linux; erlang.erlang.cookieeacces — supervisord drops HOME →environment=HOME="/var/lib/rabbitmq"); plus removed wrongUSER $DOCKER_USERfrom vuer_css/portal_css (must run supervisord as ROOT); all 3 rabbitmq images boothealthy; pushed solo-author across vuer_docker/vuer_build/vuer-release
Cron jobs / data retention
- fk-dev-nusz-deploy-and-8959-verification — FKITDEV-8959 TC-8959-02 verified PASS on fk-dev (2026-07-03): the NÚSZ image-deletion cron
RemoveAttachmentDataCronJob(thin wrapper overCustomRemoveOldDataCronService.removeAttachmentData()) →getOldImageAttachments(type LIKE 'image/%' AND isArchived=false AND createdAt<cutoff, batched, excludes thefileblob) →removeOldAttachmentskey-guard (const encryption = encryptionId ? getEncryption() : null; if (encryption?.key) encryptBuffer(empty,{key}) else { file=Buffer.from(''); encryptionId=null; skippedNoKey++ }; isArchived=true; save). Proven the key-offline path: BEFORE{isArchived:false,encryptionId:3,file_bytes:9}→{processed:1,archived:1,skippedNoKey:1,errored:0}→ AFTER{isArchived:true,encryptionId:null,file_bytes:0}(blanked + archived instead of the oldThe key options property is required…throw). Retention still OPEN: fk-devexpiryDays=7(dev.json) /28(docker.json) vs ASSNUSZ-117’s 7 — confirm with NÚSZ (one-line config) - FKITDEV-8959 — RCA of why NÚSZ image deletion never ran:
removeAttachmentData()was gated behind a hangingremoveVideoData()step in a strictly-sequential cron (ran only ~17/49 nights), and the oldgetWhereselected a 1-day band (createdAt ∈ [now-8d, now-7d)) with no catch-up so a skipped night was permanent. Fix = ownRemoveAttachmentDataCronJob(decoupled) + self-healingcreatedAt < cutoffimage-scoped query + the key-guard above; verified on fk-dev per the note above
Crypto policy / GPG SHA1
- FKITDEV-8252 — decision revised: original per-key
rpmkeys --import --allow-sha1-signaturesplan did not survive UBI10 reality (flag disappears aftermicrodnf -y updatestrips it fromrpm-libs;DEFAULT:SHA1sub-policy doesn’t exist — noSHA1.pmodships); now usingupdate-crypto-policies --set LEGACYin all 7 SHA1-key-importing build stages across portal_css, vuer_css, vuer_oss, janus (×2), vuer_cv; order matters: installcrypto-policies-scriptsfrom UBI10 BaseOS BEFORECOPY-ing the CentOS Stream 10 repo
CSP / log noise
- ASSICASH-71 — InstaCash CSS log noise:
WebServer.jssetupCSPReportViolation()writes every report unthrottled; amplifies anyhosts.portal/portal.urlconfig drift
Customization branches
- ASSICASH-71 —
customization/instacash(Express 4, HEADb0a4a37a, deployed) vsdevel(Express 5, PR 689 fixes); next core sync needs to carry route-array fix - FKITDEV-8787 —
customization/raiffeisenoverrides onSelfServiceRoomService.jsandSelfServiceV2Service.js;PRDEBUGinstrumentation gated byraiffeisen.debug.phantomRoomLog - FKITDEV-8533 —
customization/generali-atvilagitasis the base branch for the Generali videoOrientExt tablet fix (PR #7893) - FKITDEV-8788 —
customization/raiffeisenocr.engineselection (warp-firstVuerCVOCRRecognitionvs no-warpVuerCVMRZDetector) + recognition recipecustomization/cv/instruction.indexare the suspected override surface for the HU-eID-back MRZ crop bug - instacash-update-2026-05-27-status — Periodic devel→instacash sync: branch name
update/customization/instacash-2026-05-27across all three repos (esign_css/vuer_oss/vuer_css); date-only convention; per-repo conflict topology captured - esign-css-instacash-orphan-history — esign_css
customization/instacashis a single squashed orphan commit with no merge base; structurally distinct from conventional long-running customization branches - ci-github-branch-audit-chronically-red — every customization branch inherits a chronically RED “Github CI - Branch” audit gate (
improved-yarn-auditexit 4 on un-excluded critical advisories);customization/raiffeisenhas been red on it since ≥April 2026 — not a per-branch regression - customization-branch-ci-pipeline-inheritance — partner branches fork core source files in place (no override layer) and the repos have no customization-aware unit-test layer, so a partner-specific test failure can only be fixed by diverging a shared core test file — which then conflicts on every subsequent devel merge. Both amplifiers surface at once on a branch’s first devel-merge, when devel’s 6-job pipeline replaces the legacy single
lint-and-buildjob - cve-2025-7783-form-data-via-request — CVE-2025-7783 / GHSA-fjxv-7rqg-78g4, critical
form-data@2.3.3(unsafe random multipart boundary, patched>=2.5.4) via EOLrequest@2.88.2which hard-pinsform-data: ~2.3.2. Absent from devel (its Audit job is green) — present only on the customization line, becauserequestis live partner code: vuer_osscustomization/api/sms/SmsCofidis.js, vuer_csscustomization/server/web/api/{login,register,partner-register}.endpoint.js. Confirmed red oncustomization/cofidis(#3100/#8040),customization/kh(#3098),customization/raiffeisen(#8055) ⇒ blocks every partner branch adopting the new pipeline. Fix matching house style (repos already pincsurf/cookie,twig/minimatch,ts-jest/handlebars): add"request/form-data": "^2.5.6"toresolutionsin package.json +yarn install. Long-term correct fix = drop EOLrequest(4–5 call sites) = separate ticket - FKITDEV-8947 —
customization/unicredit: migrateUniCreditApiServiceoffrequest-promise-native→ fetch; the service does mTLS (cert/key/ca/passphrase fromportal.api), so the migration must useundici.fetch+Agent(vuer-oss-global-fetch-ignores-agent-mtls) — Node’s global fetch ignoresagent:. Working tree also has a stray}watApiService.js:267 - mjml-v5-esm-breaks-commonjs-email-templates — cofidis forks its own email/letter templates (
customization/email/*/*.letter.data.js); the FKITDEV-8727 MJML v4→v5 (ESM-only) upgrade merged via FKITDEV-9059 broke the ones that mix a top-levelimportwithrequire()(require is not definedatEmailService.init). Per-partner blast radius — every partner forks its own letter files, so the same upgrade can break each on its next devel-merge. Fix52a0843a1e(require→import in all 6, onlye-mail-invitehad actually crashed) is unpushed onchore/FKITDEV-9059-cofidis-update-2026-07-13-fixes
Customer data encryption
- sms-verification-code-dev-testing —
customer.datais an encrypted-at-rest TEXT column (serviceContainer.service.cryptos.data= DataCryptoService, keyed per-row bycustomer.key), but the Sequelize model’sdatagetaccessor auto-decrypts on read (customer.js:23-51,_getDecrypted:316-318,isEncrypted()=!!this.key) — so reading any portal-data field via the model (e.g.getVerificationCode()→videochatToken) returns plaintext, no manual crypto; by contrastsmslogs.messageBody/phoneNoare separately encrypted and NOT plaintext-readable - fk-dev-nusz-deploy-and-8959-verification — the
encryption.keyresolution chain (needed to exercise crypto-dependent code standalone):encryption.keyis a Sequelize getter (server/db/model/encryption.js) →serviceContainer.service.cryptos.data.getActualKey(key, customerId)(DataCryptoService) → for a null/absent key it callsserviceContainer.service.customerKeyStorage.getKey(customerId). A standalone harness must therefore initcryptos.{media,data,attachment}+CryptoService+customerKeyStorage; stubbingcustomerKeyStorage.getKey() => nullfaithfully models “customer key offline / inaccessible” — the real trigger for the FKITDEV-8959 image-deletion bug. Proven by TC-8959-02: a null-key image is blanked + archived +encryptionId=null(not thrown)
Dev / testing workflow
- dev-build-host — where to build/test: the
fk-devTailscale VM (command ssh ops@fk-dev.taild4189d.ts.net). The oldssh Facekombox is decommissioned (offline since ~2026-06-27) — every older note saying “build/test onssh Facekom” now means fk-dev. Still true: native builds on the remote host, never emulated on the Mac; usecommand ssh(thekakualias shadows plainsshnon-interactively) - instacash-external-api-esign-headless-test-2026-06-01 — how to exercise the InstaCash external API headlessly with
bin/instacash-cli.jsfrom thevuer_osscontainer: SSH viacommand sshto the dev host (now fk-dev, dev-build-host);start-server(detached) mocks the bank/auth+/statuson 8189;post-application [rt|nrt] [mkb_szemelyi_kolcson|mkb_mszh|mbh_mfl]returns{customerId, customerProfileUrl, inviteUrl};post-contract <id> [pdf]drives the ic-contract flow → EsignRPC → esign. Caveat: every cmd exceptstart-serverboots the full vuer_oss service in-process (needs healthy stack +instacash.external.apiKeyBearer +allowSelfSignedCerts); and the eSign signature itself can’t be automated (interactive video-ID + auth + sign at theinviteUrl) - dev-box-esign-container-startup-failures-2026-06-01 — debugging the
esign_css/esign_ossunhealthycontainers on the dev box (observed on the oldledererabox, now decommissioned — same triage applies onfk-dev, dev-build-host): how to triage (docker exec <c> supervisorctl status→ nginxFATALwhile app/redis/cronRUNNING= the PID-permission bug); the ~60s-unhealthy-after-any-restart healthcheck anti-flap (don’t chase it); post-dep-major-bump lesson — re-yarn installthe running container (/workspace/<svc>/node_modulesis host-bind-mounted, a baked image install goes stale →RedisStore is not a constructoretc.);command ssh Facekomto reach the box from Claude’s shell (kakushadows plainssh), login shell (bash -l) so docker is on PATH; chalk ^5 ESM-only brokeyarn trans(bin/test/trans-check.js:6) → dynamicimport('chalk') - dev-box-cv-photo-processing-failures — “error during photo processing” / “CV server is down” on the
ledereradev box has two compounding causes:vuer_cvcontainer stopped (docker start vuer_cv, ~2 min to healthy; nginx 502→404 on loopback curl) and hairpin NAT (vuer_oss host-net/etc/hostsmaps*-lederera→ own LAN IP192.168.1.93; remap →127.0.0.1); the hosts edit is wiped on everydocker restart vuer_oss(Docker-regenerated bind mount) so re-apply after any restart, via truncate+write notsed -i - sms-verification-code-dev-testing — get/force the SMS (and email) verification code when the customer phone is fake:
test.security.tempTokenSms(truthy → fixed code every send; conventional value123456in alltest/testconfigs/*.json;tempTokenEmail: "mailToken"for email) is read by thecustomer:verification:sendSmshook (customization/listeners/sms-verification.js); dev box (lederera/NODE_ENV=dev) does NOT ship it — add toconfig/local.json+ restart (node-config caches at startup) + resend (old random code won’t match); alt recovery = readcustomer.getVerificationCode()via model (auto-decrypts);matchTokens(ContactValidationService.js:16-20) = case-insensitive exact match - esign-css-customization-branches — eSign standard dev/test method: test through VÜER CSS with
requestFakeCustomer = trueand?esign=1&token=… - instacash-esign-dev-box-deploy — testing an InstaCash eSign release on the dev box (now
fk-dev— thessh Facekombox it was written against is decommissioned, see dev-build-host; code bind-mounted from/workspace): the box defaults to Raiffeisen so you must align the whole partner chain to InstaCash (esign_oss/css → taginstacash-1.3.0.11, vuer_oss/css → taginstacash-1.9.11.50since the eSign ticket pins no vuer version, pdfservice stays main/2.0.12 partner-agnostic). Per repo:git stashWIP →git fetch --tags(clones predate the tag) →git checkout <tag>→ rebuild in-containerdocker exec <c> sh -c 'cd /workspace/<repo> && yarn install && yarn build'→supervisorctl restart all. Verify supervisord RUNNING +RabbitMQ connection established+Web server is listening+ esign_css :10183 HTTP 200. Gotchas: a “dirty” vuer_css = untracked.claude/dir; old log ERRORs may be historical from the prior run (check timestamps) - fk-dev-nusz-deploy-and-8959-verification — deploy a branch to the
fk-devGCP dev-mirror VM (tailnettaild4189d.ts.net; NOT the offline on-premssh Facekombox) by bind-mount swap, no image rebuild:command ssh ops@fk-dev.taild4189d.ts.net(Tailscale SSH, no keypair;kakushadowsssh→command ssh/command scp); the box has NO GitHub key sossh-add ~/.ssh/id_ed25519+command ssh -Ato forward yours; then on/workspace/vuer_oss:git fetch origin <branch>+checkout→docker exec vuer_oss sh -c 'cd /workspace/vuer_oss && yarn install && yarn build'→docker exec vuer_oss supervisorctl restart all; verify supervisorctl RUNNING +Web server is listening on 10081+ operator UI (https://oss-fk-dev.taild4189d.ts.net) HTTP 302.postgresqlpeer-auth blockspsql -U postgres(use app Sequelize);nginx_proxycrash-loops but sidecars bypass it; restore the box’s originalbd8923d69f(InstaCash) when NÚSZ testing done. Also documents a reusable standalone cron test-harness pattern (Node script inbin/→process-settingsbootstrap + loggerProxy+ service/crypto stubs +sequelizeauthenticate + raw-SQL seed → call the REAL service methods → SELECT before/after; deliver viacommand scp+docker cp+docker exec+rm) - mailtrap-sandbox-inbox-dev-email — FaceKom dev email is not broken:
config/dev.jsonemail.transport.SMTPbakes a Mailtrap Sandbox inbox (hostsmtp.mailtrap.io, port 2525, user643414e4c00185), so registration/verification mail is delivered into the original-dev/shared inbox you can’t see (symptom reads as “emails don’t send to Mailtrap”). Route to your inbox by overridinghost→sandbox.smtp.mailtrap.io+auth.{user,pass}in the bind-mountedvuer_oss-local.jsongetconfiglocallayer (config/docker.jsonis never loaded underNODE_ENV=dev; Sandbox creds don’t auth the legacysmtp.mailtrap.io). Distinguish Sandbox (sandbox.smtp.mailtrap.io, per-inbox user/pass ~14 hex, catches mail) from Email Sending / live (live.smtp.mailtrap.io,api+ 32-char token, delivers for real — wrong for testing). Verify withnodemailer.verify()first (require nodemailer by absolute path/workspace/vuer_oss/node_modules/nodemailer). Sibling to sms-verification-code-dev-testing (invisible-delivery-channel dev testing)
Devel update sync workflow
- instacash-update-2026-05-27-status — Branch naming convention:
update/customization/instacash-<date>(date-only, no ticket prefix), applied identically across all three repos (esign_css, vuer_oss, vuer_css); per-repo conflict surfaces vary significantly (esign_css blocked structurally, vuer_oss self-service-v2 listener high-risk, vuer_css modal a11y trio + customizations.js routes high-risk); using a separate worktree to keep parallel feature WIP branches untouched is the pattern (e.g.~/coding/facekom/vuer_css-instacash-updateto protectbugfix/FKITDEV-8787) - esign-css-instacash-orphan-history — When the target branch is structurally orphan, the standard
git merge develhalts;git rev-list --count A..Bis meaningless without a merge base — three viable workflow options to choose between before resuming - FKITDEV-8817 — Parallel-strategy sequencing: don’t block the sync on an unmerged adjacent PR; let the second
devel→update-branch merge pull it in once the PR lands on devel - nusz-devel-update-2026-06-16-lint-merge-fix — NÚSZ
update/customization/nusz-2026-06-16merge oforigin/develfailed validation at lint, left mid-merge (uncommitted). Reusable merge gotcha: devel renamedFFmpegService.js→.ts; nusz tip had added an extensionlessrequire('./server/service/FFmpegService')tocron.js— conflict-free merge kept both, so it no longer resolves undern/no-missing-require.cron.js:46was the lone straggler (all other callers already on explicit.ts). Lesson: after a cross-side.js→.tsrename merge, grep for extensionlessrequire()s of the renamed modules - customization-branch-ci-pipeline-inheritance — budget for the CI pipeline expansion on a partner’s first devel-merge: 1 job (
lint-and-build) → 6 (lint/test/audit/depcheck/sonar/build), i.e. 4 jobs run on the branch for the first time ever and most red is pre-existing partner breakage newly enforced, not merge-introduced. Triage every failure by origin (git blame/git logthe offending line) before choosing a fix side (partner file vs shared core test). Characterised on FKITDEV-9059 (Cofidis, 2026-07-20) - FKITDEV-9059 — Cofidis devel update (vuer_css PR #3100 @
4dd8a927a, 105 files; vuer_oss PR #8040 @ad8a318a22, 586 files), bothmergeable_state: blocked; full 8-row failure inventory with root cause / origin / fix-side per failure - mjml-v5-esm-breaks-commonjs-email-templates — an ESM-only major upgrade of a shared loader, merged via
devel → customization/*, silently breaks CommonJS customization files. The FKITDEV-9059 cofidis merge pulled in FKITDEV-8727 MJML v4→v5 (ESM-only,c9602a519e) →EmailService.jsawait import(...)s letter templates; Node 22 then parses anycustomization/email/*/*.letter.data.jsthat mixes a top-levelimportwithrequire()as ESM →ReferenceError: require is not definedatEmailService.init. Scope trap: NOT “41 of 49 files containrequire(” — only the 6 mixed files break, and 5 had acreateRequireshim so onlye-mail-invitecrashed at boot. Reusable rule: after any ESM-loader migration, grepcustomization/for mixed import+require. The ESM cousin of the nusz-devel-update-2026-06-16-lint-merge-fix.js→.tsrename gotcha
Device detection
- FKITDEV-8533 — server-side UA parsing cannot detect a modern iPad: iPadOS 13+ Safari sends a
Macintoshdesktop UA,ua-parser-jsv1 returnsdevice.type === undefined;customer.isTablet()(device.type === 'tablet') is a strict logical subset ofcustomer.isMobile()('mobile'OR'tablet') so it adds no detection power;customer.userAgentis the only client signal the server has (noSec-CH-UAhints); reliable detection = client-sidenavigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent). Resolution avoided the detection problem entirely (2026-06-23): rather than detect the iPad, gate on the easy-and-reliable negativeCustomer.isNativeApp()(userAgent.startsWith('mobile/'), single prefix for iOS+Android native SDK) — browsers (incl. spoofing iPads) all fall on the enable side.
Face comparison
- face-comparison-data-verdict-threshold-model — canonical model note (FKITDEV-8827 design):
faceComparisonsrows key by EITHERroomId(videochat/operator) ORselfServiceRoomId(self-service-v2), no mutual-exclusivity constraint (models.js:298-309,model/faceComparison.js);euclideanDistance= cosine distance 0–2 (misnamed). PION = videochat NOT self-service — protos declarevideochat, comparisons fromvideochat:closehook (faceRecognitionHooks.js:26-44) keyed byroomId, gated by configfaceRecognition.comparisonPairs(FaceRecognitionService.js:7,20) → self-service-only query returns zero PION rows. Verdict DERIVED bygetFaceComparisonResult(SelfServiceCheckerService.js:132-154): SUCCESS≤perfect / PROBABLE≤probable (thematchtier collapses, defaultmatch:null) / FAILURE>probable, operators<=, defaults{perfect:0.5,match:null,probable:0.6}. Threshold sourcing differs by link type: self-service per-roomselfService:v2:config:state(oldest[0], ASC) REPLACES → globalSettingkeyfaceComparison(persisted bySettingsService.init()); videochat/operator rows have NO per-room path and are NOT verdict-classified at runtime (room.endpoint.js:144raw distance only). NocreatedAtindex → date-range exports full-scan; report-bin pattern + latent bug inraiffeisen-selfservice-failed-reports.js:106(prepareReportDataabstract, masked byactive:falsecron); Postgres but MySQL-portable (LOWER() LIKEnotILIKE) - face-comparison-different-face-db-query — face-comparison results are persisted:
faceComparisonstable (server/db/model/faceComparison.js:18-37) storesstatus ∈ {created,failed,success}+euclideanDistance(FLOAT nullable, actually cosine distance 0–2 despite the name);euclideanDistancewritten unconditionally byFaceRecognitionService.createFaceComparisonModel()regardless of threshold;different_faceis not stored — it’s theCHECK_FAILUREread-time verdict fromSelfServiceCheckerService.getFaceComparisonResult()(:132-153) when distance exceeds all thresholds; thresholds resolve per-room (selfService:v2:config:stateactivity log) → globalSettingkeyfaceComparison→ code defaultprobable:0.6; 4 call sites — liveness-V2 (SelfServiceV2Service.js:1390) gated bytask.options.recognitionOptions.compareFaceWith(base V2 proto doesn’t set it), portrait/ID-doc (server/flow/FlowService.js:2943), videochat-close hook, V1;faceComparisonshas no step column — portrait vs liveness only via joinedFaceRecognition.imageCategory; queryable with one read-only SQL, no release
Express 5 migration
- ASSICASH-71 — PR #666 (closed unmerged) → PR #670 (merged) for
_router → routerand/password-recovery/:token?/:lang?array rewrite; PR #689 follow-up - instacash-update-2026-05-27-status — No Express 5 risk in vuer_css side of this update wave (contrary to a prior assumption rooted in ASSICASH-71’s vuer_css
customization/instacashExpress-4-on-devel-Express-5 case); vuer_css server-side merged clean (routes.js,WebServer.js,package.json,yarn.lock)
eSign / esign_css
- instacash-external-api-esign-headless-test-2026-06-01 — the InstaCash
post-contract <customerId> [pdf]external-API call (viabin/instacash-cli.js) is how the eSign contract leg is exercised headlessly:POST /external/contract→ creates the “IC - Szerződés ajánlat feltöltése” (ic-contract) flow → EsignRPCClient → esign service. But the signature itself is interactive (video-ID + mock/auth+ SMS123456+ sign in the eSign UI) — the CLI proves the EsignRPC plumbing only, it cannot complete a signature. Requires the esign containers to behealthyfirst (see the nginx-PID fix note) - dev-box-esign-container-startup-failures-2026-06-01 —
esign_css+esign_ossdev-box containers (esign_{css,oss}:2024.4.1-20240614, rebuilt ~2025-12-08, nginx 1.28, run as non-roottechteameruid 1000) come upunhealthybecause nginx can’t writepid /run/nginx.pid;(root-owned/run) — image regression, fix belongs in the esign images/Dockerfiles (/etc/nginxnot bind-mounted);RedisStore is not a constructorinserver/web/web-server.js:24is a red herring (code is correct connect-redis v9; only an old/stalenode_modulesbites); chalk ^5 ESM brokebin/test/trans-check.jsyarn trans - esign-css-customization-branches — Customization branch fleet (only
customization/instacashactive, all others archived); standard dev/test method (test through VÜER CSS withrequestFakeCustomer = trueand?esign=1&token=…) - esign-css-instacash-orphan-history —
customization/instacashis a single squashed orphan commit (b7cee2f, 2025-11-20, release 1.3.0.10); zero shared history withdevel; 95-path delta; previous releases likely built via squash-rebuild + force-push pattern (confirmation needed) - FKITDEV-8817 — esign_css jQuery 2.2.4 vulnerability (CVE-2020-11023 / CVE-2019-11358); fix on
bugfix/FKITDEV-8817-jquery-updatepushed (b021019); dead-code path (auth.layout.twig) — repoint to existing/libs/jquery/jquery-3.7.1.min.js; PR not yet opened - esign — Electronic Signature System overview
- instacash-esign-1.3.0.11 — release composition for InstaCash eSign
1.3.0.11(esign_oss + esign_css only; taginstacash-1.3.0.11, 2026-06-08; Harborinstacash-esign-{oss,css}:1.3.0.11-20260608); changelog = devel update + FKITDEV-8817 vuln fixes (jQuery CVE-2020-11023 / CVE-2019-11358 on esign_css PR #250 + HSTS/nginx/WAF hardening); ASSICASH-92 release, ASSICASH-93 TESZT / ASSICASH-96 PROD (approved 2026-06-26 from1.3.0.8); no DB migration / no breaking change, rollback = redeploy1.3.0.8 - instacash-esign-dev-box-deploy — dev-box recipe to test an InstaCash eSign release (run it on
fk-dev; the oldssh Facekombox is decommissioned — dev-build-host): the box defaults to Raiffeisen so align the WHOLE chain to InstaCash (esign_oss/css →instacash-1.3.0.11, vuer_oss/css →instacash-1.9.11.50, pdfservice stays main/2.0.12); per repogit stash→fetch --tags→ checkout tag → in-containeryarn install && yarn build→supervisorctl restart all; verify supervisord RUNNING + “RabbitMQ connection established” + “Web server is listening” + esign_css :10183 HTTP 200
GCP dev-box mirror / Tailscale
- dev-build-host — CANONICAL host reference (2026-07-01): the on-prem box
ssh Facekom(=HostName localhost+ProxyJump FKJumpBox→root@lederera-447-fk-hardver) is DECOMMISSIONED — Tailscale shows it offline since ~2026-06-27 — and must never be used again. All native builds / tests / deploys now run on thefk-devTailscale VM (100.91.108.61,command ssh ops@fk-dev.taild4189d.ts.net, Tailscale SSH, no keypair). Unchanged: build native on the remote host, never emulated on the Mac (qemu SIGSEGV exit 139 / overlay-FS I/O exit 125 / repo-metalink 503s) — only the host moved. Agent gotcha: the user’s shell aliasesssh/scpto a_kaku_wrapped_sshfunction that is NOT loaded in a non-interactive shell (_kaku_wrapped_ssh: command not found) → usecommand ssh/command scp. Other tailnet peers are per-service sidecars on fk-dev, not build hosts:oss-fk-dev(100.91.55.42),css-fk-dev,portal-fk-dev,esign-oss-/esign-css-/esign-api-fk-dev,css-sdk-demo-fk-dev - fk-dev-nusz-deploy-and-8959-verification — fk-dev is now OPERATIONAL (2026-07-03): the 8b per-service Tailscale-sidecar overlay is pushed + wired + running (closes the “push gated on user go” item) — sidecars
oss-/css-/esign-*/portal-fk-devup, vuer_oss operator UI at https://oss-fk-dev.taild4189d.ts.net (HTTP 302; Express:10081inside), source bind-mounted/workspace/<repo>+ supervisord per container. First real use = deploying the two NÚSZ fixes (FKITDEV-8747 + FKITDEV-8959 oncustomization/nusztipd426cc6ae1) and verifying FKITDEV-8959 TC-8959-02. Operational gotchas:command ssh ops@fk-dev.taild4189d.ts.net(Tailscale SSH;kakushadowsssh); box has no GitHub key (agent-forward withcommand ssh -A);postgresqlpeer-auth (nopsql -U postgres);nginx_proxycrash-loops (bypassed). Still open: janus/WebRTC media over the tailnet, CV (non-GPU VM). Full deploy runbook + verification in the note; provisioning/overlay design in tailscale-gcp-dev-box-migration - tailscale-gcp-dev-box-migration — IN PROGRESS (decisions landed + VM provisioned 2026-06-30 via babylon
#facekom_dev): mirror the FaceKom dev box on a GCP VM reachable over tailnettaild4189d.ts.net, replacing DuckDNS / public IP. Decision 1 — hostnames = Tailscale MagicDNS (<name>.taild4189d.ts.net), NOTfacekomdev.netsubdomains → public-DNS Phase 2a RETIRED. Decision 2 — routing = 8b multi-tailscaled sidecar per service (NOT port-based 8a): each of 9 services gets its own userspacetailscaledsidecar (envTS_AUTHKEY+TS_HOSTNAME, ~30 MB idle), own MagicDNS name, owntailscale cert; no app URL rework IFF sidecars named<prefix>-fk-devto preserve<prefix>-<DEV_DOMAIN>withDEV_DOMAIN=fk-dev.taild4189d.ts.net(flagged to verify; pattern proven on pmv2-zurich). This reverses the note’s original host-level/sidecar-rejected recommendation. VMfk-devprovisioned bydeploy(levandor-infra terraformmodule "vm"→for_each=var.vms; pmv2 14 prod containers untouched): e2-standard-4 (4 vCPU/16 GB), 100 GB pd-balanced, europe-west6-a, VPCfk-dev-net/10.2.0.0/24, SAfk-dev-sa, tailnet IP100.91.108.61, MagicDNSfk-dev.taild4189d.ts.net, ACLtag:cloud; public IP 34.158.19.122 egress-only, firewall denies all inbound except DERP, no public SSH; Docker 29.6.1 + OTel collector;ssh ops@fk-dev. Open (Andras/user): CV/GPU scope (VM non-GPU), toggle “HTTPS Certificates” ON in Tailscale admin (required beforetailscale cert), whetherdeploymakes a FaceKom Artifact Registry namespace. 8b overlay IMPLEMENTED 2026-06-30 (BUILT +compose config-validated, unpushed, no commit on vuer_docker branchtailscale):tailscale.ymlships 8 userspacetailscale/tailscale:stablesidecars (network_mode host,TS_USERSPACE=true,--advertise-tags=tag:cloud, per-svcTS_HOSTNAME+TS_SERVE_CONFIG, DRY YAML anchors, namedts-state-*vols) + 5 app-svc stubs;tailscale/serve/*.json(8: oss/css/css-sdk-demo/esign-oss/esign-api/esign-css/portal/library, each HTTPS${TS_CERT_DOMAIN}:443→http://127.0.0.1:<port>, ports 20080/30080/30081/20180/20181/30180/30380/50080);tailscale/config/*-local.json(5: vuer_oss/vuer_css/esign_oss/esign_css/portal_css);tailscale/README.md;.gitignore+=tailscale/tailscale.env. KEY CORRECTION — “no app URL rework IFF naming preserved” was FALSE: apps computeseparator = DEV_DOMAIN.endsWith('facekomdev.net') ? '-' : '.', so a tailnetDEV_DOMAINflips to.→ invalid dotted names likeoss.fk-dev.taild4189d.ts.net(NOT MagicDNS-resolvable, NOT the sidecar name). Fix = zero app-repo edits, entirely in vuer_docker: host derivation guardedif (!config.X)+getconfigdeep-mergesconfig/local.jsonlast (both verified empirically) → bind-mount a per-appconfig/local.jsonat/workspace/<app>/config/local.jsonsettinghosts.*explicitly to<prefix>-fk-dev.taild4189d.ts.net(vuer_osshosts.cv=null, +esignportal.url). Validateddocker compose -f dev.yml -f vuer-oss.yml -f vuer-css.yml -f esign-oss.yml -f esign-css.yml -f portal-css.yml -f facekom-library.yml -f tailscale.yml config -q→ EXIT 0. Networking: each sidecar host-net + userspacetailscaled,tailscale serve→127.0.0.1:<app-port>, per-svc MagicDNS name + cert;nginx_proxyno longer the access path (harmless). Open (Andras/user): CV/GPU scope (VM non-GPU;hosts.cv=null), toggle “HTTPS Certificates” ON in Tailscale admin (required before cert issuance), whetherdeploymakes a FaceKom Artifact Registry namespace (none added — uses existing). Next (on user go): push →deploywires onto fk-dev. Caveat: vuer_osshosts.api=api-fk-devhas no sidecar butapi-is only used by customization/external/createCustomerTokenhostname-gating, not base dev flow. (Original source-verified analysis preserved in the note:dev.ymlservicesnetwork_mode: "host", nginx_proxy routes by subdomain PREFIX with domain-wildcardserver_name, single self-signed cert, apps build URLs fromDEV_DOMAIN; only literalduckdns=README.md:17.)
Giro / girinfo
- FKITDEV-8581 —
GiroProcess.handleTask()incustomization/server/backgroundProcess/giro.process.js(Raiffeisen,customization/raiffeisenbranch only; renamed fromgiroService.process.jsduring the “Raiffeisen PIon project clean-up”) now splits the catch-block logging into “No response from girinfo service” (RequestError/ETIMEDOUT|ESOCKETTIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN) vs “Bad response from girinfo service” (non-200/StatusCodeError/save failure, incl.statusCode); both addelapsedMs/requestTimeout/code. Log-only — retry (this.retry) unchanged. A heavier “mark bg-process/portal state after final no-response retry” option was DEFERRED (ties to the ambiguous-portal-state RCA — box “request in progress” vs dashboard “data arrived” vs logical-match “not available”). Original RCA fixf830fd8e5ashipped 2025-11-28; YouTrack still Pending
Git / orphan branches
- esign-css-instacash-orphan-history — An orphan branch (
customization/instacashin esign_css) breaks the conventional toolset:git mergehalts onrefusing to merge unrelated histories,git rev-list --count A..Breturns numbers without meaning (no merge base), cherry-pick is fragile (different ancestor than the patch was authored against); the three operational responses are--allow-unrelated-histories(one-shot, recoverable), rebase-replay (matches historical pattern), or cherry-pick-delta-forward (cleanest narrative)
Git / commit + branch rulesets
- techteamer-commit-message-ruleset — TechTeamer vuer repos enforce a repository ruleset on commit metadata: a push is rejected unless every commit subject matches
^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(!)?(\([^)]+\))?: [^\n]{1,100}. Two traps: a defaultgit revertmessage (Revert "…") is rejected — use therevert:type (git revert -n <sha>+git commit -m 'revert: …'); and the subject after thetype(scope):prefix is capped at 100 characters. A single bad subject anywhere in the pushed range rejects the whole push and the fix is a history rewrite — check the full range, not justHEAD. Same rulesets also enforce ticket-prefixed branch names (chore/FKITDEV-NNNN-…). Hit on FKITDEV-8387; branch-naming half first seen on nusz-1.9.11.47
HTTP client / fetch / mTLS
- vuer-oss-global-fetch-ignores-agent-mtls — verified (Node v22.22.3 / bundled undici 6.24.1): every
fetch()in vuer_oss is Node’s global fetch (noundici/node-fetchdep), which IGNORES the node-fetch-styleagent:(honors onlydispatcher) → thegetHttpsAgent()idiom is a SILENT NO-OP (harmless only becausecv.rejectUnauthorizeddefaultstrue);agent-based client-cert mTLS /rejectUnauthorized:falseis dropped. FIX =undici’s ownfetch+Agent(dispatcher: new Agent({ connect: { cert, key, ca, passphrase, rejectUnauthorized } })). CROSS-VERSION TRAP: standalone-undici 8.5.0Agentinto global fetch (undici 6.x) →UND_ERR_INVALID_ARG: invalid onRequestStart method; Facekom runs Node 22 and 24 (different bundled undici majors) so don’t pin standalone-undici to the bundled version. Surfaced scoping FKITDEV-8947 (UniCredit mTLS migration) - FKITDEV-8947 — migrate UniCredit
customization/server/service/UniCredit/ApiService.js(customization/unicredit,UniCreditApiService) offrequest-promise-native→ fetch; uses mTLS (cert/key/ca/passphrase fromportal.api) so the naiveagent:migration silently breaks TLS — must useundici.fetch+Agentper the gotcha note
InstaCash
- instacash-external-api-esign-headless-test-2026-06-01 — headless test path for the InstaCash external API + eSign via branch-only
bin/instacash-cli.js(in thevuer_osscontainer):start-servermocks the bank/auth+/status(8189); every other cmd (post-application/get-invite/get-customer/post-contract/get-/revoke-contract) boots the full vuer_oss in-process and HTTPS-calls${hosts.oss}/external/...(NOT a thin HTTP client).post-contract→ ic-contract flow → EsignRPC → esign. The actual eSign signature is interactive and cannot be driven headless (manual video-ID + auth + sign at theinviteUrl). 2026-06-01 run: customerId 28,post-contract→ HTTP 400{"error":"Contract flow is in progress"}on a not-yet-identified application — open question vsdeveloper-guide-hu.md(contract upload after identification) - dev-box-esign-container-startup-failures-2026-06-01 — surfaced while testing the InstaCash 2026-05-27 devel-update on the dev box:
esign_css/esign_ossunhealthydue to the nginx non-root PID image regression (NOT the update code); also the post-dep-bump re-yarn installlesson (RedisStore is not a constructorifnode_modulesis stale) and a chalk ^5 ESM fix foryarn trans - dev-box-cv-photo-processing-failures — discovered testing the nrt self-service identification flow on the dev box: photo step fails (“error during photo processing”) when
vuer_cvis stopped or the hairpin-NAT/etc/hostsfix is missing; recipe-oriented runbook (check vuer_cv running + hairpin remap, re-apply after restart) - sms-verification-code-dev-testing — discovered testing the NRT self-service identification flow on the dev box: how to get past SMS 2FA when the customer phone is fake (
test.security.tempTokenSmsfixed code + restart + resend, or readcustomer.getVerificationCode()via the model) - ASSICASH-71 — PROD
vuer_css local.json portal.urlUAT misconfig (FKITSYS-9486 fix 2026-01-06); pending log-volume confirmation;portal_csshosts.portalparallel risk - instacash-update-2026-05-27-status — 2026-05-27 devel→instacash sync wave across esign_css/vuer_oss/vuer_css; high-risk surface: vuer_oss
customization/listeners/self-service-v2.js(FKITDEV-7518 id-card +newIdFormatAcceptance), vuer_csscustomization/customizations.jsroute reconciliation + modal a11y trio; 50 oss / 57 css commits in, esign_css blocked on orphan history; vuer_css server-side clean (no Express 5 risk here) - esign-css-instacash-orphan-history — InstaCash side of esign_css is structurally distinct: single squashed orphan, intentional MBH/MKB asset retention (55 devel-deleted-instacash-keeps), three workflow options for resyncing
- FKITDEV-8817 — esign_css jQuery vuln fix on
bugfix/FKITDEV-8817-jquery-update(commitb021019, pushed, PR not yet opened); flows into InstaCash via second-merge of 2026-05-27 sync once landed on devel - youtrack-tesztjegyzokonyv-attachment-recipe — InstaCash (ICASH) historically had NO release/eSign tesztjegyzőkönyv in YouTrack (the first was generated 2026-06-26 — see below; still not attached). In YouTrack today:
ASSICASH-65(FaceKom 1.9.11.50) /ASSICASH-92(eSign 1.3.0.11) carry only build.logs; install ticketsASSICASH-66/62/67/93(TESZT) /-96(PROD) only screenshots. The only attached instacash “teszt jegyzőkönyv” PDFs are OLD compliance/DR docs:BUGICASH-460(BCP teszt 2023-06) +ISSFK-338(SaaS DR teszt 2021). - instacash-esign-1.3.0.11 — InstaCash eSign 1.3.0.11 release composition (esign_oss + esign_css; tag
instacash-1.3.0.11; ASSICASH-92 release / ASSICASH-93 TESZT / ASSICASH-96 PROD approved 2026-06-26 from1.3.0.8; FKITDEV-8817 jQuery CVEs + hardening; no migration, rollback = redeploy1.3.0.8). First InstaCash release to get a TJK — generated via fk-tjk (instacashadded topartners.json: display “InstaCash”, ASSICASH; 5 test cases →~/Downloads/tesztjegyzokonyv_instacash_1.3.0.11.docx), not yet attached. - instacash-esign-dev-box-deploy — recipe to test InstaCash eSign on the dev box (
fk-dev; thessh Facekombox is decommissioned — dev-build-host): align the whole chain to InstaCash (esign →instacash-1.3.0.11, vuer →instacash-1.9.11.50, pdfservice stays main/2.0.12),git stash/fetch --tags/checkout per repo, rebuild in-container,supervisorctl restart all; verify supervisord RUNNING + the two startup log lines + esign_css :10183 200; gotchas: untracked.claude/looks “dirty”, old log ERRORs may be historical (check timestamps)
iOS Safari / audio recovery
- FKITDEV-8887 — root cause: iOS Safari suspends WebRTC audio on
AVAudioSessioninterruption (lock→unlock / background); the remote<video>is paused and never resumed because there is novisibilitychange/pageshow/focushandler; Socket.IOconnectionStateRecovery(30 s) masks brief backgrounds (noreconnect→reload), so only short SMS-code reads produce silence that persists. Fix (UNCOMMITTED, branchfix/FKITDEV-8887-ios-audio-resume):InterruptionRecoverycontroller wired viavisibilitychange/pageshow/focuscallsVideoFeed.ensurePlaying()(remote<video>.play()when paused) +VideoChatService.recoverAudioIfNeeded()(LocalMediaService.startLocalMedia({audio:true,video:false})+replaceTrack). Critical gotcha:SenderPeer.pcis aPeer(WildEmitter) wrapper, NOT anRTCPeerConnection— the real connection isPeer.pc; callingthis.pc.getSenders()onSenderPeeris always undefined → mic recovery must proxy throughPeer.replaceAudioTrack(). Gate:isSafari(covers iPhone+iPad), notisIOS(iPadOS 13+ sends desktop UA →isIOS=false). 119 suites / 0 failures / lint clean. - FKITDEV-8887 — QA acceptance protocol (device repro): the only definitive acceptance gate (unit tests can’t confirm an iOS-runtime bug). Run baseline on
origin/develfirst (must stay silent) → then validate fix onfix/FKITDEV-8887-ios-audio-resume: iPhone Safari join → 2FA → lock ~10s to read SMS → unlock, expect audio both directions in ~1s. Evidence via allowlistedwebrtclog:interruption:resume→senderPeer:audioRecovered {swapped:true}({swapped:false}/:error= capture failure). Matrix: iPhone built-in+AirPods, iPad (Macintosh UA, validates non-isIOSgating), >30s background (crossesconnectionStateRecovery), non-default mic survival (validatesLocalMediaService.startLocalMediapath), Android/desktop regression, both directions. Version-risk settlement: pulluserAgentfor rooms 10071/10091 (ASSGRALI-63) + 2281 (ASSCIB-161/FKITDEV-8895) — iOS ≥16 weakens only the mic-interruption premise; playback + socket-mask hold regardless. - FKITDEV-8887 — polish pass 2026-06-15: mic recovery rerouted from raw
getUserMedia→LocalMediaService.startLocalMedia({ audio: true, video: false })(respects saved device);localMediawired invideochat.script.js; WebRTC test globals extracted totest/tests/unit/_helpers/webrtc-test-globals.js(must run at module top level, before describe + before require of SUT — config readsdocument.body.getAttributeat require-time);videochat.services.test.jsupdated to mocksvc.localMedia.startLocalMedia+ new undefined-guard case. - FKITDEV-8887 — SonarCloud cleanup 2026-06-18 (PR #3066): Quality Gate PASSED but 18 “New issues” (all code smells; 0 bugs/vulns; 89.2% new-code cov). Fixed the 13 in the PR’s new code (11×
prefer-optional-chaining, 1×prefer-globalThiswindow→globalThis, 1×cognitive-complexityrecoverAudioIfNeeded19→≤15 via_safeLog/_isAudioTrackDead/_applyRecoveredAudioTrackhelpers — behavior-preserving, 119 suites/1045 tests + adversarial APPROVE). Left the 5 PRE-EXISTINGpromptUpload/validationResultsmells (videochat.script.js~L424–448, untouched pergh pr diff 3066) for a separate chore. See## CI / build gatesfor the gh-check-run-annotations technique used to read the issues tokenless.
Networking / dev-box (hairpin NAT)
- tailscale-gcp-dev-box-migration — DuckDNS → Tailscale GCP dev-box mirror over tailnet
taild4189d.ts.net. IN PROGRESS (2026-06-30): MagicDNS hostnames + 8b per-service multi-tailscaled sidecar routing; VMfk-devprovisioned (tailnet100.91.108.61). 8b overlay now BUILT +compose config-validated on vuer_docker branchtailscale(unpushed); key correction — “no app URL change” was FALSE (apps switch-→.separator off tailnetDEV_DOMAIN), fixed entirely in vuer_docker via bind-mounted per-appconfig/local.json. See the## GCP dev-box mirror / Tailscaletopic for full detail - dev-build-host — SSH to the dev box (from Claude’s shell):
command ssh ops@fk-dev.taild4189d.ts.net(Tailscale SSH, no keypair, no jump box), with a login shell (command ssh … bash -l -s <<'EOF' … EOF) so docker is on PATH.command ssh/command scpare mandatory — the user’skakualias (_kaku_wrapped_ssh) shadows plainsshand is absent in non-interactive shells. The old two-hop topology (Facekom=lederera@localhostviaProxyJump FKJumpBox→root@lederera-447-fk-hardver, jump box = bare Alpine, no docker) is DEAD — recorded for history in 5. SSH access to the dev box from Claude Code’s shell - dev-box-cv-photo-processing-failures — host-network containers (e.g.
vuer_oss) reset at the TLS handshake when connecting to the box’s own public/LAN IP (192.168.1.93) — hairpin NAT; the container’s/etc/hostsmaps all*-lederera.facekomdev.netto that LAN IP by default, so inter-service HTTPS (CV pingcv-lederera,bin/instacash-cli→oss-lederera/external/...) fails withread ECONNRESET/ “Connection reset by peer”; fix = remap those names →127.0.0.1(loopback hits the same nginx, no hairpin);/etc/hostsis a Docker-regenerated single-file bind mount → edit wiped on every container start, re-apply after any restart via truncate+write (> /etc/hosts/base64 -d > /etc/hosts), NOTsed -i(failsDevice or resource busy) - fk-dev-nusz-deploy-and-8959-verification — SSH topology of the new
fk-devGCP dev-mirror VM (distinct from the on-prem box’sProxyJumptopology above): reach it atcommand ssh ops@fk-dev.taild4189d.ts.net— userops, Tailscale SSH (no keypair), tailnettaild4189d.ts.net/100.91.108.61; the samekakuwrapper shadows plainssh/scpin Claude’s shell → usecommand ssh/command scp. The box has no GitHub deploy key → forward the Mac’sid_ed25519(ssh-add+command ssh -A) forgit fetch. Per-service Tailscale sidecars (oss-/css-/esign-*/portal-fk-dev) are the access path;nginx_proxycrash-loops but is bypassed
NPM registry / package publishing
- FKITDEV-9022 — publish 7 standalone
@techteamer/*library repos (xlsx, timestamp_service, mq, video-processor, archiver-zip-encrypted, janus-api, acl — all onmaster, NOT the vuer monorepo) to the private registryhttps://npm.facekom.net/, so the GitHub source can later be made private. Mechanic (only org precedent =TechTeamer/amqplib-asyncapi-template, which declarespublishConfig:{registry:"https://npm.facekom.net",access:"restricted"}): per-repo add thatpublishConfigtopackage.json+ one.github/workflows/publish.yaml(push-to-master;secrets.FACEKOM_NPM_TOKEN→~/.npmrc;npm view <name>@<version> --registry …guard = idempotent, publishes only new versions).publishConfig.registryonly moves the publish target — the default registry stays npmjs, so installs/consumers are unaffected; no package renames. Decision (user, 2026-07-08): keep@techteamer/*, do NOT rename to@facekom/*→timestamp_serviceis the sole special-case rename:@techteamer/timestamp-service+ drop"private": true(both block publish). Correction: the “janus-sdk publish.yaml reference impl” was WRONG —TechTeamer/janus-sdk= 404; only the amqplib template references the registry.mqspecial case (release.config.mjs/semantic-release honors publishConfig.registry, but no release workflow wired yet). Phase 2 = take repos private / stop public publish — must come AFTER consumers (vuer_oss/vuer_css/portal_css, Yarn-Classic v1 + offline mirror) are repointed, or their CI/Docker installs break. Blocked on VPN: registry docs, CI token, org secretFACEKOM_NPM_TOKEN, real publish test.aclreference done + validated locally (branchchore/FKITDEV-9022-npm-facekom-publishofforigin/master), uncommitted; other 6 pending go; solo-author, no auto-PR
OCR / MRZ
- FKITDEV-8788 — HU eID back side (MRZ TD1, classId 5,
HUN-BO-06001_BACK_PO): FULL image scores MRZvalid_score:100but the warped/cropped image of the same capture scores2; prod rejects on the crop becausegetMrzRecognitionAttempts(SelfServiceV2Service.js:673-712) can feed the warped-document attempt togetMrzCheckResult(SelfServiceCheckerService.js:219-246); two CV paths — warp-firstVuerCVOCRRecognition.js:45-99(/api/v2/document-warp→/api/v1/mrzon crop) vs no-warpMRZDetectionApi.js:22-38;validScoreValidator(:48-63) forces score 0 whendetections.length !== 1;valid_score/mrzDataonly persist whenocr.useCVMRZData=true; CV 4.9.0 fix likely only validated on FULL image (triage open)
Oracle Instant Client
- FKITDEV-8252 — Oracle has not published OL10 yum repos (404 across
yum.oracle.com/repo/OracleLinux/OL10/); decision to use OL9.el9instantclient RPMs on UBI10 base forkhandbbpartner Dockerfiles (Option 1 ship-it); memo at/Users/levander/coding/facekom/FKITDEV-8252-oracle-ol10-memo.mdawaiting Bence sign-off and partner-contract escalation
Package renames / repo drift (UBI10)
- FKITDEV-8252 — already-applied renames:
pcre-devel→pcre2-devel,zlib-devel→zlib-ng-compat-devel, redis→valkey (with compat symlinks), coturn.el8pin dropped → plain EPEL104.10.0-1.el10_3, rabbitmq/el/10/empty → fallback/el/9/3.13.7 .el8.noarch,shadow-utilsfor groupadd/useradd,x86_64→$basearchin OL10 repos; A.6.1 additions:libopus→opus/opus-devel,libmicrohttpdlives in EPEL10 not BaseOS,gzipmissing from UBI10 minimal, GitHub archive URL stripsvprefix (cd ${VAR#v}),git-lfs install --systemmust run before clone; on-probe-build watchlist for Phase B:ffmpeg-devel,libogg-devel,libconfig-devel,gtk-doc,jansson-devel,pkgconf,gengetopt,libsrtp2
Phantom room
- FKITDEV-8787 — Raiffeisen Myra mobile self-service rooms with vestigial duplicates; SDK-local
Already authorized/Already has some kind of roomguards; OSS V2SelfServiceV2Service.start()silently resumes any non-closed room; partial-unique-index gap - FKITDEV-8787 — FIX (2026-06-02, vuer_css
fix/FKITDEV-8787-...): server-side self-heal inselfService:v2:start— if staleselfServiceRoomData, call OSSgetRemainingSeconds(roomId)and delete only when< 1(room positively expired); abort handler now clears state too. Design learning: FAIL CLOSED on ambiguity — first cut deleted state on ANY RPC error (fail-open), which would let a transient error on a LIVE room spawn a 2nd live room (the very duplicate bug, inverted); verified OSS returns0for timed-out rooms so the catch only sees truly-absent rooms → preserve state + log error there. RULE: for a duplicate/phantom-room-prevention guard, “RPC threw” ≠ “resource dead”
portal_css
- portal_css — slim portal sister of vuer_css: registration, login, SCA, password recovery, JWT handoff (no Janus, no waiting-room)
- ASSICASH-71 —
hosts.portalconfig feeds CSPconnect-srcandPortalService.js:48password-recovery email URL; empty default is a silent foot-gun - FKITDEV-8239 — first repo in the dependency-reduction initiative to get a depcheck CI job; branch
chore/FKITDEV-8239-depcheck-ci(based onorigin/devel), not yet committed
Queues / RabbitMQ (app-side)
- vuer-oss-optional-queue-connection — vuer_oss supports multiple named MQ connections through
@techteamer/mq’sConnectionPool(named-map config shape);server.ts:465,background.ts:197andbin/attachment.js:52all readconfig.get('esign.queueConnection')thenconnectionPool.hasConnection(). So theoptional-queue ECONNREFUSED swallow inserver.ts(from FKITDEV-3191) is NOT dead code — it covers a supported partner setup where an external eSign RabbitMQ may be down at boot (without it, supervisord crash-loops a healthy service). It looks unreachable because no in-repo config setsoptional— partner runtime configs live outside the repo tree. An attempt to delete it as dead code was reverted. Rule: when auditing “unused” config keys, grep the readers, not the setters
Raiffeisen
- face-comparison-data-verdict-threshold-model — FKITDEV-8827 (PION) face-comparison export design: PION is a videochat flow (comparisons keyed by
roomId, produced byvideochat:closehook, gated byfaceRecognition.comparisonPairs), so the tool is a general both-paths export (raiffeisen-facecomparison-export.js+FaceComparisonExportService), not self-service-only; videochat rows get a report-computed verdict (no runtime classification) carrying raw distance + applied thresholds for audit; spec at.worktrees/vuer_oss-FKITDEV-8827/docs/superpowers/specs/2026-06-03-raiffeisen-facecomparison-export-design.md - FKITDEV-8581 — girinfo no-response observability change on
customization/raiffeisen:GiroProcess.handleTask()catch block split into distinct “no response” (timeout/network) vs “bad response” (non-200/save)logger.errors withelapsedMs/requestTimeout/code/statusCode; log-only (retry unchanged); heavier portal-state-marking option DEFERRED; SLARAFIPI-53 root cause = ambiguous portal states; original fixf830fd8e5ashipped 2025-11-28 but ticket still Pending - FKITDEV-8787 — Myra mobile KYC;
customization/raiffeisenoverrides;resolveExternalToken()reusescustomer.idperofferId(mechanism forcsökevény szoba); flow handlermyra-self-service-v2-phase-1; m3szi owns prior fix (FKITDEV-7667 / SLARAFIPI-53) - FKITDEV-8788 — Raiffeisen PION HU-eID-back MRZ crop bug (SLARAFIPI-61, marked “Solved” prematurely on a CV 4.9.0 full-image test); CV/ML owner Zsolt Mészáros, coordinator Bence László, reporter Bihari Péter; mitigation ships on
customization/raiffeisen - youtrack-tesztjegyzokonyv-attachment-recipe — Raiffeisen is the only client with an eSign-tied test record:
BUGRAFIPI-512“eSign 1.3.0.22 release” →…Raiffeisen esign - Tesztjegyzőkönyv - 22 Facekom Release v1.1.2.pdf(2024-10-24; 2/2 dev cases passed, executed Nagy Balázs 2024-10-16, components vuer_css/vuer_oss/esign_queue) + siblingBUGRAFIPI-516(esign bizalmi szolgáltatás DR recovery TJK). The recent Tesztelési jegyzőkönyv PDFs (ASSRAFIPI-117r1.9.11.94,-113r93,-102r92, 2026) are FaceKom/VUER OSS+CSS releases, NOT eSign.BUGRAFIPI-514(FaceKom 1.9.11.61) has both .pdf + .docx variants.
Reports / SL export
- FKITDEV-8639 — SL discrepancy between report UI and Excel export (NÚSZ). Two SL formulas coexist BY DESIGN: naive per-period round (
CallsReportService.js:669-670) vs volume-weighted overall (:558-559, Simpson’s-paradox gap). PR #7862 (543f293c38, tagnusz-1.9.11.45) made the Excel report self-consistent/auditable (Sum value on every row) but did NOT make UI per-period == Excel weighted-overall; team standardised on the weighted overall as the headline SL. Per nusz-1.9.11.47 (ASSNUSZ-58 UAT), the client STILL reported the SL discrepancy after the fix (“Az SL eltérés itt is jelentkezett”) while the daily-stat discrepancy resolved. OPEN PRODUCT DECISION: UI == Excel exactly requires picking ONE formula everywhere — a product call, not a further bug fix; likely the live topic. Bug C (ReportsService.js:63true→localeswallow) is DISTINCT from FKITDEV-8747 (forward locale through RPC queue boundary + empty SL when no calls, PR #7929, new for 1.9.11.48) — two locale bugs at two layers. Also Bug B (Excel column misalignment), Bug D (counting gapwaiting_calls > calls + exits). - FKITDEV-8747 — the follow-up fix that shipped (PR #7929, squash
5099b8ad8b, merged 2026-05-28, nusz 1.9.11.48; parent ASSNUSZ-58). NOT a call-count bug — the raw counting logic is unchanged; all changed files are CORE (video-calls report / daily statistics), surfaced by NÚSZ. Three squashed fixes: (1) empty-period SL →nullnot0(CallsReportService.js ~L562:SL = calls>0 ? round((calls-lateAnswers)/calls*100) : null) on per-bucket and Sum/aggregate; clientreportCalls.jsrendersnull→-(was always+ '%', so0%showed); (2) Sum-column SL aligned to the per-bucket rule — that mismatch was the reported “eltérés”; (3) locale plumbed end-to-end through the RPC queue (rpc_client/rpc_serverReports.js) + the newreporterDownload.process.jsBackgroundProcess (a booleantruewas passed instead of the locale string) → xlsx exports now use the user’s UI language, reviving the FKITDEV-8639 locale fix that was dead on the download path. Test cases:/Users/levander/coding/facekom/FKITDEV-8959-8747-test-cases.md(also covers FKITDEV-8959).
Security / dependency CVEs
- cve-2025-7783-form-data-via-request — CVE-2025-7783 / GHSA-fjxv-7rqg-78g4: critical
form-data@2.3.3(unsafe random multipart boundary; patched>=2.5.4) pulled in by EOLrequest@2.88.2whoseform-data: ~2.3.2hard-pin will never move. Not on devel — customization-line only, becauserequestis live partner code (vuer_osscustomization/api/sms/SmsCofidis.js; vuer_csscustomization/server/web/api/{login,register,partner-register}.endpoint.js). Red on cofidis/kh/raiffeisen branches. Interim fix =resolutionsoverride"request/form-data": "^2.5.6"+yarn install(house-style precedent:csurf/cookie,twig/minimatch,ts-jest/handlebars); real fix = droprequest, separate ticket - security-audit — consolidated FaceKom vulnerability findings across vuer_oss / vuer_css / vuer_cv / esign / pdfservice / nyilvantarto-scraper (2 CRITICAL, 6 HIGH, 5 MEDIUM, 6 LOW + positive findings)
Self-service v2
- face-comparison-data-verdict-threshold-model — self-service liveness-v2 face comparison (
SelfServiceV2Service.js:1418) is gated bytask.options.recognitionOptions.compareFaceWith(base V2 proto doesn’t set it → no row); self-service rows key byselfServiceRoomId, get per-room thresholds from the oldestselfService:v2:config:stateactivity (getActivityLogASC[0], REPLACES the set) falling back to globalSetting; verdict mirrors runtimegetFaceComparisonResult(unlike videochat rows which have no runtime verdict) - dev-box-cv-photo-processing-failures —
SelfServiceV2Service.photoCandidate(:1043) callssubmitTaskRecognitionunconditionally →FlowService.submitTaskRecognition→RecognitionService.runRecognitions→CVRecipe(server/cv/CVRecipe.js:88throws “Recipe missing no CV Service!” when CV health-check marked the host down); there is no dev flag that skips face-detection recognition (selfService.ui.disabledChecksonly covers girinfo/emrtd/kau), so an unreachable CV service hard-fails the nrt photo step - sms-verification-code-dev-testing — dev/testing: the self-service 2FA SMS code is set by the
customer:verification:sendSmshook; force it withtest.security.tempTokenSms(+restart+resend) or readcustomer.getVerificationCode()(stored asvideochatToken) - FKITDEV-8787 —
SelfServiceV2Service.start()silently resumes;_findOpenRoomForCustomerrace; status enum['waiting','incall','left','closed','deleted','archived']— only last three treated as not-open; V1 throw atSelfServiceRoomService.js:217swallowed bySelfServiceActions.js:27-34 - FKITDEV-8787 — socket-layer fix (vuer_css
server/socket/events/selfservice-v2.js):selfService:v2:startself-heals staleselfServiceRoomDatavia OSSgetRemainingSeconds(delete iff< 1),selfService:v2:abortclears state after the OSS abort RPC; tests use REALserver/auth.jspredicates viajest.requireActual(hand-rolled fakes had diverged — dropped theisAuthorized/customerIdconjunct + collapsed thehasAnyRoomroomDatabranch) - FKITDEV-8788 —
getMrzRecognitionAttempts(SelfServiceV2Service.js:673-712) selects between full-photo attempt (mrzTask.data.attachmentId) and warped-document attempt (candidate.document.attachmentId);getMrzCheckResult(SelfServiceCheckerService.js:219-246) turnsrecognitionAttempts[0].mrz.validinto accept/reject — fallback-to-full here is a candidate mitigation
Supervisor / process config
- unversioned-partner-supervisor-overlays — RELEASE BLOCKER pattern: partner supervisor overlays are NOT version-pinned to the app.
vuer_build/partner/<client>/vuer_oss/DockerfiledoesFROM harbor…/vuer_oss:${VUER_VERSION}…(version-pinned app image) thenCOPY supervisor_vuer_oss_docker.conf(unversioned, taken frommainat build time) → conf and app version are decoupled, so a rebuild of an old release tag gets the old app with today’s conf. Consequences of changing acommand=line: (a) older release tags stop rebuilding (MODULE_NOT_FOUND→ supervisord crash-loop), (b) ~94origin/customization/*branches still carry the old spelling so each partner breaks on its next build until it merges devel (time-staggered, looks like a random partner regression). Not fixable by merge ordering — it’s a versioning mismatch. Mitigations: hold thevuer_build/vuer-releasemerges until the first release tag containing the change is cut; or delete redundant overlay confs so partners inherit the base image’s symlink to the app’s own conf (decision rule in FKITDEV-8354-mvm-supervisor-config-dedup); or make overlays release-aware. Merge hazards:customization/khedits both confs (conflicts),customization/nuszeditsserver.js+cron.js(rename+modify). Surfaced by FKITDEV-8387 - FKITDEV-8354-mvm-supervisor-config-dedup — how supervisor configs reach
/etc/supervisor/conf.d/in vuer-release component images (reusable): TWO paths — (a) baseinstall/configure-app.sh:16-21symlinks the source package’ssupervisor*.conf, (b) the partner component DockerfileCOPYs a partner override on top (last-write-wins by filename);supervisord.confincludesfiles = …/conf.d/*.conf. Decision rule: a partner override is a deletable duplicate only if byte-identical to the repo’s conf, else it’s intentional customization. Applied to PR #28 (MVM): vuer_css override = byte-identical ⇒ deleted; vuer_oss override = kept (supervisor-stdout eventlistener loggingstdout_events_enabled=true/stdout_logfile=NONE, 8 programs, omits[program:vuer_oss_storage]— consistent across all vuer-release partners: equilor/nusz/polgaribank-facekom/unicredit/unicredit-srb/mvm). The eventlistener apparatus (supervisor_stdout.py+supervisor_stdout_eventlistener.conf+pip install supervisor-stdout) lives ONLY in vuer-release and is the consumer of the supervisor-stdout plugin restored in PR #28 round-1 (07db225) - FKITDEV-8252 — supervisord runtime gotchas on ubi10-minimal (build-green ≠ runs): supervisor 4.2.5 crashes on Py3.12 (
pkg_resourcesgone) → pin4.3.0; supervisord logfile path hidden by a/var/logbind-mount → log to/var/logroot; supervisord (PID1) does NOT propagate a program’s HOME nor doesUSERset it (erlang.erlang.cookieeacces → setenvironment=HOME=…per program); must run supervisord as ROOT (removed wrongUSER $DOCKER_USERfrom vuer_css/portal_css) - entrypoint-rename-blast-radius — renaming any vuer entrypoint (
server.js/cron.js/background.js/…) is a 4-repo coordinated release, not a single-repo edit: 95 supervisor conf files hard-codecommand=node <entry>.js— 75 invuer_build/partner/*(35 partners), 11 invuer-release/projects/*/components/*, 2 invuer_docker/workspace/devtools/files/, only 7 in the three code repos (vuer_oss/vuer_css/portal_css). Two SILENT traps beyond the confs:vuer_oss/server/logger.js:102–114picks the log4js channel by sniffingprocess.argv[1].endsWith('server.js')/etc. (rename → every process logs to theunknownchannel, no crash), and an 8th entrypointsoap_server.jsexists ONLY on bb/kh customization branches (…/{bb,kh}/vuer_oss/supervisor_vuer_oss_docker.conf:137, not ondevel). A missed conf = supervisord crash-loop (exit 2, restart 1–2 s; a March-2026 attempt did exactly this). Motivates FKITDEV-8387’s.ts-module + one-line.js-shim approach (keeps every conf/logger.js/.nycrcfilename literal untouched)
TypeScript
- FKITDEV-8387 — SUPERSEDES the shim plan: the entrypoint migration landed as a DIRECT RENAME (2026-07-22). After reviewer feedback on vuer_oss PR #8059 the
.js-shim strategy was dropped — entrypoints are real.tsfiles invoked ascommand=node server.ts, no shims: vuer_oss 7 entrypoints, vuer_css + portal_css 1 each, 75 supervisor confs invuer_build, 12 invuer-release; all three code PRs CI-green 8/8. Two gotchas worth remembering: thesoap_server.jssuffix trap ('soap_server.js'.endsWith('server.js') === true, so bb/kh’s SOAP entrypoint was silently inheriting thevuerlog4js channel; the rename dropped it tounknownwith no error →endsWith('server.ts') || endsWith('soap_server.js'); lesson: suffix-matching entrypoint dispatch is fragile under rename), and the still-open release blocker in unversioned-partner-supervisor-overlays - typescript-in-vuer-repos — CORRECTION (2026-07-22): the unflagged type-stripping floor is Node 22.18, NOT 22.6 — 22.6 required
--experimental-strip-types, and no supervisorcommand=passes node flags. Verified empirically:node:22.6on a.tsentrypoint →SyntaxError: Missing initializer in const declaration(parsing TS as JS);node:22.18runs it. Version surface:engines >=22.18.0in all three repos, images/CI (vuer_build,vuer_docker) install 24.x, butvuer-releasepins a floatingNODE_VERSION: 22— above the floor today, not pinned there - typescript-in-vuer-repos — how TypeScript actually works in vuer_oss/vuer_css/portal_css (established by FKITDEV-8246 “TS Magic”, vuer_oss PR #7645
55035572bb; foundation for the FKITDEV-8251 epic): NO build step (tsconfignoEmit:true+erasableSyntaxOnly:true, nothing runstsc, no typecheck job in CI in any of the three repos — TS is editor/ESLint-only, type errors don’t fail CI), Node ≥ 22.18 strips types natively at runtime, files stay CommonJS (no"type":"module"anywhere), a cross-modulerequireof a.tsmodule needs an explicit.tsextension (require('../util/magic.ts'); extensionless →MODULE_NOT_FOUND), root-level*.tsis SILENTLY UNLINTED (ESLint TS blockfiles:['server/**/*.ts','customization/**/*.ts','client/**/*.ts']→ a rootserver.tsgets “File ignored because no matching configuration was supplied”;tsconfig includehas the same blind spot), Jest transforms.tsvia@swc/jest(vuer_oss) /ts-jest(vuer_css, portal_css),@typescript-eslint/no-explicit-anyis an ERROR (never fix a type error withany), andrequire('node:module').stripTypeScriptTypes(src)cheaply asserts a file is erasable-syntax clean - nyc-cannot-load-typescript — GOTCHA:
nyc(v18) cannot load.tsat all — it hijacks the.tsextension handler (append-transform→default-require-extensions/js.js) and compiles TypeScript as raw JavaScript →SyntaxError: Unexpected token ':'; neither--extension=.tsnor--include '**/*.ts'helps (Node’s runtime type-stripping is bypassed by nyc’s require hook). Consequence:vuer_oss/supervisor_vuer_oss_e2e_test.confrunsnpx nyc node <entry>.jsfor all 7 entrypoints andserver.jsalready requires six.tsservices at boot (server.js:48,83,99,108,109,110) → the conf has been broken since FKITDEV-8246 “TS Magic” landed (Jan 2026); nothing outside the git index references it (no CI job, no Docker repo) so it went unnoticed. Fix = swapnyc→c8(V8 coverage, no require hook) or retire the conf; warrants its own YouTrack ticket. First hit on FKITDEV-8387 - FKITDEV-8387 — Task 6 implementation, vuer_css
server.jsshim: second repo in the multi-repo.ts-shim rollout, single entrypoint.vuer_css/server/logger.jsuses a static log channel list, unlike vuer_oss’sprocess.argv[1]-sniffing logger — no logger change needed, a repo-to-repo gotcha worth checking per repo. 4 files (eslint.config.mjs/tsconfig.jsonglob widen,server.ts<void>Promise-type fix,bin/server/server.task.jswatch list);tsc/eslint/yarn lintexit 0, 115/115 suites (1064 tests) pass; commitb6513dc0onchore/FKITDEV-8387-ts-entrypoints, local-only
Validation / log analysis
- ASSICASH-71 — 2026-05-18 validation: PROD + 2 UAT log pulls (~1.1M lines total) confirm CSP-channel flood is gone; FKITSYS-9486 holding (0
ohp-uat.mbhbank.hurefs in PROD); both UATs silent for 12-19 months; status moved to validated
vuer_cv
- dev-box-cv-photo-processing-failures — CV runs in its own container
vuer_cv(imageharbor.techteamer.com/facekom-devel/vuer_cv:4.6.2.DEV-...); when stopped, nginx returns 502 forhttps://cv-lederera.facekomdev.netand vuer_oss logsCV server is down;docker start vuer_cvboots it under supervisord (nginx/redis/CV proc/~10 workers) toUp (healthy)in ~2 min (loopback curl flips 502→404); but it can still be unreachable from vuer_oss due to hairpin NAT (see topic above) - FKITDEV-8252 — in scope for FKITDEV-8252 (Q3 resolved by execution); new
base/vuer_cv/DockerfileUBI10 base, probe-builds green at 5.93 GB (iter 7); needs EPEL10 forlibmicrohttpd,git-lfs install --systembefore clone,ENV_VERSION=8matchingconfig/docker.jsonrequiredEnvVersion; size-reduction (multi-stage drop ofgit-lfs/gcc-c++/python3-devel) flagged as follow-up; cleanupmicrodnf remove --allowerasingcascade throughgit-coredeps worth a sanity audit
WebRTC / video orientation
- FKITDEV-8533 —
videoOrientExt(theurn:3gpp:video-orientationRTP header extension) lets the receiver correct rotated video; gated at 4 sites —server/cv/VuerCVListenerSession.js,server/socket/events/videochat.js,server/transport/session/RoomTransportSession.js,server/transport/session/SelfServiceTransportSession.js(keep in sync). RESOLVED 2026-06-23 via “Option A — un-gate CVO for browsers” (branchfix/FKITDEV-8533-videoorient-ungate, commitd27d4cc990): restored the gate’s 2017 intent — shared helperserver/transport/videoOrientExt.jsvideoOrientExtEnabled(customer) = !customer.isNativeApp()(null→true) enables CVO for ALL browsers, disables it ONLY for the native SDK (userAgent.startsWith('mobile/')). Supersedes the iPad-detection PRs 7945 (no detection needed — the iPad is a browser). The customer’s own ID photo is captured from the LOCAL preview, which CVO can’t touch → client-canvas rotation (PR #3043) is orthogonal and still needed. - FKITDEV-8887 — iOS Safari audio interruption recovery;
InterruptionRecoverycontroller +VideoFeed.ensurePlaying()+Peer.replaceAudioTrack()proxy chain; see also## iOS Safari / audio recoverytopic for full detail
RTK / tooling gotchas
- rtk-mangles-curl-and-pipes — RTK (the token-proxy that auto-rewrites shell commands) MUTATES some commands, not just their output → silently wrong results.
curl <url>fails with curl error (3) “Malformed input to a URL function” (Rust proxy corrupts the URL;wgetalso unreliable);ls | sortreturns empty;find|wc -l/|grep -cget zeroed (dangerous — reads like a legit “no results”). Bypass viapython3: download withurllib.request.urlretrieve(not curl/wget); run multi-step CLI checks viasubprocess.run([...])argv list (noshell=True, not a shell pipeline); for counts cross-check two independent methods.rtk proxy <cmd>is a raw escape hatch but prefer the python bypass. Hit while fetching the actionlint binary for the FKITDEV-8239 review - rtk-git-log-hides-merge-commits — sibling RTK gotcha: output-filtering drops merge commits from
git log --oneline --graph, producing a deceptively linear DAG → squash/rebase/reset can operate on the wrong range and lose a parent’s history. Use parent-aware plumbing instead (git log --pretty='%h | %p | %s',git rev-list --parents -n 1 <sha>,git rev-list --count A..B); verify a squash preserved content by comparingHEAD^{tree}hashes before/after; non-interactive squash via backup-ref +reset --soft+ tree-hash equality gate (git rebase -iunavailable in this harness)
Release management / YouTrack
- vuer-release-build-flow — how the vuer-release build/release flow actually works, read from the
TechTeamer/vuer-release-cliPython source (2026-07-22) — therelease_toolbinary is NOT a black box. Flow:release-tool release create project <p>(interactive VERSION/BUILD_NUMBER/TAG) →projects/<p>/release/<N>/release.json+ tag<p>@<N>→autobuild.ymlon a self-hosted runner (RELEASE_PAT→~/.git-credentialsHTTPSx-access-token, download release_tool asset,gen→build→publishto Harbor withHARBOR_USER/HARBOR_SECRET). Corrections to previously-guessed assumptions: (1) component source is cloned fromTAG, notVERSION(gen.py::download_source→git clone --branch <TAG> --single-branch --depth 1);VERSIONonly feeds the image tag{registry}/{PROJECT_NAME}/{NAME}:{VERSION}.{BUILD_NUMBER}-{SECURITY_NUMBER}+ the generated.env. (2) a new base component needs nobase@Nrelease first —BASE_/PROJECT_/RELEASE_COMPONENT_IMAGE_TAGare the same locally-computed string, never resolved against the registry;build.pybuilds the base stage then the project stage against the just-built local image. (3) component NAME == GitHub repo name (repo_name = component["NAME"]underGIT_REMOTE_ORG), no override key;JANUS_REPOSITORYis only used byinstall-janus-build-env.sh. (4)release createwritesCOMPONENT_LIST,genonly reads it —component_env_values.json(base then project, project wins) supplies interactive prompt defaults atrelease create(release.py:239-259/269-297, written at:356);gen.py:76readsrelease_json["COMPONENT_LIST"]and never re-reads the component env files. This corrects the old “gen snapshots component config” gotcha in vuer-release-cut-recipe (now fixed there): janus pins are the effective default but overridable at release time, not immutable. (5)TAGis NOT inREQUIRED_ENV_VALUES(release.py:49=VERSION+BUILD_NUMBERonly) — it is prompted only if already present in the merged env values; janus deliberately has noTAG→has_source()false → never cloned by the CLI (fetched byinstall-janus-build-env.shviaJANUS_REPOSITORY/JANUS_VERSION_COMMIT); trap: a new base component missingTAGis silently never cloned. Plusgen.py::rm_alwayssanitization (strips.yarnrc,config/dev.json,.git, anysupervisor_*/nginx_*withoutdockerin the name), tarball top-level dir == NAME, component availability = directory existence (release/.gitkeeprequired;component_env_values.json+Dockerfileoptional), do not userelease-tool component create(stalecomponent.j2), and the FKITDEV-8349/DÁP application (forceddap-demo-partnerhyphen naming → Harbor image rename;TAG1.0.7.1not1.0.7) - youtrack-ready-for-release-nusz-query — YouTrack access + the NÚSZ “Ready for release” release-scope query. Tracker = YouTrack at
https://youtrack.techteamer.com(REST/api/issues; MCP server at/mcpin~/.claude.json, scoped toclaude_orchestrator). Auth = Bearer token from~/.config/facekom/youtrack.token(chmod 600, never on argv); the/fk-ticketcommand (.claude/commands/fk-ticket.md) +client.pyextractor read the same file. “Ready for release” is a TAG (exact stringReady for release; searchtag: {Ready for release}— braces for the spaces); it is tracker-wide (57 issues across clients), so theproject:filter is what scopes it. The four NÚSZ projects:CRNUSZ(Business Requests),BUGNUSZ(Support Issues),SLANUSZ(SLA),ASSNUSZ(Assist). Verified scope queryproject: CRNUSZ, BUGNUSZ, SLANUSZ, ASSNUSZ tag: {Ready for release}returned 3 on 2026-06-15 (CRNUSZ-102, ASSNUSZ-58, SLANUSZ-28; BUGNUSZ 0); read-onlycurl -G --data-urlencoderecipe included. CRNUSZ-102 verified example shows StatePendingyet tag-flagged → the tag (not State) is the readiness signal. Don’t confuse with the distinctUpcoming Releasetag. GET/read-only only. - nusz-1.9.11.47 — per-release tracking hub for nusz
@13/1.9.11.47(release issue ASSNUSZ-116 / FKITDEV-8938). Scope mechanism, dual-publish 🅼 Harbor / 🅻 vuer_build checklist, manual post-release YouTrack transitions, and a per-ticket payload detail section: CRNUSZ-102 (impl FKITDEV-8794/8801 — no code/PR found, business-accepted, UAT 06.18), SLANUSZ-28 (impl FKITDEV-8639 → PR #7862, NOT yet incustomization/nusz, may be in .45/.46), ASSNUSZ-58 (stat-export, UAT/PROD gate, targeted .46.1). Merge-status warning: payload code not yet confirmed incustomization/nusz; version target (.45/.46/.46.1/.47) needs confirming. - instacash-esign-1.3.0.11 — per-release hub for the InstaCash eSign
1.3.0.11release (eSign pipeline, not vuer-release): esign_oss + esign_css only, taginstacash-1.3.0.11/ Harborinstacash-esign-{oss,css}:1.3.0.11-20260608; ASSICASH-92 release + ASSICASH-93 TESZT / ASSICASH-96 PROD (approved 2026-06-26 from1.3.0.8); changelog = devel update + FKITDEV-8817 vuln fixes; no DB migration / no breaking change; rollback = redeploy1.3.0.8. First InstaCash release to ship with a TJK. - client-registry — cross-system name glue for
/fk-release: YouTrack suffix ≠ repo name (RAFIPI=raiffeisen, MNET=magnet, PB=polgaribank, GRALI/GRALIA=generali, etc.). 22 clients mapped with build-path (modernvuer-release/projects/<client>/ legacyvuer_build/partner/<client>/ eSign instacash) + resolution rules (YouTrack projectsCR/BUG/SLA/ASS<suffix>, version from openASS<suffix>Release issue, customization branchcustomization/<repo>incl.-instant/-v2/-f1variants). - release-automation-design — reusable prepare-and-gate
/fk-release <client>design. Now also covers client generalization (path auto-detection, universalASS<CLIENT>Release-issue convention proven by CIB .101), PR fetch without YouTrack VCS (VcsChangeCategoryempty → resolve viagit log --all --grep=FKITDEV-NNNNmerge-commit + comment-scan for pasted PR URLs), and comment extraction ranking (has-attachment > Hungarian QA keywords > embedded issue links; attachment URLs are signed/expiring). - FKITDEV-8354-mvm-supervisor-config-dedup — vuer-release Gen2 partner-migration mechanics (FKITDEV-8354, MVM project,
vuer_build→vuer-releaselean format, PR #28 basemaster): partner component images layer overrides viaprojects/<client>/components/<svc>/DockerfileCOPYon top of the source-package files symlinked by baseinstall/configure-app.sh; supervisor-config dedup decision rule (byte-identical ⇒ delete, else keep). Do not conflate with FKITDEV-8252 PR #31feat: ubi10(different ticket/branch). Reviewerbencelaszlo; round-1 set janus pins1.4.1/cc0fdca8+ restored supervisor-stdout. - youtrack-tesztjegyzokonyv-attachment-recipe — where FaceKom test records (“tesztjegyzőkönyv” / “Tesztelési jegyzőkönyv”) live + a read-only REST attachment recipe. TJKs are PDF/DOCX attachments on per-client
ASS<CLIENT>release /BUG<CLIENT>tickets, NOT standalone issues; 8-section branded template (Cél / háttér / teszttípus-összegzés / tesztesetek / jegyzőkönyv+evidencia / értékelés / hibák / mellékletek); canonical templates = FKITDEV-8329 (unified format) + FKITDEV-8330 (release/install template). Recipe (pythonurllib, same base +~/.config/facekom/youtrack.tokenas youtrack-ready-for-release-nusz-query):GET /api/issues?query=…&fields=…,attachments(name,mimeType,created,url),comments(text,attachments(…)), Hungarian full-text works, scope byproject:; download = prepend base to the attachment’s relative signedurl, GET w/ Bearer, write bytes; timestamps epoch-ms. GET/read-only. - tesztjegyzokonyv-generation-flow — producing companion to the attachment-recipe note: a
/fk-tjkflow to GENERATE per-partner Tesztelési jegyzőkönyv.docxfor a release (built 2026-06-26). Practice: one TJK per AFFECTED partner per1.9.11.NN(not all 39), attached to that partner’s release ticket; shortName usuallyASS<PARTNER>/BUG<PARTNER>but VARIES (MicroSec=MF, DÁP=DAP/ASSDAP) sopartners.jsonpinsytProject; a core change reuses byte-identical body text across partners (MKBASSMKB-90== BBASSBB-82). New std templatetesztjegyzokonyv_sablon.docx(authored 2026-05-29, replaces 3 inconsistent legacy formats) = 19<…>placeholders each intact in a single<w:t>run, all inword/document.xml→ plain string substitution preserves styling (no docxtemplater/pandoc). Tool = Claude command.claude/commands/fk-tjk.md(pulls dev ticket viafkticket+ 1 past report/partner for house style → draft → render) + stdlib renderer.claude/scripts/tjk/render_tjk.py(clones test-case block document.xml paras 27–36 per case w/1.→k.,\n→<w:br/>, verbatim zip-repackage swapping ONLY document.xml, self-check) +partners.json(13 seeded —instacash/ASSICASH added 2026-06-26) + pinned sablon. v1 leaves screenshots / pass-fail underline / PDF export / YouTrack-attach MANUAL (no write-back). Self-check + tests pass; design spec/Users/levander/coding/facekom/docs/superpowers/specs/2026-06-26-teszt-jegyzokonyv-flow-design.md. First real use (2026-06-26): generated the first-ever InstaCash eSign TJK (5 cases) for eSign 1.3.0.11 →~/Downloads/tesztjegyzokonyv_instacash_1.3.0.11.docx.