Skip to content

#550 Show A Reviewer An Applicant's Other Applications - #591

Open
b-at-neu wants to merge 2 commits into
devfrom
550-show-a-reviewer-an-applicants-other-applications
Open

#550 Show A Reviewer An Applicant's Other Applications#591
b-at-neu wants to merge 2 commits into
devfrom
550-show-a-reviewer-an-applicants-other-applications

Conversation

@b-at-neu

Copy link
Copy Markdown
Collaborator

Closes #550

Summary

  • Adds an "Other applications" section to /applications/[id] so a reviewer can see whether the applicant has applied elsewhere — including on positions the reviewer doesn't manage.
  • This is the app's first deliberate cross-scope read: getApplicantOtherApplications authorizes the caller against the application being viewed first, then intentionally drops position-manager scoping for the second query. Documented as policy in PERMISSIONS.md, not a deviation.

Changes

  • prisma/data/applications.ts — new getApplicantOtherApplications(applicationId, user). Step 1 authorizes the caller against the anchor application with the untouched buildApplicationWhere(user, 'listable'); step 2 fetches the same applicant's other applications with PUBLISHED_POSITION_WHERE (not buildReviewablePositionWhere), then filters with isPositionActive in JS, matching getManagedPositions's pattern.
  • lib/types.ts — new ApplicantOtherApplication row type.
  • lib/utils.ts — new pure canReviewPosition(user, managerIds), the unit-testable half of the row-level link-eligibility rule.
  • components/features/applicant-other-applications.tsx — new server component rendering the section, its rows, and the empty state.
  • app/(main)/(auth)/applications/[id]/page.tsx — mounts the section in its own <Suspense> boundary below the existing answer cards, outside the page's Promise.all so the answers paint first.
  • app/(main)/(auth)/applications/[id]/loading.tsx — matching skeleton.
  • docs/PERMISSIONS.md — new "Cross-scope disclosure" section documenting the policy.
  • docs/WORKFLOWS.md — PM-9 updated with the new section's happy path and empty-state edge case.
  • tests/db/applicant-other-applications.test.ts — the seven db cases from the issue.
  • tests/unit/utils.test.ts — three canReviewPosition cases.

Testing plan

  • As a manager of position A only, open an application from an applicant who also applied to position B (managed by someone else): the section lists B with its real status and applied date, "Not managed by you" instead of a link, and B's title links to /positions/[B].
  • Click that position title → /positions/[B] loads. Confirm no manager name or email appears anywhere in the section (also check page source).
  • As an admin, reload the same application: every row shows "View", and each opens the matching /applications/[id].
  • As a manager of both A and B, confirm the B row shows "View" and opens.
  • Open an application from an applicant who applied nowhere else → empty state copy, subtitle still present.
  • Confirm the application being viewed is never listed in its own section.
  • Give the applicant a draft application on a third position → it does not appear. Withdraw one of their submitted applications → it still appears, badged "Withdrawn".
  • Close a position, resolve (accept/reject) all of its applications, and back-date its closesAt beyond 30 days → that row disappears. Leave one application at applied instead → the row stays.
  • Throttle the network: the answer cards paint first and the section shows its skeleton, with no layout jump when it resolves.
  • Keyboard-only: tab reaches the position title and the "View" link on every row with a visible focus ring; narrow the viewport to ~375px and confirm rows wrap without overflow.
  • A reviewer with no access to the application being viewed gets no list at all (page 404s before the section renders; direct data-function call returns []).

Automated checks

  • npm run prettier:check — pass
  • npm run eslint:check — pass
  • npm run tsc:check — pass
  • npm run test:unit — pass (230/230); tests/db/ requires Postgres, unavailable in this worktree — CI will run it

Notes

  • No manager names or emails are ever selected — the query self-filters the managers relation to only the caller's own id, resolving canOpen server-side.
  • canOpen is a UI affordance, not a permission — /applications/[otherId] still enforces its own scope independently, so a stale canOpen: true 404s rather than leaking anything.
  • No take on the query: Application is unique on [userId, positionId], so rows are bounded by the positions one applicant applied to, further trimmed by isPositionActive.

Adds getApplicantOtherApplications, the app's first intentional
cross-scope read: it authorizes the caller against the anchor
application first, then deliberately drops position-manager scoping
to surface all of that applicant's other applications platform-wide.
Documents the disclosure as policy in PERMISSIONS.md rather than a
deviation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@b-at-neu b-at-neu added the claude Will be worked on by Claude label Aug 24, 2026
@b-at-neu b-at-neu self-assigned this Aug 24, 2026
@vercel

vercel Bot commented Aug 24, 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 24, 2026 10:07pm

@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 24, 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

1 open — 1 🟡 Low (see inline)

Comment thread prisma/data/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 24, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@b-at-neu

Copy link
Copy Markdown
Collaborator Author

Revision — Cycle 1

fixed R1-L1 · 5d83f53

@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 24, 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 · 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 24, 2026
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 claude Will be worked on by Claude

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show A Reviewer An Applicant's Other Applications

1 participant