Repository navigation
Feature: fix/audit-hardening to dev - #447
Merged
Merged
Conversation
Sync: dev to main
Sync: dev to main
- Withdrawing a project drops its unscored queue slots, and the judge page moves on to the next table when the slot on screen is gone. - assignToHackathon no longer queues a project twice; isJudge rejects a malformed id as 400 instead of a Postgres 500; judge min/max per judge must be whole numbers with max >= min. - The last-super-admin guard also covers deactivation and ending the term, and no longer counts expired super admins. - Terms and semester ends are computed in Eastern time. The last six hours of a semester count as the next one, so renewing a membership stored on the old UTC boundary still buys a full semester. - leaveTeam and disbandTeam lock the team row, serialising with joins. - Chunk-error recovery reloads again after a later deploy; ModalWrapper no longer steals focus when its onClose changes; Hacklytics anchors drop content-visibility so nav taps land on the section.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3f7d4aa. Configure here.
- hackathon_projects gets withdrawn_by_admin_at (additive). An organiser pulling a project before judging left no judging row, so the team could resubmit it straight back into the gallery; submitProject now refuses on the column too. - submitProject bounds name, description and list sizes, and keeps only tracks and challenges the hackathon offers. Unknown values are dropped rather than refused: the form cannot untick a track removed since. - acceptWave locks the hackathon row, so two concurrent waves get different numbers instead of both claiming max + 1. - The metrics term label reads Eastern time, matching currentTerm.
Contributor
Author
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Contributor
Author
|
Visit the preview URL for this PR (updated for commit 0711699): https://hacklytics2027--pr-447-dfcx53hd.web.app (expires Thu, 08 Oct 2026 15:15:45 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c48ba34db61581e25fe2978355160b5eefe0e83f |
A failed getNextTable refetch still resolves with the cached answer, which is the withdrawn table itself, so a network blip put the judge back on the dead card under a message saying they had a new one. An error result, or one naming the same slot, now reports the failure; pressing any card action again retries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

fix: second audit pass on judging, admins, terms and teams
page moves on to the next table when the slot on screen is gone.
malformed id as 400 instead of a Postgres 500; judge min/max per judge
must be whole numbers with max >= min.
term, and no longer counts expired super admins.
hours of a semester count as the next one, so renewing a membership
stored on the old UTC boundary still buys a full semester.
no longer steals focus when its onClose changes; Hacklytics anchors
drop content-visibility so nav taps land on the section.
fix: close remaining audit gaps in submissions, waves and metrics
pulling a project before judging left no judging row, so the team
could resubmit it straight back into the gallery; submitProject now
refuses on the column too.
tracks and challenges the hackathon offers. Unknown values are dropped
rather than refused: the form cannot untick a track removed since.
different numbers instead of both claiming max + 1.
Note
Medium Risk
Changes touch membership billing boundaries, admin privilege invariants, and judging queue deletion during live events—high-impact domains, though mostly defensive guards and additive schema.
Overview
This PR closes several audit gaps around organiser project withdrawal, admin lockout, membership terms, and race-prone team/wave flows, plus small UX and resilience fixes on the web apps.
Judging and withdrawals: When an organiser pulls a project, the API now stamps
withdrawnByAdminAt, marks the judging entry withdrawn, and deletes unscoredjudgeQueuerows so judges are not routed to dead tables. Teams cannot resubmit after an organiser pull (column + legacy judging-row check). The judge portal auto-advances when complete/skip/force-skip hits a withdrawn slot. Judge assignment skips projects already queued and appends with correct order;isJudgerejects malformed UUIDs as 400 before Postgres; bulk assign validates max ≥ min and integer min/max.Super admins: The “last super admin” guard now blocks demotion, deactivation, and setting an already-ended term, counting only non-expired active super admins.
Terms and metrics:
currentTerm,semesterEndDate, and the metrics term label use America/New_York; the last six hours of a semester roll to the next term so renewals (including memberships stored on old UTC boundaries) buy a full semester.Concurrency and validation:
acceptWavelocks the hackathon row for wave numbering;leaveTeam/disbandTeamlock the team row.submitProjectadds field length caps and silently filters tracks/challenges to what the hackathon offers.Frontend: Chunk reload recovery uses a 30s timestamp instead of a one-shot flag;
ModalWrapperstops re-running focus trap whenonCloseidentity changes; Hacklytics dropscontent-visibilityon section anchors so hash nav lands correctly.Reviewed by Cursor Bugbot for commit 0711699. Bugbot is set up for automated code reviews on this repo. Configure here.