Skip to content

feat: Placement dashboard sharing via unique share links#66

Merged
Venkat-Kolasani merged 6 commits into
mainfrom
feat/placement-dashboard-sharing
Jun 25, 2026
Merged

feat: Placement dashboard sharing via unique share links#66
Venkat-Kolasani merged 6 commits into
mainfrom
feat/placement-dashboard-sharing

Conversation

@Venkat-Kolasani

@Venkat-Kolasani Venkat-Kolasani commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

Implements opt-in placement dashboard sharing with secure, revocable read-only links at /share/:token, covering the full #17 epic and sub-issues.

Also included (follow-up polish):

  • Encrypted recoverable tokens so owners can re-copy active links
  • Per-internship sharing from the Internships tab (single-opportunity snapshots)
  • Richer opportunity fields in public snapshots (description, deadline, application link, rounds)
  • Enterprise-style compact Shared Links UI with aligned table columns

Closes #17
Closes #18
Closes #19
Closes #20
Closes #21
Closes #22

Test plan

  • Apply Supabase migrations: 20260624163000_create_share_links.sql and 20260624171000_add_recoverable_share_tokens.sql
  • Set SHARE_LINK_ENCRYPTION_KEY in backend .env (see .env.example)
  • Dashboard → Shared LinksShare progress → create link with all/specific opportunities
  • Open link in incognito; verify read-only snapshot, passcode gate if enabled
  • Internships tab → share icon on a card → confirm only that internship is shared
  • Copy and Revoke from Shared Links table
  • cd backend && npm test (share-links integration tests)
  • npm test and npm run build (frontend)

Summary by CodeRabbit

  • New Features
    • Added shareable dashboard and internship progress links with configurable fields, expiry (24h/7d/permanent), optional 4-digit passcodes, and a read-only public share experience.
    • Added a public /share/:token page that renders shared opportunities, shows snapshot insights, and supports passcode unlock when required.
    • Added dashboard sharing controls to create, copy, and revoke links.
  • Bug Fixes
    • Improved handling for expired or revoked links (public returns a clear “expired or revoked” state).
    • Share view counts update when opening an active link.
  • Documentation / Tests
    • Documented the sharing flow and verification steps; added integration coverage for share links.

Extends dashboard share links with encrypted re-copy support, richer opportunity snapshots, Share Progress modal, per-internship sharing from the Internships tab, and a compact enterprise-style Shared Links table.
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
future-stack Ready Ready Preview, Comment Jun 24, 2026 6:03pm

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end opportunity sharing: database support for share links, backend routes and crypto helpers, frontend creation/management/public pages, and documentation plus test updates.

Changes

Dashboard Share Links

Layer / File(s) Summary
Schema, constraints, and RLS foundation
supabase/migrations/20260624163000_create_share_links.sql, supabase/migrations/20260624171000_add_recoverable_share_tokens.sql, docs/share-links-migration.sql, README.md
Creates the share_snapshot_type enum and share_links table, adds token/passcode/storage constraints, enables RLS with CRUD policies, adds indexes and the update trigger, and updates the README ERD and migrations table.
Share token, passcode, and snapshot primitives
backend/src/lib/shareLinks.js, backend/.env.example, backend/tests/setup.js, backend/src/validation/share-links-schemas.js, backend/tests/mocks/supabase.js
Adds token generation, hashing, encryption/decryption, passcode hashing and verification, snapshot building, owner/public sanitizers, expiry helpers, environment configuration, request schemas, and the Supabase .in(...) test mock.
Authenticated and public share-link routes
backend/src/app.js, backend/src/routes/share-links.js, backend/src/routes/public-share-links.js, backend/tests/integration/share-links.test.js
Registers authenticated and public route mounts, implements list/create/revoke and public read/passcode verification endpoints, and covers them with integration tests for creation, revocation, public access, and passcode handling.
Share creation, management, and public pages
src/App.js, src/components/opportunities/OpportunityCard.jsx, src/components/opportunities/OpportunityList.jsx, src/components/sharing/ShareProgressModal.jsx, src/components/sharing/ManageSharesPanel.jsx, src/pages/Dashboard.jsx, src/pages/InternshipList.jsx, src/pages/PublicSharePage.jsx, src/services/api.js
Adds the share action button, share creation modal, manage-shares panel, public share page, /share/:token routing, and the share-link API client.
Testing guidance and feature documentation
docs/CODEBASE_GUIDE.md, docs/TESTING.md, docs/share-links.md
Documents the public route, backend endpoints, service mapping, feature doc links, and manual verification steps for share creation, public viewing, passcodes, and revocation.

