Skip to content

Add project claims and personal hacker judging itineraries - #560

Merged
DVidal1205 merged 5 commits into
mainfrom
blade/project-claims
Sep 12, 2026
Merged

Add project claims and personal hacker judging itineraries#560
DVidal1205 merged 5 commits into
mainfrom
blade/project-claims

Conversation

@DVidal1205

@DVidal1205 DVidal1205 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Why

Hackers need judging directions for their own project without exposing room assignments for other teams. Devpost emails differ from hacker profile emails, so ownership starts with an emailed claim link.

What

Closes: #559

  • Add single-use member selection and teammate invitations, with check-in required and four shared roster slots. Claims lock replacement imports and add linked Discord contacts for officers.
  • Add event-scoped Hacker SDK/API access and a KHIX judging tab with personal appointments, child challenges, unscheduled itinerary cards, anonymous completed rubric scores/feedback in themed dialogs, and solid red missed-appointment warnings after server verification. Normal navigation stays locked until check-in and initial email delivery; published emergency access survives delivery failure.
  • Add Blade claim delivery/recovery in five-recipient batches that continue past failures and separate schedule publication and emergency-search controls. Emergency mode hides all feedback and restores personal access when disabled.
  • Add a generic Knight Hacks claim email; both requested previews were delivered and inspected in Zoho.

Migration 0054 is additive. Apply it before deploying consumers; retain claim records and the first-claim import lock on rollback. No environment-variable or dependency additions. No automatic disqualification, rescheduling promises, token rotation/revocation, or claim-correction workflow.

Test Plan

  • pnpm verify:precommit: passed (React analysis, formatting, lint, monorepo typecheck).
  • API full suite: 122 files / 951 tests passed, including 9 independent claim integration tests.
  • Database 157, validators 318, Hacker SDK 31, email 86, Blade project UI 64, and KHIX 14 tests passed.
  • Disposable-database migration, event/check-in isolation, concurrent claims, four-slot invites, cross-member link recovery, import protection, and anonymous feedback checks passed.
  • Real local browser flows passed: direct claim, invite, publication, emergency privacy and restoration without reload, missed dialogs, check-in gate, mobile overflow down to 320px, failed final-poll handling, and continuation after five permanently failed recipients.
  • Standard Forge review: three scope reviewers; five rounds including CodeRabbit adjudication and final review. Concrete findings fixed; scope-conflicting suggestions are explained in review replies.

Visual evidence

23 updated screenshots with synthetic data. Screenshot discussion.

Blade claims and publication state blade-claims
Blade publication dialog blade-publication-dialog
Blade emergency search dialog blade-emergency-dialog
Blade email confirmation blade-send-dialog
Blade linked profiles and recipient delivery blade-linked-contacts
Blade recipient table on mobile blade-claims-mobile
KHIX project member selection khix-claim
KHIX claimed project before publication khix-claimed-unpublished
KHIX invitation dialog khix-invite-dialog
KHIX invitation dialog on mobile khix-invite-dialog-mobile
KHIX invitation dialog at 320px khix-invite-dialog-320
KHIX project itinerary khix-itinerary-feedback
KHIX mobile itinerary and unscheduled card khix-itinerary-mobile
KHIX completed judging feedback khix-feedback-dialog
KHIX feedback dialog on mobile khix-feedback-dialog-mobile
KHIX missed appointment dialog khix-missed-dialog
KHIX missed dialog on mobile khix-missed-dialog-mobile
KHIX emergency project search khix-emergency-search
KHIX emergency search on mobile khix-emergency-mobile
KHIX locked before check-in khix-checkin-required
KHIX locked before initial email delivery khix-no-emails-locked
Knight Hacks project-claim email claim-email
Knight Hacks email on mobile claim-email-mobile

Co-authored-by: Codex <codex@openai.com>
@DVidal1205 DVidal1205 added Major Big change - 2+ reviewers required Blade Change modifies code in Blade app Hack Sites Change modifies code in a Hackathon app (ex. 2025) Database Change modifies code in the DB package API Change modifies code in the global API/tRPC package labels Sep 11, 2026
@DVidal1205 DVidal1205 self-assigned this Sep 11, 2026
@DVidal1205

Copy link
Copy Markdown
Contributor Author

Refined the mobile recipient table so contact columns retain a readable width inside the scroll region. Verified at 390px.

blade-claims-mobile

Co-authored-by: Codex <codex@openai.com>
@DVidal1205

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Co-authored-by: Codex <codex@openai.com>
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 8 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: QUIET

Plan: Advanced

