Skip to content

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-modules repo. Deploy order: publish the System 8 and 5e modules before deploying this platform version. Fixture v8 drops the seeded ability-score renderFunction, 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_groups entity and its REST routes.
  • [x] 0.3 — attributeGroup + abbreviation on 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 formatAttribute and its resolution chain; CS-1.2 numeric attributes consolidated onto IPropType.
  • [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 missing Section import.

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 dangerouslySetInnerHTML at thirteen sites with campaign-authored SVG. Now a CSS mask over a data URL, which removes the sink while keeping currentColor theming — 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 marked plus DOMPurify, with the Markdown step chosen so wiki HTML still renders.
  • [x] Both have ratcheting guards.
  • [x] Passively-executed campaign code (renderFunction, bar valueFunction) is sandboxed; ActionExecutor.validateAction deleted and the action trust boundary stated plainly.
  • [x] Uploads no longer overwrite each other's stored images, and uploadImage stops sending served image URLs to the library endpoint.

Module API 1.7.0

  • [x] CS-6 projectToken must 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 that registerSystemModule is 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.