Skip to content

Release: Luma check-in gate + Bitrefill submission terms/feedback + editable judging#181

Merged
sacha-l merged 13 commits into
mainfrom
develop
Jun 16, 2026
Merged

Release: Luma check-in gate + Bitrefill submission terms/feedback + editable judging#181
sacha-l merged 13 commits into
mainfrom
develop

Conversation

@sacha-l

@sacha-l sacha-l commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Promotes developmain (prod deploy: Railway + Vercel). First release since #176.

Included

Post-deploy steps (Bitrefill event)

The deploy is inert until configured — the Luma gate stays dormant until both the migration is applied and LUMA_API_KEY + an event id are set.

  1. Apply pending Supabase migrations (in order):
    • 20260614000000_program_assets_bucket.sql
    • 20260614000100_program_submission_feedback_terms.sql
    • 20260614000200_bitrefill_2026_content.sql
    • 20260615000000_program_luma_event.sql
  2. Railway env: set LUMA_API_KEY; leave LUMA_GATE_MODE unset/checked_in (in-person gate); set SUBMIT_TEST_EMAILS to organizers as a safety bypass.
  3. Admin → Bitrefill → Luma guests: paste the event id, Save, Sync now.
  4. Verify: a checked-in email submits, a random email gets 403, the verifying-check-in state shows.

Safety

  • Kill switch: clear the event id → gate reverts to prior CSV/test-email behavior, no redeploy.
  • Gate allows an email from any source (luma_api, CSV luma, manual, SUBMIT_TEST_EMAILS).
  • The checked-in→allowed path can only be fully exercised on event day (check in one test guest).

Verification

428 server tests pass; client build + lint clean on the merged tree.

sacha-l added 13 commits June 14, 2026 13:41
…ver-side

Two issues from the must-sign work (#173):
1. REGRESSION: the client signs award/publish/mark-paid with new SIWS statements
   that were never added to the server's VALID_STATEMENTS allowlist, so the server
   rejected them with 'Invalid statement in SIWS message' — admins couldn't award
   prizes or publish. (Mock tests couldn't catch it: mock mode never hits the real
   server validator.)
2. The per-action signing was too much friction.

New model: sign once to open the admin session (the LOAD ADMIN DATA step mints a
cached bearer), then every action rides it — EXCEPT publishing results, which
keeps a deliberate fresh signature (irreversible + public).

- ProgramJudgingSection: award + mark-paid now use the cached session (getAuth);
  only publish uses a fresh signature (signPublishAction prop, was signWinnerAction).
- m2 confirm-payment (AdminPage M1/M2 handlers + WinnersTable) reverts to the cached
  bearer; removed the signPaymentAction prop.
- siwsUtils: drop the unused mark-paid/award-prize/confirm-payment actions, keep
  publish-results.
- server/api/auth/statements.js: add 'Publish results on Stadium' to VALID_STATEMENTS
  so the one remaining fresh-signed action is accepted. Covered by statements.test.js.

Server suite green (397); client build + lint clean.
fix(judging): relax per-action signing; accept publish statement server-side
…gram page sections

- Admin cover image upload to a new public Supabase Storage bucket
  (program-assets) via an admin-gated POST /programs/:slug/cover-image,
  alongside the existing URL field with a live preview.
- Required submission terms checkbox + "Read terms" modal that preserves
  the in-progress submission; agreement stamped in agreed_to_terms_at.
- Required 6-question feedback form on the submission flow, stored in a new
  program_submissions.feedback JSONB column (server validates structure).
- New markdown content section type (react-markdown + remark-gfm) rendered
  on hackathon pages above Submit; authored the bitrefill-2026 page sections
  in mock + a generated content migration.
…tro copy

- Drop the ·INDEX / LIVE stats section on the landing page and the now-unused
  project-stats fetch + helpers (HomePage only loads programs now).
- Update the program-spaces intro to the new WebZero + Stadium framing.
Replace the CSV guest upload (hackathon programs) with a lazy, on-demand
sync of an event's CHECKED-IN guests from the Luma public API into
program_signups. The submission gate verifies the email against that
synced set, lazily re-syncing on a cache-miss (25s floor) and
distinguishing a transient Luma failure (503, retry) from a definitive
not-checked-in (403). Single-flight + sanity guard (a 0-result/truncated
sweep never overwrites a good cache). Manual single-email add remains as
an event-day fallback. CSV path is untouched for non-hackathon programs.

Server: luma.client.js, luma-sync.service.js, gate wiring, sync + manual
endpoints, luma_event_id + sync-state columns. Client: LumaGuestsSection.
Validated live against the Bitrefill event; 15 new tests.
…e-event dry runs

Lets the gate accept approved registrants before an event starts (nobody
is checked in yet) so the submit flow can be validated end-to-end. Default
stays checked_in. Renames the client/sync seam to fetchEligibleGuests.
…w modal

Two judging-flow tweaks from event prep:

1. Scores are no longer hard-locked on submit. Removed the isSubmitted -> 409
   guard on upsertScore + saveScores so a judge can revise and re-save their own
   scores anytime; the submitted ballot still counts and the leaderboard reflects
   the latest values (leaderboard already counts submitted ballots only, on
   submit — unchanged). Client: score inputs always editable, SAVE BATCH always
   available, the red 'LOCKED' banner becomes a calm 'submitted, you can still
   revise + save' note. claimBatch stays gated after submit (not part of this).

2. Clicking VIDEO opens an in-app review modal (ProjectReviewModal, reusing
   demoUtils embed + the Dialog) with an 'open in new window' button, instead of
   spawning a tab. GITHUB stays a new-tab link (X-Frame-Options blocks framing).

Tests: controller lock tests flipped to assert edit-after-submit succeeds; sim
journey updated likewise; SIMULATION_REPORT regenerated. Server 397 green; client
build + lint clean; stadium-tester 4/4 (video modal opens; edit+re-save after
submit works).
…t reads as progress

The submit POST triggers a server-side Luma sync on a cold cache (~3-4s for
the first/just-checked-in submitter; instant once warm). Relabel the in-flight
button to VERIFYING CHECK-IN and add a reassurance line so the wait doesn't
read as frozen.
…d-page-updates

feat(bitrefill): cover image upload, submission terms + feedback, program page sections
…iew-modal

feat(judging): editable-after-submit scores + in-app video review modal
Resolved SubmitProjectModal conflict: re-applied the verifying-check-in
button label + reassurance line onto #178's restructured submit form
(main form footer, not the terms modal). Verified auto-merged api.ts,
program.controller, program.routes, submission.controller + test keep
BOTH the luma gate and #180's editable-scores logic. 428 server tests +
client build + lint pass.
…tion

feat(luma): verify submissions against Luma guests via API (replaces CSV)
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stadium Ready Ready Preview, Comment Jun 16, 2026 12:05am

@sacha-l sacha-l marked this pull request as ready for review June 16, 2026 00:12
@sacha-l sacha-l merged commit b6e9461 into main Jun 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant