Validated end-to-end. The recent Qlik client authorizes the engine websocket
via ?reloadUri=...&qlik-csrf-token=<token> (not Xrfkey). Capture that token
from the client's own ws, then open ours in-page with it. Use the real engine
master-item qIds (dim Article Code=yesCP, CA N=JhqJ, Quantité N=41516861...,
Magasin Ventes Nb N=yNBLjc) — the QRS object IDs returned error 7001. Select
the supplier's codes on field "Article Code" (the app holds ~1.2M codes).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The recent Qlik client uses qmfe/single-spa (no js/qlik Capability API). Go
back to a raw engine websocket but opened in-page from the authenticated
browser (injected X-Qlik-Session cookie), which the proxy accepts. Use the
session xrfkey and capture ws close code/reason for diagnostics.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Raw and in-page websockets with a self-generated xrfkey are rejected (403).
Switch to the Qlik Capability API (require(['js/qlik']) → openApp → createCube),
which reuses the authenticated page session and manages the engine ws + xrfkey
internally. Auth via injected X-Qlik-Session cookie (Node ticket flow) +
httpCredentials. Logs rich page diagnostics on failure.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Qlik proxy refuses a raw server-side websocket (403, even internally), so
extraction now runs through headless Chromium (NTLM via httpCredentials, like
the hermes agent) and opens the Engine websocket in-page — same origin, which
the proxy accepts. Efficient: selects the supplier's article codes on the
"Article Code" field so the hypercube returns only those rows.
- qlik-playwright.ts: browser singleton, in-page hypercube extraction (paginated)
- /api/qlik/sync: use the Playwright extractor
- Dockerfile: install chromium + headless deps, PLAYWRIGHT_CHROMIUM_PATH, copy playwright-core
- deps: playwright-core (lockfiles synced)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>