Run ID: 8fa109fb-9510-4d61-9295-a5a8e53cf44d

📥 Commits

Reviewing files that changed from the base of the PR and between 3e4e7f3 and b9d78ec.

📒 Files selected for processing (26)
  • .forge/features/project-claims/spec.md
  • .forge/features/project-claims/srd.md
  • .forge/features/project-claims/status.md
  • .forge/features/project-claims/test-cases.md
  • apps/2026/src/app/(portal)/_components/hacker-judging.module.css
  • apps/2026/src/app/(portal)/_components/hacker-judging.tsx
  • apps/2026/src/app/(portal)/_components/khix-dashboard.tsx
  • apps/blade/src/app/_components/judging/project-claims-panel.tsx
  • apps/blade/src/tests/projects/project-claims-panel.test.tsx
  • packages/api/src/hacker-portal/router.ts
  • packages/api/src/routers/project-claims.ts
  • packages/api/src/routers/projects.ts
  • packages/api/src/tests/integration/project-claims.test.ts
  • packages/api/src/utils/audit/coverage.ts
  • packages/api/src/utils/project-claims/claims.ts
  • packages/api/src/utils/project-claims/itinerary.ts
  • packages/db/scripts/dev-db-backup-sanitizer.ts
  • packages/db/src/tests/migration-lineage.test.ts
  • packages/email/src/index.ts
  • packages/email/src/project-claim.ts
  • packages/email/src/tests/project-claim.test.ts
  • packages/hacker-sdk/README.md
  • packages/hacker-sdk/src/react.tsx
  • packages/validators/src/audit.ts
  • packages/validators/src/project-claims.ts
  • packages/validators/src/tests/hacker-portal.test.ts
📝 Walkthrough

Walkthrough

Adds a complete project-claims workflow for checked-in hackers. The change adds claim links, invitations, roster limits, organizer recovery, emergency lookup, personal judging itineraries, feedback visibility, SDK procedures, portal UI, database migration, email delivery, audit coverage, and tests across API, SDK, Blade, and KHIX.

Priority: ➖ Normal

Merge Risk: 🟠 High · up to 3e4e7

The current implementation can hide claimed teams and feedback, leave claim state inconsistent after project deletion, expose participant status through invitations, and make claim delivery unreliable. These issues should be resolved before merge.

