- Auth: introduce a shared AuthProvider/useAuth so entering the PIN updates
reactive state and the layout's gate navigates immediately (previously it
cached the token check at startup, so login appeared to hang until a manual
refresh). login/scanner now use signIn/signOut.
- Banquet: donor lookup now returns lifetime giving, last-12-months giving
(computed from dated transactions), member/donor status, bear name, and tags.
The banquet result screen shows status badge + lifetime and last-year figures.
Tickets are irrelevant in banquet mode.
- Admin: fix "‹ Scanner" back link wrapping (remove fixed width).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
react resolved to 19.2.7 (via react-native) while react-dom was pinned to
19.2.3, causing React error #527 (version mismatch) and a blank page on web.
Pin both to 19.2.7. Native APK was unaffected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The runner host has no working IPv6 route; Maven Central (AAAA records) was
'Network is unreachable' while IPv4-only CDNs worked. Set
JAVA_TOOL_OPTIONS=-Djava.net.preferIPv4Stack=true so all build JVMs use IPv4.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GET /test (gated by ENABLE_TEST_PAGE) renders scannable QR codes for a set of
personas covering different attributes — solo, family with ice+parking, a real
donor for Banquet mode, ice-only, a pre-exhausted ticket, and an invalid code.
Idempotently seeds them into the current NocoDB table.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
scripts/deploy-runner.sh installs Docker if missing, writes the runner
compose + env, registers against git.mowden.top, and starts the runner —
one command on the roomy server.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- gen-keystore.sh now builds a PKCS12 keystore with openssl (no JDK/keytool),
and signing.gradle declares storeType PKCS12.
- Runner is meant to run on a roomy server (the app host lacks disk for the
Android SDK); added runner/README.md with deployment steps. Removed the
runner that was registered on the app host.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Ice mode: prepaid ice bags (Ice Total / Ice Redeemed columns) redeemed
independently of ticket check-ins; grab all bags at once or some now.
- Banquet mode: donor total (online + offline) looked up by the ticket's
email via the Donors Master List, with a manual email override. New
DonorService + POST /api/banquet.
- Redeem generalized over a resource (tickets|ice); audit records ice actions.
- App gains a mode selector; webhook maps ice_bags (defaults to
ICE_BAGS_DEFAULT when only a boolean ice option is present).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every successful check-in/undo writes a row to the "2026 Ticket Audit Logs"
NocoDB table (timestamp, people, code, action, name, remaining-after).
Non-fatal: audit failures never block a gate check-in. New GET /api/audit
endpoint (global or per-code). Admin panel gains a global "Recent check-ins"
panel and per-ticket history. Audit table is optional via NOCODB_AUDIT_TABLE_ID.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>