Sequence Diagram(s)

sequenceDiagram
  participant Owner as Dashboard Owner
  participant ShareModal as ShareProgressModal
  participant API as shareLinkService
  participant Backend as Express /api/share-links
  participant DB as Supabase share_links

  Owner->>ShareModal: submit fields, expiry, passcode
  ShareModal->>API: create({ opportunityIds, fields, expiry, passcode })
  API->>Backend: POST /api/share-links
  Backend->>DB: SELECT opportunities
  DB-->>Backend: opportunity rows
  Backend->>Backend: buildShareSnapshot()
  Backend->>Backend: generateShareToken() + encryptShareToken()
  Backend->>DB: INSERT share_links row
  DB-->>Backend: inserted row
  Backend-->>API: token and share URL
  API-->>ShareModal: created share
Loading
sequenceDiagram
  participant Viewer as Public Viewer
  participant PublicPage as PublicSharePage
  participant API as shareLinkService
  participant Backend as Express /api/public/share-links
  participant DB as Supabase share_links

  Viewer->>PublicPage: open /share/:token
  PublicPage->>API: getPublic(token)
  API->>Backend: GET /api/public/share-links/:token
  Backend->>DB: lookup share_links by token_hash
  DB-->>Backend: share row
  alt passcode required
    Backend-->>API: requiresPasscode
    Viewer->>PublicPage: enter passcode
    PublicPage->>API: verifyPasscode(token, passcode)
    API->>Backend: POST /api/public/share-links/:token/verify
    Backend->>DB: update view_count
    Backend-->>API: public snapshot
  else no passcode
    Backend->>DB: update view_count
    Backend-->>API: public snapshot
  end
  API-->>PublicPage: share data
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 A token was tucked in a shiny little shell,
A dashboard got sharing and did it quite well.
With passcodes and snapshots and views on the rise,
The rabbit hops off with a /share/:token surprise!
Revoked or expired? The page gives a sigh,
Then bounces right back with a friendly goodbye.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the summary and test plan, but it omits required template sections like Type of change, Changes made, screenshots, and checklist. Add the missing template sections and fill in Changes made, Screenshots/recording, and Checklist items such as tests run and issue linkage.
Docstring Coverage ⚠️ Warning Docstring coverage is 3.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the new share-link dashboard feature.
Linked Issues check ✅ Passed The changes cover share-link storage, opt-in modal, public page, manage panel, and optional passcode flow, matching issues #17-22.
Out of Scope Changes check ✅ Passed The extra token encryption, per-internship sharing, richer fields, and compact UI are explicitly called out as follow-up polish, not unrelated scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/placement-dashboard-sharing

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: 11

Caution

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

⚠️ Outside diff range comments (1)
src/App.js (1)

47-56: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Mask public share tokens before analytics tracking.

Line 55 currently sends full /share/<token> to trackPageView(location.pathname), which leaks the share secret into analytics logs. Use the new isPublicSharePage flag to send a redacted path (or skip tracking) for share pages.

Suggested fix
   useEffect(() => {
-    trackPageView(location.pathname);
-  }, [location.pathname]);
+    const analyticsPath = isPublicSharePage ? '/share/:token' : location.pathname;
+    trackPageView(analyticsPath);
+  }, [location.pathname, isPublicSharePage]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/App.js` around lines 47 - 56, The page-view tracking in App.js is sending
the full public share pathname from trackPageView(location.pathname), which
exposes the share token. Update the useEffect that tracks route changes to use
the existing isPublicSharePage flag and either pass a redacted share path or
skip tracking entirely for /share/* routes. Keep the change localized around
isPublicSharePage and trackPageView so the analytics behavior is preserved for
normal routes.
🧹 Nitpick comments (2)
backend/tests/integration/share-links.test.js (1)

119-174: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add coverage for specific opportunity selection.

The create test only covers the “all opportunities” path, so the new .in('id', opportunityIds) branch is untested. Add a case with opportunityIds that asserts the query uses those IDs and the snapshot selection mode is specific.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/integration/share-links.test.js` around lines 119 - 174, The
share-link creation test only covers the default “all opportunities” path, so
the new opportunity-specific branch in the share-link flow is unverified. Add a
test around the share-link creation path that passes opportunityIds, then assert
the opportunities query is filtered with those IDs and the resulting snapshot
records selectionMode as specific. Use the existing share-link test setup and
the share-link creation logic symbols to locate where the .in('id',
opportunityIds) branch is exercised.
supabase/migrations/20260624163000_create_share_links.sql (1)

