Enhancement: Digital Waivers (WIP)#461
Draft
baltinerdist wants to merge 66 commits into
Draft
Conversation
0d7792d to
ecf121d
Compare
ecf121d to
00cced2
Compare
fdd7a4d to
10b6df9
Compare
- Awards config tab: clear the panel's unsaved-changes flag after a row save/delete, so the false 'Unsaved Changes' nag no longer appears after a successful save. - Kingdom admin modal: add a mousedown gate to the overlay so drag-selecting text in a field (releasing outside it) no longer closes the dialog. (Note: the related Authorization::HasAuthority parent_kingdom_id traversal that lets parent-kingdom officers manage principalities is intentionally excluded from version control by the pre-commit hook, since class.Authorization.php carries a local-only login bypass.) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Folds the standalone Principalities tab into the Parks tab on the Kingdom profile (Kingdomnew): - Below the kingdom's own parks, each child principality is shown with its heraldry, name, and an external-link icon (links to the principality profile). - Tile view: a grouped section per principality with its park tiles; list view: a separate table per principality with its own totals footer. Both respect the existing tile/list toggle. - Full Avg/Wk, Avg/Mo, Total Players, Total Members reuse the existing park_averages_json endpoint per principality (a principality is a kingdom row), via a refactored reusable knFillAverages(). - Kingdom map: principality parks render as steel-blue pins (vs the kingdom's red) with a Kingdom/Principality legend, and the map sidebar shows which principality a park belongs to. Backend: controller.Kingdom.php::profile() builds principality_parks + prinz_map_parks; KnConfig.principalityIds drives the per-principality stat fetches. New CSS is dark-mode aware. Spec: docs/superpowers/specs/2026-06-03-kingdom-principalities-in-parks-tab-design.md Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Authorization::HasAuthority now walks up parent_kingdom_id, so parent-kingdom officers (Monarch/Regent/Prime Minister) hold the same authority over a principality and its parks as over the kingdom itself. Fixes parent-kingdom officers being unable to grant awards to / configure awards for a principality. Strictly parent->child: a top-level kingdom has parent_kingdom_id 0/NULL (stops via valid_id), with no child->sibling leak. Verified live (parent create-officer resolves TRUE for the child principality + parks, FALSE for unrelated kingdoms). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds the hidden ORKremental mini-game (Progress Knight port, Amtgard-themed):
- Route Reports/orkremental -> Reports_orkremental.tpl (controller.Reports.php).
- Hidden entry point: a subtle chevron link in the footer (default.theme), gated on $IsOwnProfile.
- Assets: orkremental/{game.js, classes.js, orkremental.css}.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
A kingdom could tick an award's Title checkbox and save, but on reload it reverted to unchecked. Kingdom::GetAwardList read `ifnull(a.is_title, ka.is_title)` and the global award's is_title column is NOT NULL, so the system value always won and the per-kingdom `ka.is_title` override was never used. - GetAwardList now reads ka.is_title / ka.title_class authoritatively. - create_kingdom_awards now seeds is_title + title_class from the system award (was only kingdom_id, award_id, name) so new kingdoms get correct defaults. - Backfill migration (db-migrations/2026-06-03-kingdomaward-is-title-authoritative.sql) sets existing ka.is_title/title_class from the linked system award, so display is unchanged on deploy and per-kingdom edits now stick. After deploying + running the migration, re-apply any intended Title flags once (previously-saved-but-ignored overrides are reset to the system default by the backfill). Fixes the 'turn Master into a Title -> save -> reload shows it unchecked' report. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Per-kingdom admin toggle 'Include Principality in Statistics' (default off, shown only when a kingdom has child principalities). When on, kingdom-scoped stats, graphs, reports, counts, and the weekly recap fold in active child-principality data via Kingdom::GetStatsKingdomIds (kingdom_id = X -> IN (family)). - New helpers on class.Kingdom: GetChildPrincipalityIds / GetFamilyKingdomIds / StatsIncludesPrincipalities / GetStatsKingdomIds; admin checkbox + (?) tooltip in revised.js; backfill migration + CreateKingdom seed for the config. - Rollup applied across class.Report.php (rosters, awards, recs, units, attendance summary/distinct/monthly, recap, park-attendance explorer, inactive parks, status reconciliation) and controller.Kingdom.php (park_averages_json aggregate, events, Parks count). Per-park LIST methods stay parent-only (principalities keep their separate sections) so only aggregates roll up. - Officer Directory gains a per-principality subsection (model.Reports + controller + Reports_kingdomofficerdirectory.tpl), toggle-gated. - Always-on (NOT toggle-gated): principality parks in the parks dropdown (getparks / GetParks KingdomIds param) and principality members in kingdom-scoped playersearch. - Includes in-file robustness fixes to class.Kingdom: SetKingdomParent cycle guard, GetParks dead is_principality/parent_park_id removal, GetPrincipalities returns an empty success list instead of InvalidParameter. Spec: docs/superpowers/specs/2026-06-03-include-principality-in-statistics-design.md Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- common.php create_officers: remove the dead branch testing the undefined $for_principality (param is $principality_id) that would misattribute officers to the parent kingdom; normal officer seeding is unchanged. - model.Principality.php get_officers/set_officers: call the Principality lib methods (which map PrincipalityId->KingdomId) instead of the Kingdom methods, which were operating on kingdom id 0. - class.Award::LookupAward: guard the find() so a missing row returns an invalid kingdomaward id; class.Player::AddAward rejects a zero/invalid KingdomAwardId before saving, preventing orphaned award grants. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The parent-kingdom authority traversal recursed on parent_kingdom_id with only a valid_id() gate, so a corrupt/cyclic parent (self-parent or A->B->A) could infinite-recurse (500 / stack overflow). Thread a visited-set of kingdom ids plus a depth cap of 10 through HasAuthority so the walk always terminates. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
GetStatsKingdomIds (and its helpers GetChildPrincipalityIds / StatsIncludesPrincipalities) are invoked dozens of times across a single kingdom-scoped report page. The Kingdom lib is a single instance per request, so cache the child-principality list and the stats toggle by kingdom id. This removes redundant DB round-trips — most beneficial for ordinary kingdoms with no principalities, which previously paid a fresh child-lookup query on every call site. Behavior is unchanged. https://claude.ai/code/session_015CrcHpyb4BUfrHpW7GqgVT
Inlining the kingdom's full open-recs list (1k-4k <tr> rows on busy kingdoms) was blocking DOMContentLoaded for 1+ second on initial profile render. Moves the table body into a new partial (Kingdomnew_recommendations_panel.tpl) served by Controller_Kingdom::recommendations_panel($kid) on first tab activation; JS (knLazyLoadRecs) swaps the placeholder in, then re-initialises the DataTable + filter bar idempotently. Net effect on Desert Winds: 3.7MB HTML / 4k inline <tr>s → 134KB / 0 inline rows on first paint, ~28x. Adds cheap COUNT queries (Report::PlayerAwardRecommendationsCount and an inline player COUNT in profile()) so the Players and Recommendations tab badges render their numbers on first paint without waiting for the lazy hydration. Both wrapped in ghettocache (300-600s) so re-renders are free. KingdomAjax::setconfig now does a full memcache->flush() on any successful save. Kingdom::CreateKingdom / SetKingdomParent / WaffleKingdom (activate/deactivate) do the same via a new _flushPrincipalityCaches() helper. Kingdom config and structure changes ripple through too many derived caches (averages, events, recs, recap, officer directory, count badges) to enumerate; these are rare admin actions so the wipe is acceptable. With the lazy load in place, the principality rollup on PlayerAwardRecommendations is restored (originally pulled back to keep the inlined HTML small) along with its matching behavior on the new count method, so the toggle once again affects what shows up in the parent kingdom's Recommendations tab per the branch's spec. Co-Authored-By: Claude Opus 4.7 <[email protected]>
Recommendations panel: adds a Park column (linked to the park profile) between Player and Award so it's easier to tell who's from where — ParkName/ParkId already shipped on each rec, just unused. DataTable's date column index shifted from 4 → 5 to match. Awards admin panel: - Search box above the list filters rows client-side by name / system name / class. Pre-lowered haystack on each <tr>'s dataset so each keystroke is one indexOf per row. - Save button per row now starts disabled, lights up the moment any field in the row is edited, stays disabled after a successful save (clean row), re-enables on a failed save for retry. Existing .kn-admin-tsave:disabled CSS already handles the 50% opacity dim. - Delete confirmation now uses the existing knConfirm() styled modal instead of the browser-native confirm() dialog, matching the rest of the kingdom admin UI. Co-Authored-By: Claude Opus 4.7 <[email protected]>
Principalities: Parks-tab folding + statistics rollup toggle, ORKremental, and awards/auth fixes
Autonomous design for feature/digital-waivers: Kingdom-admin waiver builder (kingdom + park scopes), player submission with drawn/typed signature, officer verification queue and sign-off. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
TDD-driven plan: migration + skeletons (Phase 0) → domain class with 10 tested methods (Phase 1) → AJAX + page controllers (Phase 2) → five templates with shared signature widget (Phase 3) → Kingdomnew/Parknew/ Playernew integration hooks (Phase 4) → QA + PR (Phase 5). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds ork_waiver_template and ork_waiver_signature tables. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Minimal-chrome standalone printable page for a signed waiver. Renders header/body/footer markdown (strip_tags for header/footer to stay visually minimal), signer facts grid, typed-or-drawn signature, and an officer verification block when verified. Auto-triggers window.print() after load. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Add "Edit Waivers" and "Waiver Review Queue" links to the kingdom admin menu dropdown so authorised kingdom admins can reach the builder and review queue from the Kingdomnew profile page. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Load the active park-scope waiver template into $park_info['WaiverActive'] and render a "Sign Park Waiver" CTA card in the sidebar when the template is enabled. Park admins also get a "Waiver Review Queue" link in the admin menu dropdown. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Populate a new $_wv_sidebar data bag on Player/profile for own-profile views and render a Digital Waivers sidebar card listing kingdom- and park-scope active templates with sign/view links. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…ors, custom fields)
…ness, minors, custom responses
…ustom, minors, witness, officer intake
…ness, minors repeater, custom fields
…view() The View extracts controller ->data entries into local scope before including the template, so $this->data['_wv'] resolves to null (View has no data prop). Matches the working pattern already in place on Waiver_sign.tpl. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Amendment 1 against the v1 design spec: extend the waiver builder to cover demographic data (DOB, address, phone, email, preferred name, gender), emergency contact, multi-minor rosters, witness signatures, kingdom-defined custom fields (checkbox/radio/initial/etc.), and officer ID-intake metadata. Hybrid mechanism — first-class columns for searchable data, JSON blob only for per-kingdom boilerplate. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Floating pencil icon appears to the left of the focused markdown textarea (Header / Body / Minor / Footer). Hover shows an instant in-product CSS tooltip with a markdown cheatsheet. No native title attributes. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
On one's own profile, the yellow "Needs Waiver" nameplate badge becomes a
link to /Waiver/sign/kingdom/{kingdom_id}. Other viewers still see a plain
badge (only the player can sign for themselves).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
After ctx.scale(dpr, dpr), drawing with canvas.width/height (physical px) applied the DPR multiplier twice, shifting strokes to roughly 2x the mouse offset on a 1.25x-2x display. Draw in CSS-unit coords (cssW/cssH) captured at init, and apply the same pattern to the read-only wvRenderSignature helper used in review/print. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Link default/style/reports.css and replace the raw h1/intro with the standard rp-root > rp-header (icon + title + kingdom scope chip) and rp-context info strip used by the Reports pages. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds an amber notice above the builder panes acknowledging that use of the optional Digital Waiver module requires kingdom-side due diligence and board approval. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds html[data-theme="dark"] overrides for every waiver template (builder, sign, review, queue, signature widget) and the Parknew sidebar waiver CTA card. Signature canvas keeps a light bg in dark mode so the saved signature PNG remains readable everywhere. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Replaces the four markdown textareas with self-hosted Trix 2.1.15
editors and restructures the cluttered builder into three sub-tabs
per scope (Data Capture, Page Layout, Waiver Body). Side-by-side
live preview is gone; a "View Preview" button now POSTs the form
to a new Waiver/preview/{kingdom_id} route that renders the waiver
end-to-end as a signing player would see it, in a new tab.
Storage swap: ork_waiver_template columns header_markdown/body/
footer/minor renamed to *_html. PreviewMarkdown method/AJAX route
removed; a DOMDocument-based allowlist sanitizer (_sanitize_html)
strips any tag, attribute, or URL scheme outside Trix's expected
output. Sign/review/print templates now emit the stored HTML
directly. The save AJAX endpoint also now forwards MaxMinors,
CustomFieldsJson, and the Requires* flags it was silently dropping.
129 PHP tests pass including new sanitizer coverage. No production
waivers existed, so the migration renames in place rather than
dual-writing.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds a parallel Markdown-authored variant of the waiver builder so
the two authoring UXes can be evaluated side-by-side. Variant A is
the existing Trix WYSIWYG; variant B uses Markdown textareas with a
GitHub-style toolbar (heading, bold, italic, strike, quote, inline
code, link, bulleted + numbered lists) plus Ctrl/Cmd+B/I/K shortcuts.
ork_waiver_template gains a variant enum('a','b') column and a
parallel set of *_markdown columns. The "one active row" rule is now
keyed on (kingdom, scope, variant), so the two variants live
independently. Variant B saves both the raw markdown source AND a
sanitized HTML render (Parsedown safe-mode -> _sanitize_html), so
sign/review/print pages stay variant-agnostic and continue to read
*_html only.
Routes: Waiver/builder/{kid}[/{a|b}] and Waiver/preview/{kid}[/{a|b}]
(defaults to 'a' for backwards compatibility). Each variant page
shows a banner with a one-click link to swap variants. Admin Tasks
in Kingdomnew now exposes two entries: Manage Waivers — Rich Text
and Manage Waivers — Markdown.
129 PHP tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Each toolbar button now visually mirrors the markdown it produces:
H1/H2/H3 render as bolded "H" with descending sizes and a subscript
level; B is a bold serif "B"; I is an italic "I"; S is strikethrough;
quote is a Georgia serif quote glyph; inline code shows "</>" in
monospace; code block shows "{ }" in a pill; link is underlined blue
"link"; bullet/numbered/task lists show their actual list marker; HR
shows an em-dash line.
Adds Heading 1/2/3 (replacing the single ## button), Image, Code
Block (fenced ```), Task list (- [ ] ), and Horizontal Rule. The
Image action prompts for URL like Link does; HR inserts a fenced
"---" paragraph at the cursor.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…version metadata
Adds two officer/admin reports and the schema behind true versioning:
- Waivers Compliance report (Reports/waivers/{Type}&id=): stat cards
(templates, signatures by status, compliance %, in-review backlog) plus a
per-player status table, kingdom/park scope-correct. New WaiverReport domain
class holds all read-only aggregate SQL; model passthroughs bridge to it.
- Waiver Change History report (Reports/waiverhistory/{Type}&id=[&scope=]):
newest-first list of every template version with name, save date, author,
status, and change reason, plus a read-only per-version content View. Kingdom
view gets a Kingdom/Park scope toggle.
- version-metadata migration: adds version_name + change_reason to
ork_waiver_template and backfills existing rows.
- Reports tab links on Kingdomnew/Parknew profiles for both reports.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…audit hardening Core module changes spanning the builder, sign, and officer flows: - Trix is the single standard builder; the Markdown A/B variant is removed (template, variant routing/columns, and a drop-markdown migration). - "Publish New Version" modal on save captures a version name (default "YYYY-MM-DD V1", incrementing V2/V3 same day) and a change summary, pre-filled via WaiverAjax/versionDefaults; first-ever version pre-fills "Initial publication of digital waiver.". New WaiverAjax versionContent endpoint (IDOR-guarded) powers the read-only history View. SaveTemplate stores the version metadata and computes server-authoritative defaults. - Audit hardening: submitSignature/verifySignature now forward the full demographic/witness/minor/custom + ID-intake field sets that the domain expected; SanitizeHtml made public and called consistently (fixes a latent cross-class private call in preview); SaveTemplate transaction wrap; GetQueue uses bound scope + explicit column list; printable/review auth + name resolution; HiDPI signature resize. - House-rule polish: dark-mode coverage, human-readable DOB rendering, Flatpickr date inputs, CSS-class colors, and real data-tip tooltips. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Tracks the SanitizeHtml rename in the existing sanitizer tests and adds domain coverage for true versioning: default name "YYYY-MM-DD V1" with same-day increment, first-version "Initial publication of digital waiver." reason, custom name/reason persistence, and newest-first GetVersionHistory with change reasons and author names. Suite: 147 passed, 0 failed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
e2ced0c to
1516fd3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
End-to-end digital waivers for ORK3:
Architecture
Standard ORK3 three-layer:
system/lib/ork3/class.Waiver.php— domain / yapo DB access (77 unit tests)orkui/model/model.Waiver.php— thin__callpass-through via APIModelorkui/controller/controller.Waiver.php(page) +controller.WaiverAjax.php(JSON)orkui/template/revised-frontend/Waiver_{builder,sign,queue,review,print}.tpl+ sharedWaiver_signature_widget.{inc.php,css.inc,js.inc}Uses existing
Parsedown(safe mode) for markdown. Signatures stored as normalised JSON stroke arrays (drawn) or plain text (typed); no blob storage, no new dependencies.DB migration
db-migrations/2026-04-17-digital-waivers.sql— two new tables:ork_waiver_template(versioned, per-kingdom, per-scope)ork_waiver_signature(snapshotted player fields + signature + officer verification)The legacy
ork_mundane.waiveredflag and existing file-upload waiver path are untouched.Integration hooks
Test plan
./tests/php/run-waiver-tests.sh— 77 passed, 0 faileddocs/superpowers/plans/2026-04-17-digital-waivers.mdfor the full checklist): build → sign → queue → verify → print round-trip in Chromeorkui.css)Notes
docs/superpowers/specs/2026-04-17-digital-waivers-design.md; plan atdocs/superpowers/plans/2026-04-17-digital-waivers.md(both on this branch).🤖 Generated with Claude Code