v0.13.0 — Multi-select with bulk actions, record duplication, metric tiles
Lists treated every row alike: changing one field across many records meant opening each record in turn, there was no way to copy an existing record as a starting point, and the dashboard showed widgets but no numbers. This release adds three user-facing capabilities to the single-file app and tightens several paths that could quietly let bad data or network references through.
Multi-select with bulk actions (OPEN-19)
- Checkbox per row plus a header checkbox for the visible page (indeterminate state on partial selection), shift-click for range selection, and an "N selected" counter. Selection is deliberately limited to what is visible — bulk changes never reach filtered-out records.
- The action bar offers set enum field value (only when the entity has an enum field) and delete selected with confirmation; from 50 records the count must be typed. Records protected by references are named and kept — the same protection as in the form.
- Bulk actions run through the same
applyActionspipeline as model suggestions: schema rules still apply, records already carrying the target value are skipped, and one pass is exactly one audit-log entry — one Ctrl+Z restores everything. - Fixed en route:
exportCsvwrote resolved reference titles back into the live data block, replacing IDs without an audit entry. It now works on a copy.
Per-record duplication (OPEN-20)
- A copy button in a new action column (row hover/focus) and next to Delete in the form footer. The copy carries the saved values of the original under a new ID with a localized "(Copy)" title suffix; its form opens for editing right away.
- Duplication goes through the normal change path: undo stack (Ctrl+Z removes the copy completely), amber unsaved marking, audit log derives a Create event on next save — nothing touches the file before you save. The attachment budget is enforced before the copy exists.
Metric tiles in the dashboard (OPEN-21)
- An entity can now declare
metricsin the domain; the dashboard renders tiles above the existing widgets:count,sumover a numeric field andavgfixed at two decimals, each optionally with a filter criterion. Clicking a tile jumps to that entity's list. - Purely declarative closed catalog — no
eval, no second validation site, computed locally at render time, nothing written into the embedded data block. Invalid declarations (unknown op, sum over a non-numeric field) are rejected by name in their own tile instead of silently ignored. Without ametricsdeclaration the dashboard is exactly as before.
Behavior changes worth knowing
- Wizard CSV and JSON imports are now validated (OPEN-74). Both paths previously bypassed the schema check shared by form and CSV import. Every incoming record runs through coercion + validation; rejected rows appear by name with line number and rule text. JSON import is atomic — one violation rejects the whole file, unknown keys are rebuilt away rather than merged unchecked. Files that used to slip through may now be refused, deliberately.
- The SVG sanitizer strips
styleattributes entirely and removes<style>elements (OPEN-71). Both could smuggle external CSS or@import url(...)into the output file, breaking the no-runtime-network guarantee. Inline coloring viastyleis lost (documented trade-off); presentation attributes (fill,stroke,stop-color) and internal gradient references keep working. Removed root attributes are reported instead of dropped silently. - Due dates use the local calendar instead of UTC (OPEN-73; also applied to all
examples/*.domain.jsin OPEN-83). Seed offsets, overdue highlighting and days-left were shifted by up to ~12 h depending on timezone; they now key on the local day. - Number cells show a stored
0as0, not the empty placeholder (OPEN-79). - The AI-suggestion deletion path respects reference protection like every other delete (OPEN-70).
Tooling & docs
- CI gates hardened: closed-file verification of
dist/index.html, Pages deployment only after a green build (OPEN-78); smoke suite binds its mock port dynamically so parallel runs don't collide (OPEN-75); drawer-focus flake fixed (OPEN-43); build-prompts emits metric tiles as a prompt section (OPEN-44); PPWR seed record V-103 brought into compliance (OPEN-65). - Docs: mass editing and metric tiles documented across all seven READMEs, screenshots refreshed, inventory numbers corrected against the code — including the i18n key count, verified by parsing
src/i18n.js: 474 keys, en/de complete pairs.
Consciously not included
- Bulk editing of free-text fields, moving records between entities, selection reaching beyond visible/filtered hits.
- Pre-filtering when clicking a metric tile — the jump opens the unfiltered list.
- Multi-record duplication, template catalogs, duplication across entities.
Full changelog: v0.12.0...v0.13.0

