Skip to content

feat(seed): a private hackathon an invitation can actually get you into - #253

Merged
sabinem merged 1 commit into
mainfrom
feat/add-to-seed-for-invite-link
Aug 26, 2026
Merged

feat(seed): a private hackathon an invitation can actually get you into#253
sabinem merged 1 commit into
mainfrom
feat/add-to-seed-for-invite-link

Conversation

@sabinem

@sabinem sabinem commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

As someone testing invitation links, I can now actually follow one.

Before this, I couldn't. The platform had four seeded hackathons and exactly one was private — the Internal Product Sprint, which is deliberately finished with registration switched off. So every time I tried an invitation, the backend said "permission denied" — and it was telling the truth, just about something else entirely: the event was over. There was no way to tell a broken invitation from a closed hackathon, and no way to see what a revoked or expired link does without permanently spoiling the one link there was.

Now there's a fifth hackathon, Partner Data Sprint 2026 — private, starting in twelve days, taking sign-ups. It comes with three invitation links: one that works, one that's been revoked, and one that expired yesterday. The seed prints all three as ready-to-click URLs when it runs, so testing an invitation is a copy-paste instead of a database expedition.

Details:

  • Alice owns it, not the admin. A global admin bypasses permission checks entirely, so testing the organizer's screens as the admin would prove nothing about the permission gate the invite endpoints actually sit behind.
  • Dana joins through the live link during seeding and stays on the waiting list. That means every seed run tests the invitation gate for real — a regression there breaks the seed instead of quietly surfacing later. It also gives the organizer's waitlist someone to approve.
  • Bob and Charles are deliberately not in it, so either is available to redeem a link by hand. Dana can't log in to Keycloak, so she can never be mistaken for the account you're meant to test as.
  • The registration form asks two mandatory questions. That's on purpose: a private hackathon that asked nothing could be joined by posting an empty form, and then the invitation page would only ever need a button.
  • No phases, tracks, projects or pages. This fixture is the door, not the room.

The invite RPCs landed with no fixture exercising them. H3 is the only
private hackathon and it is over with `register` off, so Join refuses
before it ever looks at a token — every attempt to test an invitation
came back PermissionDenied for a reason that had nothing to do with the
invitation.

H5 is private, upcoming and taking sign-ups, so a link is the only way in
and following one gets you somewhere. It carries three invites, one in
each state the API can produce: live, revoked, expired. The last two are
there because neither can reasonably be made by hand — an organizer
cannot backdate an expiry, and revoking is a one-way door — so without
them those refusals could only be seen once, by breaking the fixture.

alice owns it rather than admin. A global admin passes casbin's
g2(r.sub, "admin") escape hatch, so testing the organizer surfaces as
admin proves nothing about the hackathon:write gate all four invite RPCs
sit behind.

dana joins on the live link and stays waitlisted, so every seed run
exercises Join's invite gate for real. bob and charles are left out so
either stays available to redeem a link by hand — that needs an account
that can sign in to Keycloak, which dana cannot.

The tokens print as ready URLs: a token is unguessable by design, and
until the organizer's invitations page exists there is no way to get one
without a detour through ListInvites or Postgres.

No phases, tracks, projects or pages. This fixture is the door, not the
room. It does have a markdown description, because that is the whole of
what PreviewInvite shows an invitee.

Adding a fifth hackathon makes any database holding the previous four
look like a run that died partway, which is fatal by design — so this
needs `just clean::state && just start && just db::seed`.
@sabinem
sabinem merged commit b957d85 into main Aug 26, 2026
2 checks passed
@sabinem
sabinem deleted the feat/add-to-seed-for-invite-link branch August 26, 2026 11:31
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