Skip to content

SCRUM-254 — AdminUI content packs page

Plan ref: UI-9 (docs/11-admin-plane-plan.md). Uses Config's pack routes (SCRUM-217) through gateway_dev's 512 MiB upload route (SCRUM-195).

What exists

Piece Notes
client.ts uploadWithProgress XMLHttpRequest with upload.onprogress, the same bearer token, COM-5 error mapping and one refresh-and-retry as request; abortable
config.ts listPacks(), uploadPack(name, file, …) returning the pack and created (201 new vs 200 same bytes already stored)
Route /config/packs "Packs" viewer to read, content group in the nav
Upload (live_ops+) drop zone / file picker for .pck; name derived from the file name and validated against Config's rule; GDPC header checked in the browser before uploading; > 512 MiB refused with the limit named; progress bar (percent, MiB, rate, ETA), Cancel, leave-page warning; result shows sha256 and size, or "Already uploaded" for identical bytes
Pack list name, short sha (copyable), size, uploader, time; refreshed after an upload

Also: the service-detail timing test now measures from the click to the chart's draw timestamp inside the page (the 500 ms budget is unchanged); it had been counting Playwright's own click overhead and failed intermittently on staging.

How to verify

cd services/adminui
npm run typecheck && npm run lint && npm run format:check && npx vitest run && npm run build
npx playwright test

Results at time of writing

  • typecheck, lint, prettier, vitest (382 tests), build: pass; Playwright 23/23 twice, incl. a 100 MB upload whose progress bar is sampled between 0 and 100 and completes with a sha, the same file again → "Already uploaded", and a non-GDPC file refused in the browser. Screenshots checked before and after an upload.

How it was built

DeepSeek run scoped (Landlock) to services/adminui; interrupted twice by WSL crashes, then a continuation round hit its one-hour limit with the work complete but unreported. Claude rebased it onto the merged staging, ran every check, and dropped an unrelated comment edit in vite.config.ts.