79-83: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Drop the extra token_hash indexes or make the lookup query use them.

token_hash is already indexed by the UNIQUE constraint on Line 18, and the public lookup shown in backend/src/routes/public-share-links.js:31-46 only filters by token_hash. As written, idx_share_links_token_hash duplicates the constraint-backed index, and idx_share_links_active_token_hash will not be used unless the query also adds is_active = true.

Suggested cleanup
-CREATE INDEX IF NOT EXISTS idx_share_links_token_hash ON share_links(token_hash);
-CREATE INDEX IF NOT EXISTS idx_share_links_active_token_hash
-  ON share_links(token_hash)
-  WHERE is_active = TRUE;
+-- `token_hash` is already indexed by the UNIQUE constraint above.
+-- Keep an extra partial index only if the lookup query also filters by `is_active = TRUE`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260624163000_create_share_links.sql` around lines 79 -
83, The share_links migration currently adds redundant token_hash indexes that
duplicate the UNIQUE constraint-backed index. Update the migration to remove the
extra idx_share_links_token_hash and either drop
idx_share_links_active_token_hash or make the public-share-links lookup in
backend/src/routes/public-share-links.js filter by is_active = true so that
index can be used. Refer to the share_links index definitions in the migration
and the public lookup handler to keep the schema and query aligned.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/app.js`:
- Around line 118-120: The current publicShareLimiter is applied to the entire
/api/public/share-links router, so POST /:token/verify shares the same generous
limit as public reads. Keep publicShareLimiter for GET /:token, but add a
separate stricter rate limiter for the verification flow in the public
share-links router, ideally keyed by token plus client IP, and apply it only to
the verify handler so passcode guessing is slowed down without affecting read
traffic.

In `@backend/src/lib/shareLinks.js`:
- Around line 133-177: normalizeFieldOptions() is incorrectly tying
rejectedRound to rounds, and toPublicOpportunity() only gates both round fields
behind fields.rounds. Update normalizeFieldOptions() so rounds and rejectedRound
are tracked independently, then adjust toPublicOpportunity() to use separate
checks so currentRoundNumber follows rounds while rejectedRoundNumber follows
rejectedRound, matching the share-links schema flags.

In `@backend/src/routes/public-share-links.js`:
- Around line 48-52: Update the view count logic in incrementViewCount so it
uses an atomic database operation on share_links instead of reading
share.view_count and writing back a computed value, and make the function return
the persisted row from Supabase. Adjust the caller(s) that currently rely on a
locally synthesized count so they consume the updated row returned by
incrementViewCount rather than assuming the increment succeeded. Use the
incrementViewCount helper and the share_links update path to locate the fix.
- Around line 76-92: The public share flow in findShareByToken,
incrementViewCount, and sendPublicShare still has a revoke/expiry TOCTOU window
because it authorizes on one read and serves on a later step. Update the
handlers so the final response is gated by a single conditional database
operation that only succeeds if the share is still active and unexpired, and
only send the returned row from that operation. Apply the same pattern to both
the normal public-share path and the passcode path so revocation/expiration is
checked at the moment of serving, not just during the initial lookup.

In `@backend/src/routes/share-links.js`:
- Around line 58-62: The owner share list query in the share-links route is
returning revoked rows because it only filters by user_id; update the Supabase
query in the owner-list handler to also require active shares by filtering on
is_active so only currently active links are returned. Keep the change scoped to
the existing share_links select flow that uses OWNER_SHARE_FIELDS and
req.auth.internalUserId.
- Around line 87-99: The specific-share path in the share link route currently
builds a snapshot even when some requested opportunity IDs do not resolve, which
allows partial or empty results. Update the handler around the existing
`query.in('id', opportunityIds)` and `buildShareSnapshot` flow to verify that
every ID in `opportunityIds` was returned for the authenticated user before
creating the snapshot. If any requested ID is missing, return a 400 error
instead of continuing; keep the normal behavior only when all requested IDs are
found.

In `@backend/src/validation/share-links-schemas.js`:
- Around line 23-28: The createShareLinkSchema currently allows an empty
opportunityIds array, which can be treated the same as omission by
buildShareSnapshot() and accidentally widen or misclassify the share scope.
Update the Joi validation in createShareLinkSchema so that when opportunityIds
is present it must contain at least one UUID, while still allowing the field to
be omitted entirely. Keep the behavior aligned with buildShareSnapshot() in
shareLinks.js by rejecting empty “specific selection” payloads at the API
boundary.

