Skip to content

#347 Validate Position Status, Window, And Deletion In Reopen - #409

Merged
b-at-neu merged 2 commits into
devfrom
347-validate-position-status-window-and-deletion-in-reopen
Aug 12, 2026
Merged

#347 Validate Position Status, Window, And Deletion In Reopen#409
b-at-neu merged 2 commits into
devfrom
347-validate-position-status-window-and-deletion-in-reopen

Conversation

@b-at-neu

Copy link
Copy Markdown
Collaborator

Closes #347

Summary

reopenApplication only checked that the caller owned the application and that its status was withdrawn — it performed no check on the position at all, so a withdrawn application against a soft-deleted, draft, closed, or out-of-window position could be reopened straight into the review queue.

Changes

  • prisma/actions/applications.ts
    • Extracted a non-exported findMissingRequiredAnswers helper (position + required-answer check logic) shared by submitApplication and the rewritten reopenApplication, so the two gates can't drift.
    • Refactored submitApplication to call the helper — same order, same messages, no behavior change.
    • Rewrote reopenApplication to run inside prisma.$transaction: re-reads the application with its position and answers (ownership + source status folded into the where), then gates in order — not found/not withdrawn → position soft-deleted → not accepting (draft/closed/before-open/after-close) → missing required global answers → missing required position answers — before writing applied via a caller-scoped updateMany. submittedAt is left untouched.

No schema change, no UI changes — the existing confirm dialog already toasts a returned { error }.

Testing plan

Set up via the manager UI (create/edit/delete positions) and the applicant UI (apply → withdraw). For each case, press Re-open on /my-applications and confirm.

  • Happy path — open position, in window, all required answers present → toast "Application re-opened", status becomes Applied, the row moves back into the reviewer queue on /applications.
  • Soft-deleted position — manager deletes the position → refusal toast "This position is no longer available."; status stays Withdrawn after refresh.
  • Draft position — manager sets status back to draft → "This position is no longer accepting applications."
  • Closed position — manager sets status to closed → same message.
  • Out of window (past)closesAt set to yesterday, status still open → same message; and same-day closesAt (today) still succeeds (inclusive end-of-day).
  • Out of window (future)opensAt set to tomorrow → same message.
  • New required position question — manager adds a required question after the application was withdrawn → "Answer all required questions on this application before re-opening it."
  • New required global question — admin adds a required global question the applicant hasn't answered → "Answer all required profile questions before re-opening this application."
  • Non-withdrawn / other user's application — reopen is not offered; a second click on an already-reopened row (stale tab) gives "This application can no longer be re-opened."
  • Submit unregressed — a draft with a missing required answer still shows the original submit messages, and a complete draft still submits.
  • npm run prettier:check · npm run eslint:check · npm run tsc:check

Automated checks

  • npm run prettier:check — pass
  • npm run eslint:check — pass
  • npm run tsc:check — pass
  • No test framework exists in this repo; the checklist above is the manual verification matrix.

Notes

  • Gate Application Answer Writes and Submission on Application Status #345 also edits prisma/actions/applications.ts (createOrUpdateApplicationAnswer / submitApplication status gating). This PR only refactors submitApplication's required-answer block into a shared helper and leaves its status scoping alone — expect a rebase touchpoint in submitApplication if Gate Application Answer Writes and Submission on Application Status #345 lands first, resolvable by keeping both sides.
  • The Re-open button is still shown for withdrawn applications on unavailable positions (getMyApplications doesn't select position state). Refusal is server-side with a clear message; hiding/relabelling the button belongs to the Resubmit rework tracked separately, not this fix.

@b-at-neu b-at-neu self-assigned this Aug 11, 2026
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
aplio Ready Ready Preview Aug 12, 2026 1:06pm

@b-at-neu b-at-neu added ready for review PR ready for review agent reviewing Review agent working (in-flight) and removed ready for review PR ready for review agent labels Aug 11, 2026

@b-at-neu b-at-neu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code Review — Cycle 1 · needs revision

3 open — 1 🔴 Critical, 1 🟡 Low, 1 ⚪ Nit

R1-C1 🔴 Critical — the Vercel check is failing: https://vercel.com/sga-operational-affairs-projects/aplio/5YeWuvmRRZSd3wCHKhJnr124XXWa. Fix: resolve the failing deployment before merge.

R1-L1 🟡 Low (preexisting) — submitApplication (

const application = await prisma.application.findUnique({
) still reads-then-writes outside a prisma.$transaction and never checks position.deletedAt, unlike the now-hardened reopenApplication this PR ships. Fix: file a follow-up to bring submitApplication to the same bar (wrap in $transaction, add the deletedAt check).

Comment thread prisma/actions/applications.ts Outdated
@b-at-neu b-at-neu added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed reviewing Review agent working (in-flight) needs revision Review found issues that need fixing labels Aug 11, 2026
@b-at-neu

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 1

fixed R1-N1 · skipped R1-C1 · 8c08784

R1-C1: investigated — this PR only touches prisma/actions/applications.ts (no auth/env code), and sibling PRs #410/#411 (unrelated diffs, opened the same window) fail the Vercel check with the identical instant (0s) failure, while earlier PRs from the same day passed. That points to a platform/account-level issue, not a regression in this diff. vercel inspect/CLI access is deny-listed for pipeline agents, so I can't pull the deploy logs directly. Re-pushed (this commit) to trigger a fresh deployment attempt — it failed again identically, so this isn't transient either; needs a human with Vercel dashboard access.

follow-up: R1-L1 (preexisting) — submitApplication still reads-then-writes outside $transaction and doesn't check position.deletedAt; worth a follow-up ticket to bring it to the same bar as the now-hardened reopenApplication.

@b-at-neu b-at-neu added ready for review PR ready for review agent and removed revising Revise agent working (in-flight) labels Aug 11, 2026
@b-at-neu b-at-neu added reviewing Review agent working (in-flight) and removed ready for review PR ready for review agent labels Aug 11, 2026

@b-at-neu b-at-neu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code Review — Cycle 2 · needs revision

2 open — 1 🔴 Critical, 1 🟡 Low

R2-C1 🔴 Critical — the Vercel required check is still failing: https://vercel.com/sga-operational-affairs-projects/aplio/ASxDszkxrYTKuVmUXHtwD4D1n7Xt. Diagnosed as a Neon preview-branch quota issue unrelated to this diff (now tracked in #412), but the check itself remains red and blocks merge. Fix: resolve the branch quota / land #412, or retry once capacity frees up.

R2-L1 🟡 Low (preexisting) — submitApplication (

const application = await prisma.application.findUnique({
where: { id: parsed.data.applicationId },
) still reads-then-writes outside a prisma.$transaction and never checks position.deletedAt, unlike the now-hardened reopenApplication. Fix: file the follow-up ticket to bring it to parity (or fix it in this PR).

@b-at-neu b-at-neu added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed reviewing Review agent working (in-flight) needs revision Review found issues that need fixing labels Aug 11, 2026
@b-at-neu
b-at-neu force-pushed the 347-validate-position-status-window-and-deletion-in-reopen branch from 8c08784 to 040fd19 Compare August 11, 2026 22:26
@b-at-neu

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 2

skipped R2-C1, R2-L1 · 040fd19

R2-C1: rebased onto latest dev and re-pushed to retry the Vercel check; still fails at the same build step (missing DATABASE_URL_UNPOOLED), confirming the Neon branch-quota diagnosis in #412 rather than anything in this diff. No in-PR code fix exists for this — leaving open pending #412 or freed capacity.

R2-L1: preexisting (submitApplication predates this PR and isn't touched by it) — not fixed here per scope. follow-up: bring submitApplication to parity with the now-transactional, deletedAt-checked reopenApplication (wrap in prisma.$transaction, add a position.deletedAt guard).

@b-at-neu b-at-neu added ready for review PR ready for review agent reviewing Review agent working (in-flight) and removed revising Revise agent working (in-flight) ready for review PR ready for review agent labels Aug 11, 2026

@b-at-neu b-at-neu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code Review — Cycle 3 · needs revision

1 open — 1 🔴 Critical

R3-C1 🔴 Critical — the Vercel check is still failing: https://vercel.com/sga-operational-affairs-projects/aplio/F7MpMPuvb12kjtqkFhSgiGGMQbMj. Same Neon preview-branch quota issue diagnosed in cycles 1-2 (tracked in #412), unrelated to this diff, but it remains red and blocks merge. Fix: land #412 or retry once branch capacity frees up.

@b-at-neu b-at-neu added needs revision Review found issues that need fixing revising Revise agent working (in-flight) and removed reviewing Review agent working (in-flight) needs revision Review found issues that need fixing labels Aug 11, 2026
b-at-neu and others added 2 commits August 12, 2026 09:03
reopenApplication only checked ownership and source status, so a
withdrawn application against a deleted, closed, or draft position
could be reopened straight into the review queue. It now re-reads the
position and required answers inside a transaction, applying the same
gates submitApplication uses, before writing the applied status.

Extracted findMissingRequiredAnswers so submit and reopen share one
required-answer check and can't drift.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reword the reopenApplication comment (R1-N1): it previously claimed
submitApplication uses the same pattern, but only reopenApplication
runs inside a $transaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@b-at-neu
b-at-neu force-pushed the 347-validate-position-status-window-and-deletion-in-reopen branch from 040fd19 to a71d495 Compare August 12, 2026 13:05
@b-at-neu

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 3

fixed R3-C1 · a71d495

R3-C1 was the Neon preview-branch quota flake (tracked in #412), unrelated to this diff. Rebased onto dev and pushed, which retriggered the Vercel deployment; capacity had freed up and it now passes. No code change was needed.

@b-at-neu b-at-neu added ready for review PR ready for review agent reviewing Review agent working (in-flight) and removed revising Revise agent working (in-flight) ready for review PR ready for review agent labels Aug 12, 2026

@b-at-neu b-at-neu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code Review — Cycle 4 · approved

0 open — clean

@b-at-neu b-at-neu added approved Review passed, ready to merge and removed reviewing Review agent working (in-flight) labels Aug 12, 2026
@b-at-neu
b-at-neu merged commit 7023531 into dev Aug 12, 2026
5 checks passed
@b-at-neu
b-at-neu deleted the 347-validate-position-status-window-and-deletion-in-reopen branch August 12, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Review passed, ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate Position Status, Window, and Deletion in Reopen

1 participant