Plugin reports render; USB check-in/out audit report; kiosk drive lists

This commit is contained in:
2026-08-27 10:20:59 -04:00
parent 376298dc02
commit 60c340b07f
7 changed files with 609 additions and 59 deletions

View File

@@ -12,6 +12,38 @@ ADR-007 and ADR-002.
### Added
- **USB check-in / check-out audit report.** CMMC removable-media tracking is an
audit obligation and there was no report for it - answering "who had this
drive, and when" meant paging through the check-in/out list by hand. The
window is named rather than a day count: today, last month, six months, a
year, or all time. Events rather than totals, because that is the question an
audit actually asks, with a CSV export for the people who want it in a
spreadsheet. Works against the external `cmmc_usb` log or the self-hosted
tables; in self-hosted mode one stored loan expands into a take and a return,
so a returned drive is distinguishable from one still out.
### Fixed
- **Plugin reports rendered a raw JSON dump.** The reports page ran a hardcoded
switch over five core report ids and fell through to
`console.error('Unknown report')`, and its results panel was a matching chain
of per-id templates ending in a `JSON.stringify`. So a plugin could register a
report, watch it appear in the catalogue, and get a wall of JSON when it was
opened - which is where the three printedparts reports have been since they
were added. Any report that declares an endpoint is now fetched from it, and
any report returning `{columns, rows}` renders as a table. A plugin needs no
core code to have a working report. CSV export follows the same endpoint
rather than assuming `/api/reports/<id>`, which does not exist for a plugin
report, and a report that fails now says so instead of showing an empty panel.
Export CSV is fetched through the api client rather than `window.open`: a new
window carries no Authorization header, so every report behind a real
`jwt_required` answered the export button with a 401. The core reports are
jwt-optional, which is the only reason the old way ever appeared to work.
- **Reports had no way to choose a time period.** Endpoints accepted a window;
the page offered no control for it, so `printedparts-consumption` was
permanently stuck on its 30-day default.
- **USB kiosk: check a drive out and back in without a login.** The people who
actually take USB drives are standing at the cabinet, and most of them have no
ShopDB account - so check-out and check-in were gated behind a login that was