In `@README.md`:
- Around line 226-236: The SHARE_LINKS ERD is outdated and missing the new
encrypted token and passcode fields, so update the README schema reference to
match the current share_links table definition. Add token_ciphertext, token_iv,
token_auth_tag, and passcode_salt alongside the existing columns, and keep the
SHARE_LINKS block aligned with the create route and migration behavior so the
quick reference reflects the actual schema.

In `@src/components/opportunities/OpportunityCard.jsx`:
- Around line 71-81: The share button inside OpportunityCard is still affected
by the card’s Enter/Space keyboard handler, so keyboard activation can trigger
handleCardClick() or get suppressed on Space. Update the OpportunityCard wrapper
keyboard logic to ignore events originating from the share button (or otherwise
separate the share action from the card-level handler), and ensure the button
itself remains a normal accessible button via onClick/onKey handling without
bubbling into the card action.

In `@src/components/sharing/ManageSharesPanel.jsx`:
- Around line 81-85: The copy-flow in ManageSharesPanel is stacking multiple
timeout callbacks, which causes a previous timer to clear copied state for a
later link. Update the clipboard handler that calls
navigator.clipboard.writeText, setCopiedId, and setTimeout so it cancels any
existing pending timer before scheduling a new one, ideally by storing the
timeout id in a ref and clearing it first. This keeps the “Copied” state aligned
with the most recent share row.

In `@src/pages/PublicSharePage.jsx`:
- Around line 33-40: The date handling in PublicSharePage is timezone-shifting
date-only values because formatDate and the deadline-state logic are using new
Date(...) on YYYY-MM-DD strings, which can move the day for some viewers. Update
the date parsing/display path to treat date-only values as plain local dates
(not UTC timestamps) and make sure the deadline comparison logic uses the same
normalized date representation. Use the existing formatDate helper and the
deadline-state code near the other date parsing to keep both display and math
consistent.

---

