Skip to content

Fix 11 bugs: security, logic, error handling, and code quality#41

Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1774195110-fix-bugs
Open

Fix 11 bugs: security, logic, error handling, and code quality#41
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1774195110-fix-bugs

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented Mar 22, 2026

Summary

Fixes 11 bugs found during a systematic code review, spanning security issues, logic errors, missing error handling, and code quality problems.

Security (authorization gaps in job mutations):

  • deleteTailoredJob had no authentication or ownership check — added getUser() call and user_id filter
  • deleteJob authenticated the user but did not filter queries by user_id — added user_id filter to both the affected-resumes select and the delete query

Logic / functional fixes:

  • countResumes returned -1 when count was 0 due to || vs ?? — changed to count ?? 0
  • getSubscriptionStatus returned 'Free' (capitalized) in the no-subscription fallback, while the rest of the codebase uses lowercase 'free'
  • testApiKey passed an OpenRouter model ID (deepseek/deepseek-v3.2:nitro) to the OpenAI SDK — replaced with gpt-5-mini-2025-08-07 and reduced max_tokens to 256 for a simple connectivity test
  • Removed empty stub functions in subscriptions/actions.ts that silently returned undefined

Error handling:

  • Cover letter streaming IIFE had no error handling — errors were swallowed and stream.done() never called, leaving clients hanging. Added try/catch with stream.error()
  • Auth callback ignored failed exchangeCodeForSession — now redirects to /auth/login?error=auth_callback_failed

Data integrity:

  • deleteUserAccount deleted profiles and resumes but left orphaned job records — added job deletion step

Code quality:

  • Removed debug console.log statements that leaked user IDs and subscription details to server logs
  • Removed unnecessary void expressions used to suppress lint warnings
  • Cleaned up unused MODEL_DESIGNATIONS import

Review & Testing Checklist for Human

  • Verify deleteUserAccount deletion order doesn't violate FK constraints — jobs are now deleted between profiles and resumes. If there's a foreign key from resumes.job_id → jobs.id, deleting jobs first could fail. Check your DB schema for CASCADE/SET NULL behavior on that FK.
  • Verify stream.error() is a valid method on createStreamableValue — used in the cover letter error handler. If this method doesn't exist in your version of ai/rsc, the catch block would itself throw.
  • Verify the login page handles ?error=auth_callback_failed — the auth callback now redirects there on failure. If the login page doesn't read this param, users will see the login form with no error message (still better than silent redirect, but not ideal).
  • Check if Supabase RLS was already enforcing ownership on the jobs table — if RLS policies filter by auth.uid(), the security bugs in deleteJob/deleteTailoredJob may not have been exploitable in practice, though the server-side checks are still good defense-in-depth.
  • Test the testApiKey function with a real OpenAI API key to confirm gpt-5-mini-2025-08-07 is a valid model ID for your OpenAI account.

Recommended test plan: Exercise the core flows that touch these changes — delete a job, delete a tailored job, generate a cover letter (and interrupt it mid-stream), delete a user account, trigger the auth callback with an invalid code, and call testApiKey from settings.

Notes

  • The testApiKey model is now hardcoded rather than using a constant. This was intentional since MODEL_DESIGNATIONS didn't have a suitable OpenAI-native model designation.
  • The countResumes fallback changed from -1 (null sentinel) to 0 — this is arguably more correct but is a subtle semantic change.

Link to Devin session: https://app.devin.ai/sessions/df6a7139bf3f4945b2043bf89ab4df2e
Requested by: @olyaiy


Open with Devin

Security fixes:
- Add auth check and user_id filter to deleteTailoredJob (was completely unauthenticated)
- Add user_id filter to deleteJob delete/select queries (allowed cross-user deletion)

Functional fixes:
- Remove stub subscription actions that silently returned undefined
- Fix countResumes returning -1 instead of 0 (|| vs ?? operator)
- Add error handling to cover letter streaming IIFE (prevents hanging streams)
- Fix getSubscriptionStatus returning 'Free' (capitalized) instead of 'free'
- Fix testApiKey using OpenRouter model ID with OpenAI SDK (always failed)
- Add job deletion to deleteUserAccount (left orphaned records)
- Handle failed code exchange in auth callback (was silently ignored)

Code quality:
- Remove debug console.log statements leaking user IDs
- Remove unnecessary void expressions
- Clean up unused MODEL_DESIGNATIONS import

Co-Authored-By: Alex Olyaiy <alexolyaiy@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Mar 22, 2026

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

Project Deployment Actions Updated (UTC)
resumelm Error Error Mar 22, 2026 4:05pm

Request Review

Copy link
Copy Markdown
Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

Copy link
Copy Markdown

@JiwaniZakir JiwaniZakir left a comment

Choose a reason for hiding this comment

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

The hardcoded model string 'gpt-5-mini-2025-08-07' in settings/actions.ts is a regression — the MODEL_DESIGNATIONS constant was removed specifically to introduce a magic string, which defeats the purpose of maintaining a central constants file. If this model name needs to change or is wrong (and gpt-5-mini-2025-08-07 doesn't match any currently known OpenAI model identifier), it now has to be tracked down and updated in-place rather than changed in one location.

The countResumes fix in resumes/actions.ts from count || -1 to count ?? 0 is a meaningful correctness fix — the original would return -1 when count is 0 (a valid result), silently misreporting an empty result as an error sentinel.

In jobs/actions.ts, deleteTailoredJob now correctly gates on user_id, but deleteJob still fetches affectedResumes without a corresponding ownership check on the resume update step — only the final delete call has the user_id guard added. If there's downstream logic that acts on affectedResumes, it could still operate on resumes belonging to other users if the RLS policies don't cover it.

The cover-letter/actions.ts change wraps the async IIFE in a try/catch and propagates errors via stream.error(...), but it also removes the onFinish usage tracking callback without any replacement, which may affect observability for token usage monitoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants