Claude VM f49fdb1da0 harden(epay): cart hygiene, auth/IDOR gates, single-page fetch, parallel downloads
Live-path hardening from the 2026-06-04 deep-dive (11 confirmed criticals).
ArchiTools-only; the legacy queue is still the sole fulfiller.

Security:
- requireCfAccess() — staff-only, portal accounts blocked, fail-closed
  in-route on download / download-zip / cf-status / orders (C4 IDOR/PII)
  and order / recover (C3). order also enforces a daily credit cap
  (ANCPI_DAILY_CREDIT_CAP, default 200) and stamps userId.
- /api/ancpi/test returns 404 in production — it was a GET that spends 2
  real credits, CSRF-able (C5).
- drop the token-metadata debug blob from the session (QW8).

Correctness / robustness:
- cart hygiene (C1): build the ePay cart under an invariant — the Nth add
  must report N items; any excess = pre-existing junk, so we wipe + abort
  (never submit a cart we didn't fully build). Pre-submit failures clean
  up our basket rows; post-submit we never touch the cart (recover owns
  it). metadata-less rows are deleted from the cart.
- getOrderStatus fetches the whole order in ONE page (itemsPerPage, QW4);
  navDir loop kept only as fallback. index-fallback matches are flagged
  'review' instead of silently 'completed' with a possibly-wrong PDF (R4).
- downloadDocument asserts %PDF magic bytes — a login page returned mid
  session no longer gets stored as a .pdf (R2). Session reuse TTL aligned
  under ANCPI's ~10min expiry.
- recover accepts ?extractId= and pre-submit states; retry buttons in the
  ePay tab re-run poll+download with no new charge (QW2/QW3).

Performance:
- parallel document downloads (V1, concurrency 4); poll writes only on
  status change via updateMany (QW5); getNextFileIndex scans the cadastral
  prefix instead of the whole bucket — and actually works now (it was
  ^-anchoring the full key, so every file got index 1) (V2); download-zip
  streams instead of buffering the whole archive, capped at 100 (V3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 23:59:44 +03:00
S
Description
No description provided
3.4 MiB
Languages
TypeScript 98.7%
Shell 0.4%
PLpgSQL 0.4%
Dockerfile 0.2%
CSS 0.1%
Other 0.1%