Outside diff comments:
In `@src/App.js`:
- Around line 47-56: The page-view tracking in App.js is sending the full public
share pathname from trackPageView(location.pathname), which exposes the share
token. Update the useEffect that tracks route changes to use the existing
isPublicSharePage flag and either pass a redacted share path or skip tracking
entirely for /share/* routes. Keep the change localized around isPublicSharePage
and trackPageView so the analytics behavior is preserved for normal routes.

---

Nitpick comments:
In `@backend/tests/integration/share-links.test.js`:
- Around line 119-174: The share-link creation test only covers the default “all
opportunities” path, so the new opportunity-specific branch in the share-link
flow is unverified. Add a test around the share-link creation path that passes
opportunityIds, then assert the opportunities query is filtered with those IDs
and the resulting snapshot records selectionMode as specific. Use the existing
share-link test setup and the share-link creation logic symbols to locate where
the .in('id', opportunityIds) branch is exercised.

In `@supabase/migrations/20260624163000_create_share_links.sql`:
- Around line 79-83: The share_links migration currently adds redundant
token_hash indexes that duplicate the UNIQUE constraint-backed index. Update the
migration to remove the extra idx_share_links_token_hash and either drop
idx_share_links_active_token_hash or make the public-share-links lookup in
backend/src/routes/public-share-links.js filter by is_active = true so that
index can be used. Refer to the share_links index definitions in the migration
and the public lookup handler to keep the schema and query aligned.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 99fa3f26-e029-4b93-a287-a9dd228b9075

📥 Commits

Reviewing files that changed from the base of the PR and between 8556f42 and 0541588.

📒 Files selected for processing (25)
  • README.md
  • backend/.env.example
  • backend/src/app.js
  • backend/src/lib/shareLinks.js
  • backend/src/routes/public-share-links.js
  • backend/src/routes/share-links.js
  • backend/src/validation/share-links-schemas.js
  • backend/tests/integration/share-links.test.js
  • backend/tests/mocks/supabase.js
  • backend/tests/setup.js
  • docs/CODEBASE_GUIDE.md
  • docs/TESTING.md
  • docs/share-links-migration.sql
  • docs/share-links.md
  • src/App.js
  • src/components/opportunities/OpportunityCard.jsx
  • src/components/opportunities/OpportunityList.jsx
  • src/components/sharing/ManageSharesPanel.jsx
  • src/components/sharing/ShareProgressModal.jsx
  • src/pages/Dashboard.jsx
  • src/pages/InternshipList.jsx
  • src/pages/PublicSharePage.jsx
  • src/services/api.js
  • supabase/migrations/20260624163000_create_share_links.sql
  • supabase/migrations/20260624171000_add_recoverable_share_tokens.sql

Comment thread backend/src/app.js Outdated
Comment thread backend/src/lib/shareLinks.js
Comment thread backend/src/routes/public-share-links.js Outdated
Comment thread backend/src/routes/public-share-links.js Outdated
Comment thread backend/src/routes/share-links.js
Comment thread backend/src/validation/share-links-schemas.js
Comment thread README.md
Comment thread src/components/opportunities/OpportunityCard.jsx Outdated
Comment thread src/components/sharing/ManageSharesPanel.jsx Outdated
Comment thread src/pages/PublicSharePage.jsx Outdated
Repository owner deleted a comment from coderabbitai Bot Jun 24, 2026
Add atomic serve RPC, stricter passcode rate limits, independent round field toggles, active-only owner listing, opportunity ID validation, and small frontend fixes for analytics redaction, date parsing, keyboard share access, and copy state.
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":404,"request":{"method":"PATCH","url":"https://api.github.com/repos/Venkat-Kolasani/FutureStack/issues/comments/4792191287","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: autofix status by CodeRabbit -->\n> [!NOTE]\n> Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.\n\n⚠️ **Branch updated during autofix.**\n\nThe branch was updated while autofix was in progress. Please try again.\n<!-- autofix-run-id: 4ae99503-aa4b-4ea5-bb5a-79f22f66db0b -->"},"request":{"signal":{}}},"response":{"url":"https://api.github.com/repos/Venkat-Kolasani/FutureStack/issues/comments/4792191287","status":404,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset, Warning","content-encoding":"gzip","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Wed, 24 Jun 2026 18:09:12 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","transfer-encoding":"chunked","vary":"Accept-Encoding, Accept, X-Requested-With","x-accepted-github-permissions":"issues=write; pull_requests=write","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-api-version-selected":"2022-11-28","x-github-media-type":"github.v3; format=json","x-github-request-id":"28D0:3CEA7D:58C193:1453637:6A3C1D47","x-ratelimit-limit":"8150","x-ratelimit-remaining":"8062","x-ratelimit-reset":"1782326456","x-ratelimit-resource":"core","x-ratelimit-used":"88","x-xss-protection":"0"},"data":{"message":"Not Found","documentation_url":"https://docs.github.com/rest/issues/comments#update-an-issue-comment","status":"404"}}}

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/routes/public-share-links.js`:
- Around line 34-40: The rate limiter key in publicShareVerifyLimiter should be
normalized so IPv6 subnet masking is preserved and bearer tokens are not stored
in limiter state. Update the keyGenerator in
backend/src/routes/public-share-links.js to use ipKeyGenerator(req.ip) for the
IP part, and hash the req.params.token before combining it into the key. Keep
the change localized to publicShareVerifyLimiter and its keyGenerator logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8e53b973-1a89-49d3-89dc-550be2229c86

📥 Commits

Reviewing files that changed from the base of the PR and between 0541588 and 9e21d02.

📒 Files selected for processing (14)
  • README.md
  • backend/src/app.js
  • backend/src/lib/shareLinks.js
  • backend/src/routes/public-share-links.js
  • backend/src/routes/share-links.js
  • backend/src/validation/share-links-schemas.js
  • backend/tests/integration/share-links.test.js
  • docs/share-links-migration.sql
  • src/App.js
  • src/components/opportunities/OpportunityCard.jsx
  • src/components/sharing/ManageSharesPanel.jsx
  • src/pages/PublicSharePage.jsx
  • supabase/migrations/20260624163000_create_share_links.sql
  • supabase/migrations/20260624180000_share_links_serve_rpc.sql
💤 Files with no reviewable changes (2)
  • supabase/migrations/20260624163000_create_share_links.sql
  • docs/share-links-migration.sql
✅ Files skipped from review due to trivial changes (2)
  • supabase/migrations/20260624180000_share_links_serve_rpc.sql
  • README.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/App.js
  • backend/src/validation/share-links-schemas.js
  • src/components/sharing/ManageSharesPanel.jsx
  • backend/src/routes/share-links.js
  • backend/src/lib/shareLinks.js
  • backend/tests/integration/share-links.test.js
  • src/components/opportunities/OpportunityCard.jsx

Comment thread backend/src/routes/public-share-links.js
@Venkat-Kolasani Venkat-Kolasani merged commit 7c73a09 into main Jun 25, 2026
8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 25, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant