Skip to content

fix: resolve 6 admin bugs with input validation and filter consistency#297

Merged
bd73-com merged 3 commits intomainfrom
claude/fix-github-issues-py3mr
Mar 27, 2026
Merged

fix: resolve 6 admin bugs with input validation and filter consistency#297
bd73-com merged 3 commits intomainfrom
claude/fix-github-issues-py3mr

Conversation

@bd73-com
Copy link
Copy Markdown
Owner

@bd73-com bd73-com commented Mar 27, 2026

Summary

Resolves 6 open bugs (#287, #288, #290, #292, #293, #294) across admin campaign routes, error log endpoints, and the error log filter UI. All fixes are defensive hardening — adding input validation, filter consistency, PII masking, and a missing UI dropdown sync with the shared constant.

Changes

Campaign routes — input validation (#293, #294)

  • Add Number.isInteger(id) || id <= 0 validation to all 7 campaign ID routes (GET, PATCH, DELETE, send-test, send, cancel, analytics), matching the existing reconcile route pattern
  • Return 400 with "No valid fields to update" when PATCH body contains no recognized fields, preventing a Drizzle SQL crash on empty .set({})

Error log endpoints — filter consistency (#288, #292)

  • Add eq(errorLogs.resolved, false) to the list endpoint's WHERE clause so it matches the count endpoint's filter — badge count and displayed entries are now consistent
  • Add isNull(errorLogs.deletedAt) to the single-delete endpoint's SELECT query so already-soft-deleted entries return 404 instead of being re-deleted

Error log UI — dropdown completeness (#290)

  • Replace hardcoded 4-item source filter dropdown with ERROR_LOG_SOURCES.map() from the shared constant in shared/routes.ts, adding the missing stripe, resend, and browserless sources

PII masking (#287)

  • Mask user email in the test-email console.log line (e.g., a****@example.com)
  • Handle edge cases: single-character local parts get at least one asterisk; malformed emails without @ log as [redacted]

Tests

  • 38 new tests covering all 6 bug fixes including edge cases (NaN, negative, zero, float IDs; empty/unknown PATCH fields; email masking for normal, single-char, malformed, and null emails)

How to test

  1. Campaign ID validation: As app owner, send GET /api/admin/campaigns/abc — should return 400 "Invalid campaign ID" (previously returned 500 or inconsistent errors)
  2. Campaign PATCH empty body: Send PATCH /api/admin/campaigns/<id> with {} — should return 400 "No valid fields to update" (previously returned 500)
  3. Error log list filter: With resolved error logs in the DB, verify they no longer appear in GET /api/admin/error-logs (previously they appeared in the list but not the count badge)
  4. Error log re-delete: Soft-delete an entry, then try to delete it again — should return 404 (previously returned 200 and reset the deletedAt timestamp)
  5. Source filter dropdown: Navigate to Admin Errors page, open source filter — should show all 7 sources including Stripe, Resend, Browserless (previously only showed 4)
  6. Email masking: Trigger POST /api/test-email and check server logs — email should be masked as a****@example.com (previously logged in plaintext)

Closes #287, closes #288, closes #290, closes #292, closes #293, closes #294

https://claude.ai/code/session_01V8DMhAGucN6hhELgzR8XUN

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Campaign endpoints now validate numeric IDs and return clear error messages for invalid inputs.
    • Campaign updates are rejected when the request contains no valid fields to modify.
    • Error log deletion now properly handles already-deleted entries, preventing errors.
    • Email addresses are masked in application logs for privacy protection.
    • Error log filtering now correctly identifies unresolved entries.
  • Tests

    • Added comprehensive regression tests for campaign and error-log management routes.

claude added 3 commits March 27, 2026 13:57
- Add NaN/non-positive ID validation to all campaign routes (#294)
- Return 400 on empty PATCH body instead of crashing with 500 (#293)
- Add resolved=false filter to error log list endpoint to match count (#292)
- Derive source filter dropdown from shared ERROR_LOG_SOURCES constant (#290)
- Filter out already-soft-deleted entries in single-delete endpoint (#288)
- Mask user email in test-email log line to avoid PII in logs (#287)

https://claude.ai/code/session_01V8DMhAGucN6hhELgzR8XUN
- Add 37 tests covering all 6 bug fixes (#287-#294)
- Fix email masking to handle single-char local parts (a@x.com → a*@x.com)

https://claude.ai/code/session_01V8DMhAGucN6hhELgzR8XUN
Adds fallback to log '[redacted]' when email lacks an @ sign, preventing
raw PII from leaking to server logs in edge cases.

https://claude.ai/code/session_01V8DMhAGucN6hhELgzR8XUN
@github-actions github-actions bot added the fix label Mar 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b317fc5b-d45e-4dab-b825-bbe0601770be

📥 Commits

Reviewing files that changed from the base of the PR and between b971e98 and 481e0e3.

📒 Files selected for processing (3)
  • client/src/pages/AdminErrors.tsx
  • server/routes.bugfixes.test.ts
  • server/routes.ts

📝 Walkthrough

Walkthrough

This PR fixes six security and correctness bugs across admin error logging and campaign management. Changes include email masking in test logs, strict campaign ID parameter validation, consistent resolved-entry filtering, preventing re-deletion of soft-deleted logs, rejecting empty campaign updates, and comprehensive regression tests for all fixes.

Changes

Cohort / File(s) Summary
Client-side Error Log Filter
client/src/pages/AdminErrors.tsx
Replaced hard-coded error source filter options with dynamic rendering from imported ERROR_LOG_SOURCES constant to ensure dropdown stays synchronized with server-side valid sources.
Bug Fix Regression Tests
server/routes.bugfixes.test.ts
Added 500-line comprehensive test suite with global mocks for all dependencies and regression tests for #287 (email masking), #288 (soft-delete prevention), #292 (resolved filter consistency), #293 (empty update rejection), and #294 (campaign ID validation).
Route Handler Bug Fixes
server/routes.ts
Implemented email masking in test-email logging (#287); added resolved=false filter to error-log list endpoint (#292); enforced deletedAt IS NULL check in error-log deletion (#288); added Number.isInteger(id) && id > 0 validation to six campaign endpoints (#294); added rejection of campaign PATCH with no valid fields (#293).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

The diff spans heterogeneous bug fixes (email masking, ID validation, filtering logic) across multiple sensitive endpoints, plus 500 lines of new test code with multiple mock scenarios requiring careful validation of test coverage completeness. Security-critical paths (ID validation, soft-delete handling, PII masking) warrant extra scrutiny.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: resolving six admin bugs with input validation and filter consistency across campaign routes, error log endpoints, and UI.
Linked Issues check ✅ Passed All objectives from linked issues are fully addressed: PII masking for test-email [#287], no re-soft-delete with isNull check [#288], programmatic source filter from ERROR_LOG_SOURCES [#290], resolved=false filter consistency [#292], PATCH empty body rejection [#293], and integer ID validation across campaign routes [#294].
Out of Scope Changes check ✅ Passed All changes directly address the six linked issues; no unrelated modifications detected beyond the defensive hardening objectives outlined in the PR 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 claude/fix-github-issues-py3mr

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@bd73-com bd73-com merged commit 23ff187 into main Mar 27, 2026
2 checks passed
@github-actions github-actions bot deleted the claude/fix-github-issues-py3mr branch March 27, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment