Commit graph

12 commits

Author SHA1 Message Date
0e8fe3bb9a 4-digit auto-submit PIN + operator name in audit logs
Login: fixed-length 4-digit PIN that auto-submits on the 4th digit (no submit
button to scroll to on small iPhone screens) and clears on a wrong PIN.
Compact, vertically-centered keypad so it fits without scrolling.

Operator tracking: after PIN auth, staff enter their name (new /operator
screen, persisted per device). The name is sent as X-Operator on every authed
request and recorded on each check-in/undo/ice audit entry (new Operator
column), so logs show who did what. Shown in the scanner header and the admin
audit view.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 16:45:23 +00:00
336d2a5c83 Fix banquet mode ignored on web: use latest onScan in camera loop
The web scanner's camera loop starts once in useEffect and closed over the
mount-time onScan handler, so switching modes (e.g. to Banquet) kept invoking
the original ticket-check-in handler. Route onScan through a ref updated each
render so the loop always calls the current handler. Native was unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 16:31:25 +00:00
3583c2e15f CI: cache Android SDK/NDK, Gradle, and npm across APK builds
Persist three Docker volumes into the build job (android-sdk, gradle home, npm
cache) and enable the Gradle build cache, so repeat builds skip the ~2GB NDK
download, Maven dependency resolution, and unchanged native/Kotlin compilation
— cutting builds from ~1h to a few minutes after the first run.

The runner must whitelist these volumes via config.yaml (container.valid_volumes);
deploy-runner.sh now writes that config, pre-creates the volumes, and starts the
daemon with --config. Requires re-running deploy-runner.sh on the runner host
before the next tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 16:26:06 +00:00
1ca2c38fbf Fix login hang after PIN + enrich Banquet mode
Some checks failed
Build Android APK / build-apk (push) Failing after 57m31s
- 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>
2026-07-08 16:01:41 +00:00
dc39c41428 Fix blank web page: align react and react-dom versions
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>
2026-07-08 05:37:45 +00:00
dbc1ece1ee CI: force IPv4 for Gradle so Maven Central is reachable
Some checks failed
Build Android APK / build-apk (push) Failing after 1h21m22s
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>
2026-07-08 05:04:47 +00:00
b71dce0878 Add /test page with sample QR codes for scanner testing
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>
2026-07-08 04:47:47 +00:00
8d6dd56a1a Add self-contained runner deploy script for remote Ubuntu host
Some checks failed
Build Android APK / build-apk (push) Failing after 15m24s
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>
2026-07-08 04:19:14 +00:00
994aaa88d1 Move APK runner to a separate host; openssl-based keystore
- 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>
2026-07-08 04:16:37 +00:00
d293e53ee6 Add Check-in / Ice / Banquet scan modes
- 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>
2026-07-08 04:07:51 +00:00
b36d63a6a4 Add check-in audit logging + in-app history view
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>
2026-07-08 03:53:30 +00:00
3397e3e3ec Initial Camp Scan ticketing system
Backend (Fastify + TS): FluentForms webhook -> NocoDB row + QR + MailerSend
email; PIN auth; scan/lookup/redeem with per-code serialization; reusable QR
codes with count-based check-in; admin search.

App (Expo, one codebase): Android APK + iPhone PWA. Login, camera scanner
(native + web barcode-detector split), green/red overlay with sound + haptics,
admin lookup/redeem. Session token persisted per device.

Ops: multi-stage Dockerfile serving API + PWA same-origin, compose bound to
127.0.0.1; Forgejo Actions runner + tag-triggered signed APK build for Obtainium.
Docs in README.md and INSTALL.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 03:47:59 +00:00