NÚSZ 1.9.11.48 — Release Test Runbook (TJK source)

Release ticket: ASSNUSZ-126 “NÚSZ Release 1.9.11.48” · prep/devel-update ticket: FKITDEV-9217 · vuer-release: next = release/17 + nusz@17 Build under test: vuer_oss chore/FKITDEV-9217-nusz-devel-update (HEAD d09274cb, merge eb865201) + vuer_css (merge 828846cc). Scope of .48 = fresh devel core-sync (~80 OSS / ~38 CSS commits) folded onto customization/nusz, plus the two NÚSZ payload items already on customization/nusz since .47: ASSNUSZ-76 / FKITDEV-9150 (webm/reconversion + retention-cron hardening) and FKITDEV-8975 (NÚSZ text). ASSNUSZ-117 / FKITDEV-8959 (image-deletion) already shipped in .47 — excluded.

Reconciliation notes / confirm before sign-off

  • AI-Act IS present (PortalData.js aiIdentificationConsent, AiActRPCServer.js, aiAct.* config both repos) but config-gated OFF by default (CSS aiAct.videoCall=false, aiAct.selfService=false). Test per §2.
  • FKITDEV-9150 productized script = bin/remove-old-video-files.js (with -f/-t). The bin/nusz-*.js rescue scripts from the ASSNUSZ-76 RCA are separate ops artifacts, not in this tree.
  • Retention values: config/dev.json removeOldRoomData = videos 7d / audios 730d / attachments 7d. Confirm the prod-intended NÚSZ value (7d vs 28d question is open).
  • Known pre-existing reds (NOT regressions): calls-report-service.test.js (inherited dead Dictionary import — repaired in HEAD d09274cb); @techteamer/sequelize fork audit red (NÚSZ is Postgres, not Oracle — no ORA breakage).

1. Payload verification

1.1 ASSNUSZ-76 / FKITDEV-9150 — remove-old-data cron doesn’t wedge & regenerates audio-only webm — P1

  • What: Nightly RemoveOldRoomDataCronJob (+ manual CLI) runs to completion without hanging on ffmpeg’s Overwrite? [y/N] prompt, and strips the video track from old recordings → audio-only webm. Root cause was missing ffmpeg -y; symptoms = wedged cron (prod “started 49 / finished 17”) + fat A/V webm surviving retention (~1 TB, disk 98–99%).
  • How:
    1. node ./bin/remove-old-video-files.js -f 2024-08-01 -t 2024-08-02 on a data-bearing env.
    2. Logs: RemoveOldRoomData startedremoveVideoData started/finishedremoveAttachmentData finished: {"processed":N,…,"errored":0}RemoveOldRoomData finished.
    3. Inspect one processed room’s converted/*.webmvideo track gone (audio-only), size dropped.
    4. Process exits (no stdin hang).
  • Expected: No TypeError: Cannot read properties of undefined (reading '_run'), no overwrite-prompt hang, errored:0, replay webm audio-only + smaller. Stray *-tmp files are harmless (atomic temp+rename).
  • Fix internals (tester awareness): -y on generateNewWebmFile; audio-only written to …-tmp then fsPromises.rename on success; MediaFile.findOne fallback for out-of-window webm rows; per-file getMetadata guard; -f lavfi split to two argv tokens; manual CLI registers ffmpeg (FFmpegService.ts) + customerKeyStorage.

1.2 Cron scheduling & config sanity — P2

  • How: config/dev.json removeOldRoomData.cron: active:true, schedule:"0 0 * * *", videos{expiryDays:7}, audios{730}, attachments{7, batchSize:500, maxPerRun:5000}. Confirm cron-customization.js registers RemoveOldRoomDataCronJob + RemoveAttachmentDataCronJob at boot; let the run fire and confirm errored:0 with no manual invocation.
  • Expected: Registered, runs on schedule, batched attachment blanking drains; order videos → audios → attachments.
  • UAT can’t show: real disk reclaim + load profile (~40–50% CPU, ~940 Mbit/s, ~1 TB backlog) are prod-only. Deploy ladder = prod after-hours 1-day pilot → month → full walk, with data-owner approval. UAT proves the script runs clean, not that space frees.
  • Prod-only path: customer-key-offline branch (key inaccessible → blank + archive encryptionId=null) not reproducible in UAT.

1.3 FKITDEV-8975 — NÚSZ text renders correctly — P2

  • What: Copy only. Email/Email aktiválásE-mail-cím/E-mail-cím aktiválása; - → en-dash in “Magyar Közút Nonprofit Zrt. – Útdíj Üzletág”; Tel.számTelefonszám; megtisztelt minketmegtisztelt bennünket; comma in “kérjük, ne válaszoljon rá.” Touches 15 email letter.trans.js + PortalData.trans.js.
  • How: Preview/trigger the affected NÚSZ emails + view a customer data sheet; visual-diff vs the ticket’s before/after; check hu + en.
  • Expected: New wording renders; en-dash + “E-mail-cím” present; no broken placeholders. Visual, low risk.

2. AI-Act (new regulatory feature) — present but OFF by default

Background (docs/features/ai-act/developer-hu.md): EU AI-Act disclosure before any OCR/CV/AI step. After registration the customer is informed and must accept to proceed. Rejection is log-only — does NOT change portalData, does NOT immediately abort (AIACT_ERROR_NOTACCEPTED returned/logged). Already-accepted customers are never re-asked. For mobile SDK, the server checks AI-Act state before a videocall starts.

Config: CSS aiAct.videoCall / aiAct.selfService (bool; off → client passes through), aiAct.compatibleSdkVersion.{web:^2.8.0, android:^2.4.1, ios:^2.4.1} (min SDK); OSS compatibleSdkVersion.{android:^3.0.0, ios:^3.0.0, websdk:^2.8.0} + configEditor aiactdocument_hu/_en. Defaults: both flags false. OSS AiActRPCServer: acceptAiAct (sets aiIdentificationConsent=true, finishes task, next step), aiActStatus (default false), rejectAiAct (warn + AIACT_ERROR_NOTACCEPTED), getConsentPortalData, getDocumentUrl(WithLocale). Portal field aiIdentificationConsent (checkbox, required).

2.1 AI-Act OFF (default) — flows not gated — P1 ← primary NÚSZ prod config

  • How: Leave aiAct.videoCall=false + selfService=false; run a NÚSZ videochat identification (§3) and (if used) a self-service flow.
  • Expected: No consent screen; client proceeds; no AIACT_ERROR_NOTACCEPTED; waiting-room entry normal.

2.2 AI-Act ON — videochat gate — P2

  • How: aiAct.videoCall=true, restart. Fresh (not-consented) customer starts NÚSZ video-ID. Try continue without ticking, then tick + continue. Repeat with an already-consented customer.
  • Expected: Consent shown before first AI interaction / waiting-room. Continue-without-tick → „Kérjük jelölje be a négyzetet, ha folytatni szeretné!” and customer never hits the operator waiting list. Tick → proceeds (202/next step), aiIdentificationConsent on the data sheet. Already-consented → not re-prompted. Reject / aiActStatus=falseAIACT_ERROR_NOTACCEPTED, no waiting-list entry, portalData unchanged (warn logged).

2.3 AI-Act ON — self-service gate — P3 (only if NÚSZ enables self-service)

  • How: aiAct.selfService=true; run a self-service room. Consent on prep page before technical start; accept advances, reject blocks with AIACT_ERROR_NOTACCEPTED.
  • Note: NÚSZ’s 12 flows are operator-videochat; self-service may not be in the NÚSZ prod profile — confirm first.

2.4 SDK-version compatibility & default document — P3

  • How: (a) WebSDK ≥ 2.8.0 → AI-Act step renders/completes; older SDK → flagged incompatible/passed through per config. (b) aiactdocument_hu/en unset → default doc served (facekom.net/docs/ai_act_tajekoztato.pdf HU / …/ai_act_information_notice.pdf EN) links resolve; set → partner doc shown.
  • Flag: websdk-side compatibleSdkVersion.web enforcement noted “not yet implemented on websdk side” — verify actual behaviour.

3. Core NÚSZ flow smoke (E2E) — P1

The 12 operator-videochat flows (config/dev.jsonflow.flows): nusz-customer-identification, nusz-surcharge-payment, …-with-country-vignette, …-without-country-vignette, nusz-application-for-surcharge-cap, nusz-surcharge-cap, nusz-surcharge-amnesty-application, nusz-surcharge-amnesty, nusz-request-for-instalments, nusz-false-detection, nusz-service-modification, nusz-proof-of-eligibility.

3.1 Flow registration at boot — P1

  • How: Boot OSS; check startup flow-registration logs; open the flow list in operator/admin UI.
  • Expected: 12 flows present + creatable; none silently fail (merge kept NÚSZ’s 12, dropped devel’s test flows + extraCreatableProtoType).

3.2 Main identification + surcharge-payment E2E — P1

  • How: Register a test customer (test phone for SMS 2FA; ensure vuer_cv up for photo/liveness). Operator creates/joins a room, runs nusz-customer-identification (greeting → confirmation → identification → feedback → CaseIdentification), then nusz-surcharge-payment (documentsPresentation → paymentIntentConfirmation → sendPaymentLink → paymentInformation → paymentConfirmation → paymentFeedback → caseFeedback → caseClose).
  • Expected: confirm gates require explicit action; reaches caseClose, instance → finished; registration fields (licensePlate, purchaseId, surchargeIdentifier, zipCode/settlement/street/houseNumber…) persist.

3.3 Vignette + remaining flows spot-check — P2 / P3

  • P2: nusz-surcharge-payment-with-country-vignette + nusz-surcharge-amnesty-application E2E.
  • P3: smoke the rest to first confirm + caseClose.

4. Devel-update regression by area

4.1 Reports — SL / daily-stat (FKITDEV-8747 area) — P1

  • What: Empty-period SL renders - (null) not 0%; Sum SL matches per-period; xlsx/download exports in the user’s UI language.
  • How: Calls report, date range with an empty period → check SL column + Sum row; as HU-UI user export xlsx + open.
  • Expected: Empty SL -; Sum consistent; xlsx Hungarian for HU-UI. (Don’t flag the inherited calls-report-service.test.js red.)
  • P2: advanced-reports RPC (ReportsAdvancedService, reports-advanced) loads + produces a report; formats [xlsx,csv,txt,pdf,docx], maxDateRange:31.

4.2 Portal registration / PortalData field set — P1

  • How: Complete a portal registration; all fields render, validate (required aiIdentificationConsent), persist to the data sheet.
  • Expected: No missing/dup fields; NÚSZ “waiting” customisation intact (nusz.customerService.waitingTimes.verboseLog).

4.3 Videochat — PermissionService + InterruptionRecovery — P1 / P2

  • P1 (FKITDEV-8575): deny/disable customer camera mid-call → activity-log entry; operator re-request → customer re-prompted.
  • P2 (FKITDEV-8887): real iOS Safari — background mid-call (lock to read SMS), return → audio resumes both ways. Safari-gated (iPadOS = desktop UA); hard to verify on desktop.
  • P3: socket changes (fkitdev-8846 dedup socket, fkitdev-9199 socket token) — call connects once, layout token works.

4.4 Attachment / S3 storage & export — P1

  • What: NÚSZ inline S3 engine + sync brings FKITDEV-7665 (S3 attachment storage, BREAKING) + 9125 model file storage + 9104 attachmentId index + 8924 restore self-service attachments — prime conflict surface.
  • How: Upload attachment / store media in an ID flow; retrieve; vuer_oss_storage worker moves media (storageUploadCronJob 45 * * * *); run a room export (roomExport/selfServiceRoomExport) → archive with correct full names (fkitdev-8260).
  • Expected: Upload/retrieve/move OK; export complete + openable.

4.5 Emails / MJML v5 (FKITDEV-8727, BREAKING — ESM) — P1

  • What: MJML v5 is ESM-only; a NÚSZ *.letter.data.js mixing top-level import + bare require( → Node treats it ESM → require undefined → letter type silently never registers, email never sends (green CI, broken runtime).
  • How: For each NÚSZ email, actually trigger + confirm it sends (Mailtrap sandbox / overridden inbox): invite, verification, device-change, password-recovery, restore, archive, cert-expiry, audit-log-alarm, validation, appointment-remember/verification, user-temporary-password, user-password-change, document-summary, auto-archive-summary. (Also re-checks 8975 text.)
  • Expected: Every email sends + renders; silence = failure. Watch boot logs for letter-type registration errors.

4.6 Crons (general) — P2

  • How: NÚSZ cron set registers + runs: storageUploadCronJob 45 * * * *, audioArchive 0 23 * * *, audioDelete 730d 0 0 * * *, removeOldRoomData (§1.2), + customerDelete, autoCloseRooms, flowClear, roomBulkDelete, temporaryFileCleanup (deleteRoomCronJob defaults active:false).
  • Expected: All boot-register; none throw first run.

4.7 TS-entrypoint / merge-hidden breakage sweep — P2 (dev/CI, not UAT)

  • What: Sync renamed FFmpegService.js.ts; extensionless require('./server/service/FFmpegService') survives a conflict-free merge but breaks nyc/eslint. (9150 CLI + cron.js already use explicit .ts.)
  • How (dev): grep extensionless requires of renamed modules + any require of deleted aiActHelper.ts (→ server/web/helper/getAiActData.js); run lint/unit.
  • Expected: clean except the two known pre-existing reds.

Priority summary

P1: §1.1 cron/webm, §2.1 AI-Act-off, §3.1–3.2 flow registration + main E2E, §4.1 reports, §4.2 portal, §4.3 camera permission, §4.4 attachments/S3, §4.5 emails. P2/P3: §1.3 text, AI-Act on-path, vignette/other flows, iOS audio recovery, advanced reports, crons, TS/CI sweep. Cannot be validated in UAT: real disk reclaim & load profile, reconversion backlog scale, customer-key-offline deletion branch — all prod-only.