3 Commits
Author SHA1 Message Date
ort 8c7710d981 Add household admin roles: invite gating, promote/demote, removal, passwords
Every household now always has exactly one or more admins. Admins can
invite new members (previously open to any parent -- now gated), promote/
demote other admins, remove parents, and directly set another parent's
password (no email infra exists for a reset-link flow, so this is a
direct admin-sets-the-value action). Every parent can change their own
password with current-password confirmation. A sole admin can't remove
themselves or demote until they promote someone else -- this falls out of
a single "household must have >=1 admin" invariant rather than needing
special-case code.

Schema: parents.is_admin, added via a new idempotent ensureColumn() helper
(SQLite has no ADD COLUMN IF NOT EXISTS, and this needed to run safely
against the already-populated production parents table on next boot, not
just fresh installs). A boot-time backfill promotes the earliest-created
parent in any household with zero admins -- verified against a simulated
copy of the real production schema/data (including the exact "spouse
joined via invite" scenario), confirming correct promotion and clean
idempotency across repeated boots.

Fixed a real foreign-key landmine along the way: household_invites.
used_by_parent_id had no ON DELETE clause, so deleting any parent who'd
ever accepted an invite -- i.e. any spouse, in this app's normal usage --
would have thrown a constraint violation. src/lib/removeParent.js nulls
that reference before deleting, wrapped in an explicit transaction (first
use of manual BEGIN/COMMIT/ROLLBACK in this codebase, verified working
with node:sqlite before relying on it).

Verified extensively: every route's permission/edge cases via curl
(cross-household isolation, sole-admin guards, password round-trips via
real login), and the full UI flow (promote/demote/remove/both password
modals/leave-with-error-toast) across two independent real browser
sessions acting as admin and non-admin simultaneously. Full-app regression
and a Docker build/boot check both pass with the new code in place.
2026-08-15 18:07:52 -04:00
ort 2826a3819c Add Web Push notifications, PWA support, and full-screen tablet kiosk
Parents get a real push notification when a kid checks off a task
(false->true transitions only, fire-and-forget, degrades gracefully with
no VAPID keys configured). Dashboard is a fully installable iOS/Android
PWA; each child's kiosk link gets its own dynamic per-token manifest so
"Add to Home Screen" opens straight into their board in standalone mode.

Kiosk view is reworked for tablets: safe-area-aware full-bleed layout,
the whole task row is now tappable (previously only the 24px checkbox
was, well under Apple's touch-target minimum), and app icons are
generated by a small dependency-free PNG encoder (no image tooling
available in this environment).

Push requires real HTTPS (iOS Safari won't allow it otherwise) - README
and UNRAID.md cover VAPID setup and the HTTPS prerequisite.
2026-08-15 16:14:56 -04:00
ort 66b8fc5d4d Add self-hosted kids calendar app
Express + SQLite (node:sqlite, no native build step) family calendar:
parent accounts with household invites, per-child calendars with
save/duplicate/print, a token-gated read-only kiosk view for tablets,
and polling to keep parent and kiosk views in sync. Defaults to port 3007.
2026-08-15 13:48:01 -04:00