🚥 Pre-merge checks | ✅ 5 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Issue #559 requires automated coverage for claim concurrency and access behavior, emergency/publication privacy, feedback, invitations, and import restrictions. The added `packages/api/src/tests/integ… Unskip packages/api/src/tests/integration/project-claims.test.ts and make its database, concurrency, access, publication, feedback, invitation, and import tests execute successfully in the automated test suite.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.88% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 41 functions across 33 files. (7 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ⚠️ Warning The title describes the project-claims and hacker-judging changes and is under 72 characters, but it does not start with an issue number in brackets. Change the title to start with the issue key, for example: "[#559] Add project claims and personal hacker judging itineraries".
✅ Passed checks (5 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The changes stay within Issue #559. The portal, Blade administration, API, SDK, validators, database migration, email template, roster/import protections, Discord contacts, and related tests all suppo…
No Hardcoded Secrets ✅ Passed No hardcoded API keys, passwords, or credential-shaped secrets were introduced. Claim tokens use randomBytes(32).toString("hex"), and email URLs come from runtime input. The token-like test URLs use…
Validated Env Access ✅ Passed No changed file contains direct process.env usage. Added diff lines also contain no process.env access, and structural searches across all changed TypeScript/JavaScript files found no matches.
No Typescript Escape Hatches ✅ Passed No changed TypeScript code uses the any type, @ts-ignore, @ts-expect-error, or non-null assertions. The only added any matches occur in prose and test descriptions.
Description check ✅ Passed The description directly explains the project-claims workflow, personal judging itineraries, implementation scope, and validation for the changeset.
Full details: Linked Issues check

Explanation

Issue #559 requires automated coverage for claim concurrency and access behavior, emergency/publication privacy, feedback, invitations, and import restrictions. The added packages/api/src/tests/integration/project-claims.test.ts suite is marked skipped, so the summary does not establish that these integration tests execute. Other implementation and contract tests are present, but the skipped suite leaves a concrete validation requirement unmet.

Full details: Docstring Coverage

Explanation

Docstring coverage is 4.88% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 41 functions across 33 files. (7 skipped: 7 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch blade/project-claims

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/api/src/routers/projects.ts (2)

730-730: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject dropAll when any project has claim state.

Before tx.delete(Project), check for ProjectClaim or ProjectClaimLink rows in the hackathon and raise a conflict. ProjectClaim uses onDelete("restrict"), so claims currently make the hard delete fail at the foreign key. Claim links cascade through ProjectMember and are otherwise erased by dropAll.


993-999: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject deletion when claim state exists. Before updating Project.deletedAt, check for ProjectClaim rows and ProjectClaimLink rows through ProjectMember. assertNoProjectReservations checks only JudgingAppointment, so deletion can leave claim state while claimLinkRecord and hackerJudging exclude the deleted project.

🟡 Other comments (2)
apps/blade/src/app/_components/judging/project-claims-panel.tsx-144-144 (1)

144-144: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep table columns usable on narrow screens.

Add a minimum width to the table so the existing scroll container scrolls it. The current four-column table compresses contact and action columns on mobile.

packages/api/src/tests/integration/project-claims.test.ts-133-133 (1)

133-133: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Isolate the project-claims fixtures per test.

The root test script runs the API Vitest suite when canRunDatabaseTests() allows it. TC-007/015/016 expects users[0] to own project, and TC-011 expects projectClaimsStartedAt; both states are created only when TC-001/010/014 calls selectProjectMember. These tests fail when run alone or before that test. Create fresh fixtures per test, and seed claimed state only for tests that require it. Keep first-claim tests on an unclaimed fixture.

🧹 Nitpick comments (2)
packages/api/src/routers/project-claims.ts (1)

206-209: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Record why a delivery failed.

Rejected results are discarded. failed reaches the officer as a bare count, and projectClaimDelivery can reject for distinct reasons: a missing claim URL, an event that already ended, a consumed link, or a provider error. None of these are distinguishable afterwards.

Log result.reason for each rejection.

♻️ Proposed change
         for (const result of results) {
           if (result.status === "fulfilled") sent++;
-          else failed++;
+          else {
+            failed++;
+            console.error("project claim delivery failed", result.reason);
+          }
         }
.forge/features/project-claims/test-cases.md (1)

11-11: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Add separate executable regressions for the remaining SRD invariants.

Cover provider failures that preserve the reserved slot and unused credential, read errors that hide stale itinerary content, guest completion that updates status without exposing guest content, and existing oversized projects that reject claims and invitations. Keep duplicate invitation retries and incoming oversized imports out of this addition because existing tests already cover them.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: QUIET

Plan: Advanced

Run ID: 0ec41dda-c4e4-43aa-83fa-2ef2b6fc600a

📥 Commits

Reviewing files that changed from the base of the PR and between 3cd0aec and 3e4e7f3.

⛔ Files ignored due to path filters (1)
  • packages/api/src/tests/root/__snapshots__/api-surface.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (41)
  • .forge/features/project-claims/spec.md
  • .forge/features/project-claims/srd.md
  • .forge/features/project-claims/status.md
  • .forge/features/project-claims/test-cases.md
  • apps/2026/src/app/(portal)/_components/hacker-judging.module.css
  • apps/2026/src/app/(portal)/_components/hacker-judging.tsx
  • apps/2026/src/app/(portal)/_components/khix-dashboard.tsx
  • apps/2026/src/app/(portal)/dashboard/judging/page.tsx
  • apps/2026/src/lib/hacker-portal.tsx
  • apps/blade/src/app/_components/judging/appointment-move-dialog.tsx
  • apps/blade/src/app/_components/judging/project-claims-panel.tsx
  • apps/blade/src/app/_components/judging/project-command-center.tsx
  • apps/blade/src/app/admin/judging/page.tsx
  • packages/api/src/hacker-portal/router.ts
  • packages/api/src/projects-import.server.ts
  • packages/api/src/routers/judging.ts
  • packages/api/src/routers/project-claims.ts
  • packages/api/src/routers/projects.ts
  • packages/api/src/tests/integration/project-claims.test.ts
  • packages/api/src/tests/projects/devpost-import.test.ts
  • packages/api/src/utils/audit/coverage.ts
  • packages/api/src/utils/judging-schedule/appointments.ts
  • packages/api/src/utils/project-claims/claims.ts
  • packages/api/src/utils/project-claims/itinerary.ts
  • packages/api/src/utils/projects/devpost-import.ts
  • packages/db/drizzle/0054_worried_reptil.sql
  • packages/db/drizzle/meta/0054_snapshot.json
  • packages/db/drizzle/meta/_journal.json
  • packages/db/src/schemas/knight-hacks.ts
  • packages/email/src/index.ts
  • packages/email/src/project-claim.ts
  • packages/email/src/tests/project-claim.test.ts
  • packages/hacker-sdk/src/contracts.ts
  • packages/hacker-sdk/src/react.tsx
  • packages/hacker-sdk/src/tests/contracts.test.ts
  • packages/validators/src/audit.ts
  • packages/validators/src/hacker-portal.ts
  • packages/validators/src/index.ts
  • packages/validators/src/project-claims.ts
  • packages/validators/src/projects.ts
  • packages/validators/src/tests/hacker-portal.test.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread apps/2026/src/app/(portal)/_components/hacker-judging.tsx Outdated
Comment thread apps/2026/src/app/(portal)/_components/hacker-judging.tsx Outdated
Comment thread apps/blade/src/app/_components/judging/project-claims-panel.tsx
Comment thread packages/api/src/routers/project-claims.ts Outdated
Comment thread packages/api/src/routers/project-claims.ts Outdated
Comment thread packages/api/src/utils/project-claims/itinerary.ts Outdated
Comment thread packages/api/src/utils/project-claims/itinerary.ts
Comment thread packages/hacker-sdk/src/react.tsx Outdated
Comment thread packages/validators/src/audit.ts
Comment thread packages/validators/src/projects.ts
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Co-authored-by: Codex <codex@openai.com>
@DVidal1205

Copy link
Copy Markdown
Contributor Author

Updated visual pass after the requested refinements. These 23 captures replace the earlier UI examples. The generic email was delivered and visually inspected in Zoho.

Blade claims and publication state blade-claims
Blade publication dialog blade-publication-dialog
Blade emergency search dialog blade-emergency-dialog
Blade email confirmation blade-send-dialog
Blade linked profiles and recipient delivery blade-linked-contacts
Blade recipient table on mobile blade-claims-mobile
KHIX project member selection khix-claim
KHIX claimed project before publication khix-claimed-unpublished
KHIX invitation dialog khix-invite-dialog
KHIX invitation dialog on mobile khix-invite-dialog-mobile
KHIX invitation dialog at 320px khix-invite-dialog-320
KHIX project itinerary khix-itinerary-feedback
KHIX mobile itinerary and unscheduled card khix-itinerary-mobile
KHIX completed judging feedback khix-feedback-dialog
KHIX feedback dialog on mobile khix-feedback-dialog-mobile
KHIX missed appointment dialog khix-missed-dialog
KHIX missed dialog on mobile khix-missed-dialog-mobile
KHIX emergency project search khix-emergency-search
KHIX emergency search on mobile khix-emergency-mobile
KHIX locked before check-in khix-checkin-required
KHIX locked before initial email delivery khix-no-emails-locked
Knight Hacks project-claim email claim-email
Knight Hacks email on mobile claim-email-mobile

@DVidal1205

Copy link
Copy Markdown
Contributor Author

Addressed the review in f0d52a0. CodeRabbit has acknowledged the fixes and scope decisions and resolved all 12 inline threads.

The grouped findings are covered too:

  • Claimed projects cannot be soft-deleted. Replacement imports already honor the first-claim inventory lock; the error now gives add-only advice. Before the first claim, officers can still deliberately replace an import.
  • Integration cases rebuild their own fixtures and explicitly seed claims. All nine passed, including failed email delivery and oversized-roster link prevention.
  • Provider failures log sanitized error codes, without provider payloads or claim credentials.
  • The mobile table has a minimum width and horizontal scrolling. Its latest screenshot is in the updated gallery.

The MR now includes 23 updated screenshots. The generic claim email was sent to the authorized preview address and visually inspected in Zoho. Local static checks and the affected package suites passed; final CI is running.

Co-authored-by: Codex <codex@openai.com>
@DVidal1205

Copy link
Copy Markdown
Contributor Author

Final verification passed on b9d78ec. CI is green for tests, build, typecheck, lint, formatting, database tests, and fresh/upgrade migration checks. Production migration was skipped as expected for an MR.

CodeRabbit acknowledged the fixes and scope decisions and resolved all 12 review threads. Its subsequent full-review attempt was rate-limited. The 23 updated screenshots and the Zoho-verified generic email cover the requested visual refinements. No merge or deployment performed.

@DGoel1602 DGoel1602 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@DVidal1205
DVidal1205 merged commit 5737bb5 into main Sep 12, 2026
13 checks passed
@DVidal1205
DVidal1205 deleted the blade/project-claims branch September 12, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API Change modifies code in the global API/tRPC package Blade Change modifies code in Blade app Database Change modifies code in the DB package Hack Sites Change modifies code in a Hackathon app (ex. 2025) Major Big change - 2+ reviewers required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add project claims and personal hacker judging itineraries

2 participants