Skip to content

feat: add Eventbrite admin data layer and show-up prediction API - #47

Open
DJCrossman wants to merge 1 commit into
feat/admin-01-authfrom
feat/admin-02-eventbrite-data
Open

feat: add Eventbrite admin data layer and show-up prediction API#47
DJCrossman wants to merge 1 commit into
feat/admin-01-authfrom
feat/admin-02-eventbrite-data

Conversation

@DJCrossman

Copy link
Copy Markdown
Contributor

Stack 2/4 — stacked on #46 (Slack OAuth). Next: events list UI → event detail UI.

Summary

  • Shared Eventbrite client (fetch/eventbrite.ts): Bearer-header GET with a host allowlist (the token can never be sent off-Eventbrite) and one 429 retry. fetch/events.ts / fetch/createEvent.ts migrate onto it — this removes the existing ?token= query-param auth (token-leak fix); public /api/events behavior is unchanged.
  • Admin fetchers: fetchAdminEvents() / fetchAdminEventById() use expand=ticket_classes,venue → sold/capacity per event, no venue N+1, drafts included. fetchAttendeesForEvent() follows continuation pagination (50/page); draft events 404 → [].
  • Attendance history (fetch/attendanceHistory.ts): per-email {registrations, checkins} from the 25 most recent past events, deduped per (event, email), cancelled/refunded excluded, cached 6h (unstable_cache, tag attendance-history). Events with zero scans are skipped — organizers sometimes don't run check-in, and counting those days would mark everyone a no-show.
  • Prediction (utils/showUpProbability.ts): smoothed personal rate p = (C + 3B)/(R + 3) where B = community base rate, clamped to [5%, 95%]; no-history attendees get B + isNew. lib/attendeeReport.ts composes event + attendees + predictions + summary (expected turnout counts checked-in people as 1.0).
  • API: GET /api/admin/events and GET /api/admin/events/[id]/attendees, both requireAdmin()-guarded (defense in depth behind the proxy), house-style error fallbacks, 404 passthrough.

Verified against the live Eventbrite org

  • 12 upcoming events listed with correct sold/capacity (e.g. Code Together 24/24)
  • History: 20/25 recent events have check-in signal → 334 registrations, 203 check-ins, base rate 61%, 170 people
  • Live event: 24 active attendees, expected turnout 15; spot-checked probabilities match the formula (3/3 regular → 80%, 0/3 → 30%, 2/2 → 76%)
  • bun run lint / bun run build pass; grep -rn 'token=' fetch/ is empty
  • Logged out, /api/admin/events → 401

🤖 Generated with Claude Code

Introduces the server-side data layer for the admin dashboard behind
/api/admin/* (guarded by requireAdmin on top of the proxy):

- fetch/eventbrite.ts: shared Bearer-header GET client (refuses
  non-Eventbrite hosts, one retry on 429). fetch/events.ts and
  fetch/createEvent.ts migrate onto it, removing the token-in-URL
  query params that risked leaking the token into logs.
- fetch/adminEvents.ts: upcoming events with expand=ticket_classes,venue
  for sold/capacity without the venue N+1 (drafts included).
- fetch/attendees.ts: continuation-paginated attendee fetch; drafts 404
  to an empty list.
- fetch/attendanceHistory.ts: per-email registration/check-in stats from
  the 25 most recent past events, cached 6h via unstable_cache. Events
  with zero scans carry no signal and are skipped so unscanned events
  don't mark everyone a no-show (verified against real data: 20/25
  recent events have scans, base rate 61%).
- utils/showUpProbability.ts: smoothed personal rate
  (C + 3B)/(R + 3) clamped to [0.05, 0.95]; first-timers get the base
  rate and isNew.
- lib/attendeeReport.ts: composes event + attendees + history into the
  report used by the API route and (next PR) the detail page; checked-in
  attendees count as 1.0 so expected turnout converges during an event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
website Ready Ready Preview Aug 21, 2026 5:14pm

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