Conversation
Remove superseded docs/HANDOFF.md and docs/session-reports/*, update AGENTS.md to point at docs/handoff/HANDOFF.md (the tree father).
POST /api/public/job-alerts had no rate limit, unlike the sibling
application-submit endpoints — flagged as an open P0 in
docs/SECURITY-AUDIT.md ("Public routes" / rate limiting).
Reuses the existing per-IP fixed-window limiter from
src/lib/rate-limit.ts (same 10/min shape as the application submit
routes). Unauthenticated GET /unsubscribe is token-scoped and left
as-is.
Tests: 3 new cases (under limit, 429+Retry-After over limit,
per-IP isolation). 209/209 pass.
The webhook integration form rendered the bearer-token API key as
type="text" — plaintext on screen during a demo, screen-share, or
over someone's shoulder. Flagged in docs/SECURITY-AUDIT.md
("Webhooks / integrations": mask API keys in UI/logs).
Switched to type="password" with autoComplete="off" (avoids the
browser offering to save/fill it as a login password).
Tests: new render test asserts the input is masked. 207/207 pass.
chore(docs): finish handoff-tree migration cleanup
fix(job-alerts): rate-limit the public subscribe endpoint
fix(integrations): mask the API key input field
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAGENTS.md is updated to reference a new docs/handoff structure, replacing legacy docs/HANDOFF.md and docs/session-reports files which are deleted. IntegrationForm's API key input is changed to a password field with autocomplete disabled, with a new test. The job-alerts POST endpoint gains per-IP rate limiting returning 429 with Retry-After, with new tests. ChangesDocumentation Restructuring
Integration Form Security
Job-Alerts Rate Limiting
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Route as POST /api/public/job-alerts
participant Limiter as RateLimiter
participant Service as subscribe
Client->>Route: POST request
Route->>Limiter: check IP allowance
alt limit exceeded
Limiter-->>Route: not allowed + reset time
Route-->>Client: 429 + Retry-After
else within limit
Limiter-->>Route: allowed
Route->>Route: parse and validate body
Route->>Service: subscribe(email)
Service-->>Route: result
Route-->>Client: 200 response
end
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/app/api/public/job-alerts/route.ts (1)
10-12: 🩺 Stability & Availability | 🔵 TrivialConsider a shared store for production rate limiting and note unbounded Map growth.
Two limitations of the current in-memory limiter to be aware of:
Serverless isolation — each function instance gets its own
countersMap, so the effective limit is multiplied by the number of concurrent instances. The comment acknowledges this, but for production you may want a shared store (e.g., Upstash Redis, Vercel KV) to enforce a true global limit.Unbounded memory —
createRateLimiternever evicts stale entries from itscountersMap. On a public endpoint with many unique IPs, memory grows indefinitely within a single instance. Consider periodic cleanup of expired entries or a TTL-based cache.🤖 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/api/public/job-alerts/route.ts` around lines 10 - 12, The current job-alerts rate limiter uses an in-memory Map via createRateLimiter, which is only per-instance and never evicts expired entries. Update the public/job-alerts route to either switch to a shared production store for true global limiting or clearly gate the in-memory limiter as non-production, and add cleanup/TTL eviction in createRateLimiter so the counters Map cannot grow without bound. Use the jobAlertRateLimiter symbol and the createRateLimiter implementation in src/lib/rate-limit.ts to locate the changes.
🤖 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.
Nitpick comments:
In `@src/app/api/public/job-alerts/route.ts`:
- Around line 10-12: The current job-alerts rate limiter uses an in-memory Map
via createRateLimiter, which is only per-instance and never evicts expired
entries. Update the public/job-alerts route to either switch to a shared
production store for true global limiting or clearly gate the in-memory limiter
as non-production, and add cleanup/TTL eviction in createRateLimiter so the
counters Map cannot grow without bound. Use the jobAlertRateLimiter symbol and
the createRateLimiter implementation in src/lib/rate-limit.ts to locate the
changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ead827e9-c57f-47c1-9679-555e2d424cb5
📒 Files selected for processing (17)
AGENTS.mddocs/HANDOFF.mddocs/session-reports/2026-05-19-docs-review.mddocs/session-reports/2026-05-20-auth-email-notifications-plan.mddocs/session-reports/2026-05-20-handoff-system.mddocs/session-reports/2026-05-20-parsing-ai-engineer-plan.mddocs/session-reports/2026-05-20-parsing-performance-test.mddocs/session-reports/2026-05-20-public-job-readability.mddocs/session-reports/2026-05-20-resend-google-email-templates.mddocs/session-reports/2026-05-26-codex-fixes-notifications-hardening.mddocs/session-reports/2026-05-28-takehome-finish-p0.mddocs/session-reports/2026-06-11-resume-pipeline-oauth-emails.mddocs/session-reports/TEMPLATE.mdsrc/app/(admin)/admin/jobs/[id]/integrations/_components/IntegrationForm.test.tsxsrc/app/(admin)/admin/jobs/[id]/integrations/_components/IntegrationForm.tsxsrc/app/api/public/job-alerts/route.test.tssrc/app/api/public/job-alerts/route.ts
💤 Files with no reviewable changes (12)
- docs/session-reports/2026-05-20-parsing-ai-engineer-plan.md
- docs/session-reports/2026-05-20-auth-email-notifications-plan.md
- docs/session-reports/2026-05-26-codex-fixes-notifications-hardening.md
- docs/session-reports/TEMPLATE.md
- docs/session-reports/2026-06-11-resume-pipeline-oauth-emails.md
- docs/session-reports/2026-05-20-resend-google-email-templates.md
- docs/HANDOFF.md
- docs/session-reports/2026-05-19-docs-review.md
- docs/session-reports/2026-05-28-takehome-finish-p0.md
- docs/session-reports/2026-05-20-parsing-performance-test.md
- docs/session-reports/2026-05-20-handoff-system.md
- docs/session-reports/2026-05-20-public-job-readability.md
Summary by CodeRabbit
New Features
Bug Fixes
Documentation