On this page
Feature-flag and rollout behaviorAccess Keys and the lease layerUpload verification and storageX-ray acquisition lifecycleKnown cosmetic bug (carried forward, still present)Desktop app (xolize-core) — worth flagging to the team that owns itFor Quality
Status: pre-release, beta-gated. This page lists what to test, re-derived from a fresh read of the current code (both /work/repo and the companion xolize-core desktop-app repo) rather than carried over from an earlier draft. An earlier version of this documentation, written before a subsequent security rewrite on this branch, listed several verified access-control gaps as release blockers — every one of those has since been fixed and is no longer listed here. What follows is a new pass, not a copy.
Feature-flag and rollout behavior
- Beta gating works end-to-end. For a company with
isBeta: false, confirm: the Acquire button doesn't render (XrayUploadBox.js'suseFeatureFlagcheck), therequestXrayAcquisitionmutation rejects with "X-ray acquisition is unavailable" if called directly, and the desktop app'sconnectcall gets404rather than a lease. Then flipisBetaon and confirm the feature-flag cache (5-minute TTL) actually picks it up within that window rather than requiring a server restart. - Emergency kill switch. Set the
FEATURE_XRAY_ACQUISITIONflag'sactivefield tofalseand confirm every enforcement point (client button, web mutation, desktop connect, desktop lease validation) fails closed immediately, including for a desktop app that's already mid-session with a valid lease. - Outdated desktop client. Send a
connectrequest with aclientVersionbelowMINIMUM_XRAY_DESKTOP_VERSION(once that env var is configured) and confirm a426 CLIENT_UPDATE_REQUIREDrather than a silent failure.
Access Keys and the lease layer
- Revoke is not delete. Revoke a key and confirm: it stays visible in the list with "Revoked" status (not removed), its checkboxes/scopes remain visible for audit purposes, the delete button becomes disabled, and — the part most worth testing deliberately — a desktop app already holding an active room lease from that key loses the room immediately (not after the 90-second lease TTL), because
revokeAccessKeyexplicitly callsdesktopConnectionManager.revokeByAccessKey. - Room collision. With one desktop instance already connected to a room, have a second instance attempt to connect to the same
(branchId, room)and confirm a409 ROOM_OCCUPIEDrather than the first instance being silently displaced. - Lease vs. Access Key on every call. Confirm that revoking a key mid-session invalidates not just new
connectattempts but also in-flightheartbeat/transitions/upload-intentscalls using an already-issued lease token —validateDesktopPrincipalre-checksrevokedAton every call, not just at lease-issue time; this is worth a direct test since it's easy to accidentally only re-check at connect time in code like this. - Rate limits. Confirm the documented limiter thresholds actually trigger (120/min for lease-bearing calls, 60/hour for upload-bearing calls, 120/min and 60/min per-IP for validate/setup) and that hitting them returns a clear error rather than a generic 500. Also worth confirming the IP-based limiters can't be trivially bypassed by a spoofed
X-Forwarded-Forheader — this depends onTRUST_PROXY_HOPSbeing correctly configured per environment (see Rollout, Feature Flag & Observability); test with a plausible production proxy-hop count, not just locally. - Row-level query scoping returns empty, not an error.
xrayAcquisitionRequestandxrayAcquisitionLogs(singular lookups) returnnull/[]for a request outside the caller's company or branch access, rather than throwing. Deliberately test this with a cross-company ID and confirm the response is genuinely empty (not e.g. an error page that a tester might misread as "the query failed for an unrelated reason" and move on without confirming no data leaked).
Upload verification and storage
- A tampered upload is rejected. Get a real upload intent, then upload a file to the presigned URL that doesn't match the declared size, content-type, or checksum, and confirm
/completerejects it (size/type/checksum mismatch) rather than trusting the desktop app's original declaration. - A non-image "PNG"/"BMP" is rejected. Upload a file with a correct declared size/checksum but that isn't actually a valid PNG/BMP (e.g. a renamed text file with matching byte length) and confirm the header inspector (
inspectXrayHeader) rejects it — this is real header parsing, not just a MIME-type/extension check. - Storage quota is enforced and refunded. Reserve an upload intent for a company near its
sizeLeftlimit and confirm it's rejected once the limit would be exceeded; then cancel an in-flight acquisition or let an intent expire and confirm the reserved bytes are actually credited back tosizeLeftrather than leaking. - Orphaned object cleanup. Create an intent, upload the object, then cancel the acquisition before calling
/complete— confirm the cron job eventually deletes the now-orphaned S3 object (cleanupCancelledXrayUploadObjects) and that theXrayOrphanCleanupFailingalert would fire if that deletion itself started failing.
X-ray acquisition lifecycle
- Request a capture with no desktop app connected → should reject with "No desktop app connected in this room."
- Request a second capture for a slot that already has an active (non-terminal) request → should reject.
- Request a capture into a slot number invalid for the X-ray's chart type (e.g. slot 19 on a 5-slot bitewing layout) → should reject client- and server-side (
VALID_SLOTS). - Full happy path across every status, including the newer
PREVIEWstep for multi-page captures — confirm the widget renders it sensibly (it currently maps to the same visual step as "In Progress"). - Retry the same web request with the same
clientRequestId→ should return the original request, not create a duplicate; retry with the sameclientRequestIdbut different input → should be rejected as an idempotency conflict. - Cancel while
WAITING/ACCEPTED→ succeeds for the requester; attempt as a different non-admin staff member → should be rejected; attempt as aDO_ALLadmin on someone else's request → should succeed. - Let a request sit past its per-state deadline → confirm the cron flips it to
TIMEOUTand the requester's browser updates without a manual refresh. Also confirm a request that's already pastCAPTUREDdoes not get force-timed-out by this mechanism (by design — see Real-Time Status, Presence & Timeouts), only its upload intent's own 10-minute expiry applies from that point. - Two browser tabs/users watching the same branch: confirm both see live updates via subscription; a third tab on "All Branches" should still update, just on the 10s poll.
Known cosmetic bug (carried forward, still present)
- The Room column header in Logs → X-Ray Acquisitions still renders as the literal string
patients.roominstead of "Room", in both English and (very likely) Arabic — visible directly in the Walkthrough screenshot of this page. Root cause, re-confirmed against the current translation files:XrayAcquisitions.js:136callst('patients.room'), but onlycalendar.roomexists inpackages/clinic-mobile/src/shared/i18n/translations/en.json— nopatients.roomkey exists anywhere in that file. This was flagged in the earlier draft and has not been fixed since.
Desktop app (xolize-core) — worth flagging to the team that owns it
- No real-hardware validation yet. Per the desktop repo's own
XRAY_RELEASE_ACCEPTANCE.md, the physical-scanner validation matrix is entirely "Not run." Everything validated so far is against TWAIN's reference sample source and the app's E2E simulation mode. This is a real gap for anyone planning a pilot with an actual clinic's scanner hardware, not a documentation nitpick. - Unsigned installer. Releases are built and published unsigned, explicitly framed as a temporary pilot state in the desktop repo's own docs — Windows SmartScreen warnings during pilot install are expected, not a bug to file.
- Update-safety window. Confirm the desktop app genuinely defers a forced auto-update restart while a capture/upload is in progress, rather than only doing so in the common case — this is a real correctness property (
isUpdateRestartSafe), worth an explicit test rather than trusting the code comment.