v0.45.0 — Character Sheet Overhaul: Play Mode for System 8
The overhauled character sheet becomes Play Mode. Production had no working sheet on /play;
this ships one, built from the module's CS-1 schema and CS-2 projections rather than from system
branches. The old Build Mode is retained unchanged for editing — one axis of change per release, so
v0.46.0 takes the Build toggle and the write side.
Main article: Character Sheet Overhaul · task list: todo-v2.md · refactor record: refactor.md · sheet spec: phase-1-character-sheet.md
Module-side work lives in the sibling
vtt-modulesrepo. Deploy order: publish the System 8 and 5e modules before deploying this platform version. Fixture v8 drops the seeded ability-scorerenderFunction, and the platform now ranks a seeded string below a module formatter that would not yet be present — ability scores would render as bare numbers.
The mid-release refactor
The project was refactored partway through,
on two premises. todo-v2.md supersedes todo.md and records which of the 30 already-built tasks
survive, are amended, or are retired.
- [x] D2 — Linked/unlinked replaces divergence. A token is now either linked — a one-way projection of its character — or unlinked and fully independent, replacing the old model where tokens were snapshots that could diverge. R2 retired divergence detection; R3 + N2 replaced the multi-token warning with a linkage indicator.
- [x] D4 — Build mode is a toggle, not tabs. It makes every field editable, replacing per-field hover editing. Per-field extras appear on focus and hide on blur.
- [x] D6 — Token linkage per creation flow, including making the System 8 generator produce unlinked tokens.
- [x] D9/D10/D11 — Re-plan. Every task bucketed by release, nine open questions closed, and the System-Platform Separation rollover items re-bucketed onto the Overhaul's schedule.
Data model (0.1 – 0.13)
- [x] 0.1 / 0.2 — the
attribute_groupsentity and its REST routes. - [x] 0.3 —
attributeGroup+abbreviationon property definitions. - [x] 0.4 / 0.5 — seed attribute groups from system fixtures; the attribute-group backfill script.
- [x] 0.6 / 0.7 —
IPropType's three-axis attribute-type model, and attribute facets in both authoring modes. - [x] 0.8 — roll contribution becomes declarative, and the ability-score literal leaves the roller.
- [x] 0.9 / 0.10 / 0.11 — CS-1.6
formatAttributeand its resolution chain; CS-1.2 numeric attributes consolidated ontoIPropType. - [x] 0.12 — Module API
1.6.0. - [x] 0.13 — the buff-evaluation seam; attribute totals unified.
Sheet primitives (1a)
- [x] 1a.1 – 1a.9 —
<Section>extracted and all nine rewired; the two attribute tiles unified into<StatTile>; the HP/AC/Speed strips collapsed into one;<ActionButtonRow>,<TraitListRow>,<NumericStepper>,<EditableField>and<SheetHeader>extracted; the stock Mantine accents re-pointed onto the retro skin. - [x] 1a.12 — property edits batched across a multi-select.
- [x] Made
apps/web's typecheck actually run — it had been passing vacuously, and immediately surfaced two real type errors plus a missingSectionimport.
The sheet itself (1b)
Sections shipped read-only: metadata, attribute groups with ability and numeric tiles, CS-1.5 derived-stat panels, attacks, powers and feats with inline actions and three grouping modes, other actions, inventory, ledger, notes, options, and the five token sections.
- [x] 1b.1 – 1b.6 — scaffold from the module schema; Metadata; attribute groups; editable ability scores (rolling separated from editing); numeric-attribute edit logic reading HP/AC/Speed from components with a metadata fallback; death saves and the HP danger state.
- [x] An in-app toggle between the classic and new sheets, so "which sheet am I looking at?" stops costing a round-trip. (Retired in v0.47.0.)
- [x] Feature-flag URL overrides resolved at startup.
Security work that was not on the plan
- [x] Condition badges were rendered through
dangerouslySetInnerHTMLat thirteen sites with campaign-authored SVG. Now a CSS mask over a data URL, which removes the sink while keepingcurrentColortheming — a security fix with no visual diff. - [x] Action descriptions were injected raw at six sites, including campaign actions typed
into a plain textarea and shown to every player in the campaign. Now
markedplus DOMPurify, with the Markdown step chosen so wiki HTML still renders. - [x] Both have ratcheting guards.
- [x] Passively-executed campaign code (
renderFunction, barvalueFunction) is sandboxed;ActionExecutor.validateActiondeleted and the action trust boundary stated plainly. - [x] Uploads no longer overwrite each other's stored images, and
uploadImagestops sending served image URLs to the library endpoint.
Module API 1.7.0
- [x] CS-6
projectTokenmust be callable on the server. The audit found no signature change needed — both modules' projections are already synchronous and free of browser globals — so the obligation is packaging, and the remaining work is thatregisterSystemModuleis only called from each module's client entry.
Acceptance
Run by the user against a real System 8 character and a linked token. Seven defects found and fixed, two of them wrong data rather than styling.