printedparts stage 15: print-file revision history + role-based alerts
Some checks failed
CI / backend (push) Successful in 1m44s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 7s

printeditemfiles lands as the plugin's first incremental migration
(0002 on the plugin chain - the ADR-008 payoff). Revisions are
append-only per item: upload assigns the next number, records the
uploader from the JWT, enforces an extension allowlist and a 100 MB
cap; download serves the original filename; a permission-gated delete
covers wrong-file mistakes. The detail page gains the revision table
with a current badge. Unique storedfilename is sized 191 so the index
fits MySQL's 767-byte prefix - the per-plugin chain does not apply the
core env's ROW_FORMAT hook.

Alert recipients gain roles: Role joins the 0.13.0 surface, a role
picker on the settings page, and every active member of the selected
roles is folded into the deduped recipient list.
This commit is contained in:
cproudlock
2026-07-17 08:47:41 -04:00
parent 26b6b6b32f
commit aa4bfcd41c
14 changed files with 479 additions and 11 deletions

View File

@@ -479,8 +479,8 @@ What `shopdb.api` exposes:
- Import mode: `apply_import_timestamps`, `import_mode_active`,
`parse_import_datetime`
- Legacy employee directory: `employee_connection`
- `User` (0.13.0) - the account model, e.g. resolving alert recipients'
emails from selected user ids
- `User` / `Role` (0.13.0) - the account and role models, e.g. resolving
alert recipients' emails from selected user ids or role membership
- Mailer (0.12.0): `send_email(to, subject, html, text=None)` and
`send_alert(subject, html, text=None)` - settings-first, no-op safe when
email is unconfigured; send_alert targets the site's alert_recipients

View File

@@ -347,6 +347,30 @@ the site wanted `WJRP0042`, not `WJRP-0042`.
2. Minting drops the dash: `f'{prefix}{id:04d}'`. Existing items keep their
codes - itemcode is an immutable label once printed on a bin.
## Stage 15 (extension) - print-file revisions + role-based alerts
Two more field requests, and the plugin's FIRST incremental migration:
1. `printeditemfiles` (append-only revisions of the STL/3MF/gcode per item)
arrives as `0002_printeditemfiles` on top of the 0001 baseline - the
ADR-008 payoff: the plugin evolves its own schema, `flask plugin
upgrade-all` applies it, the core chain never hears about it. Update
PLUGIN_TABLE_OWNERS and the guard test's expected head.
Gotchas hit live: (a) MySQL 5.6 dev box - a VARCHAR(255) UNIQUE on
utf8mb4 dies with error 1071 because the per-plugin chain does not apply
the core env's ROW_FORMAT=DYNAMIC hook; size unique columns to 191 or
less (191*4 = 764 bytes fits the 767 prefix). (b) The dev container's
innodb_large_prefix globals reset on restart (documented dev caveat).
2. Upload endpoint assigns revision = max+1, stores
`printeditem-<id>-rev<n><ext>` in `instance/printedpartsfiles/`
(extension allowlist, 100 MB cap), records uploader from the JWT.
Download serves the ORIGINAL filename; delete (permission-gated) exists
for wrong-file mistakes, otherwise history is append-only. Detail page
gains the revision table with a "current" badge on the newest.
3. Role-based alert recipients: `Role` joins the 0.13.0 surface beside User;
Setting `printedparts_alert_roleids`; `_alert_recipients` folds in every
ACTIVE member of each selected role (role.users backref), deduped with
the user picks and free-text; settings page gains a role picker.
---
## Where each pattern lives (cheat sheet)