Skip to content

[codex] Resolve open issues with reliability, analytics, and test hardening - #34

Merged
nickbeau merged 1 commit into
mainfrom
codex/resolve-open-issues-tests
Feb 16, 2026
Merged

nickbeau merged 1 commit into
mainfrom
codex/resolve-open-issues-tests

Conversation

@nickbeau

@nickbeau nickbeau commented Feb 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR resolves all currently open repository issues: #21, #27, #28, #29, #30, #31, and #32.

The previous implementation had four concrete reliability/performance gaps and one release-readiness documentation gap:

  • outbound email dispatch consumed multiple retries in a single worker cycle and duplicated dead-letter transitions,
  • analytics dashboard executed redundant ticket materialization and per-ticket first-response query logic,
  • knowledge-base search treated % and _ as unescaped LIKE wildcards,
  • backup scripting copied a live SQLite file directly instead of using a transactional SQLite backup snapshot,
  • release hardening and known limitations were not documented as a single tracked checklist.

Root Cause and User Impact

Outbound email retry handling used an inner loop that exhausted retry budget immediately under transient provider failures, reducing recovery opportunities between worker cycles and inflating risk of premature dead-lettering. The same method had two dead-letter paths, which could duplicate audit/metric side effects.

Analytics dashboard calculations materialized similar ticket sets multiple times and used a projection pattern for first response that risked inefficient query plans as data volume grows.

Knowledge article search assembled LIKE patterns without escaping user-entered wildcard characters. This produced broad, unintended matches when users searched for literal % or _ characters.

Backup logic performed raw file copy against a potentially active SQLite database. Under concurrent writes, this can produce an inconsistent backup image.

What Changed

1) Outbound email reliability

  • Refactored OutboundEmailService.DispatchPendingAsync to perform exactly one send attempt per message per dispatch run.
  • Consolidated dead-letter transitions into a single helper path (MarkDeadLetter) to prevent duplicate dead-letter events.
  • Preserved send-failure audit recording and terminal dead-lettering when the final allowed attempt fails.

2) Analytics query efficiency

  • Refactored AnalyticsService.GetDashboardAsync to materialize ranged tickets once into a lightweight projection.
  • Reused that projection for total/open/channel calculations.
  • Replaced per-ticket first-response subquery pattern with a grouped ticket-message query and dictionary lookup for first-response timestamps.

3) Knowledge-base search hardening

  • Added LIKE-pattern escaping in KnowledgeBaseService for \\, %, _, and [.
  • Switched search filter to EF.Functions.Like(..., pattern, "\\") so wildcard characters are interpreted literally when escaped.

4) Backup safety

  • Updated scripts/backup-helpdesk.sh to use SQLite snapshot backup:
    • sqlite3 "$DB_PATH" ".backup '$PAYLOAD_DIR/helpdesk.db'"

5) Release hardening documentation

  • Added docs/release-readiness-security.md with:
    • authorization/tenant isolation coverage references,
    • sanitization and attachment safeguards,
    • AI guardrail notes,
    • MVP release checklist,
    • known limitations and mitigation notes.
  • Added README link to the new checklist document.

6) Added regression/unit tests

  • OutboundEmailServiceTests:
    • one-attempt-per-dispatch on failure,
    • single dead-letter transition at terminal failure,
    • no send attempt when retry budget is already exhausted.
  • AnalyticsServiceTests:
    • validates expected volume/open/channel and average first-response output from seeded data.
  • KnowledgeBaseServiceSearchTests:
    • verifies % and _ are treated as literals in search.
  • BackupScriptTests:
    • verifies backup script uses SQLite .backup and no longer uses raw DB cp.

Validation

Executed locally on this branch:

  • dotnet restore Helpdesk.Light.slnx
  • dotnet build Helpdesk.Light.slnx -warnaserror
  • dotnet test Helpdesk.Light.slnx

Results:

  • Build succeeded with 0 Warning(s) and 0 Error(s).
  • Unit tests: 29 passed, 0 failed.
  • Integration tests: 35 passed, 0 failed.

Additional Included Files

This branch also includes the previously untracked GitHub workflow files in .github/workflows/ (ci.yml and release.yml) so the repository state is consistent with the new README CI/CD references.

Closes #21
Closes #27
Closes #28
Closes #29
Closes #30
Closes #31
Closes #32

@nickbeau nickbeau changed the title Resolve open issues and add regression tests [codex] Resolve open issues with reliability, analytics, and test hardening Feb 16, 2026
This was referenced Feb 16, 2026
@nickbeau
nickbeau marked this pull request as ready for review February 16, 2026 22:58
Copilot AI review requested due to automatic review settings February 16, 2026 22:58
@nickbeau
nickbeau merged commit 56074e2 into main Feb 16, 2026
5 checks passed

Copilot AI 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.

Pull request overview

This PR resolves seven open repository issues by addressing reliability gaps in outbound email dispatch, performance issues in analytics queries, security concerns in knowledge-base search, backup integrity risks, and documentation gaps for release readiness.

Changes:

  • Refactored outbound email retry logic to perform one send attempt per dispatch cycle and consolidated duplicate dead-letter transitions into a single code path
  • Optimized analytics dashboard queries by materializing ticket data once and replacing per-ticket subqueries with grouped queries
  • Added LIKE wildcard escaping for knowledge-base search to prevent unintended pattern matching
  • Updated backup script to use SQLite .backup command for transactional consistency
  • Added comprehensive release readiness and security hardening documentation with checklists
  • Included GitHub Actions CI/CD workflow files for automated build, test, and release processes

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Helpdesk.Light.Infrastructure/Services/OutboundEmailService.cs Refactored retry logic to single attempt per cycle with consolidated dead-letter helper
src/Helpdesk.Light.Infrastructure/Services/AnalyticsService.cs Optimized dashboard queries with single materialization and grouped first-response lookup
src/Helpdesk.Light.Infrastructure/Services/KnowledgeBaseService.cs Added LIKE pattern escaping for literal wildcard character handling
scripts/backup-helpdesk.sh Replaced file copy with SQLite .backup command for consistent snapshots
docs/release-readiness-security.md New security hardening checklist with authorization, sanitization, and AI guardrail documentation
README.md Added reference link to release readiness documentation
tests/Helpdesk.Light.UnitTests/OutboundEmailServiceTests.cs New unit tests for single-attempt retry and single dead-letter transition
tests/Helpdesk.Light.UnitTests/AnalyticsServiceTests.cs New unit tests for dashboard metrics calculation
tests/Helpdesk.Light.UnitTests/KnowledgeBaseServiceSearchTests.cs New unit tests for literal wildcard character handling
tests/Helpdesk.Light.UnitTests/BackupScriptTests.cs New unit tests verifying backup script uses SQLite .backup command
.github/workflows/ci.yml CI workflow for build and test automation on pull requests and pushes
.github/workflows/release.yml CD workflow for creating release artifacts and publishing to GitHub releases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

Potential N+1 query problem. The first response calculation on lines 68-78 uses a subquery for each ticket, which could result in one database query per ticket. For large datasets, this could cause significant performance issues. Consider refactoring to use a join or pre-fetch all messages for the ranged tickets before computing the first response times. The backup script performs a simple file copy of the SQLite database while it may be in use. This can result in a corrupted backup if write transactions occur during the copy operation. SQLite provides the .backup command specifically for this purpose, which creates a consistent snapshot even during active use. Consider using sqlite3 "$DB_PATH" ".backup '$PAYLOAD_DIR/helpdesk.db'" instead of the cp command on line 79. Potential SQL injection vulnerability in the search functionality. The search term is directly interpolated into the LIKE pattern without proper escaping of special characters like % and _. If a user searches for text containing these characters, it will be interpreted as wildcards rather than literal characters. Use parameterized queries or escape the special characters before building the LIKE pattern. There's duplicate dead-letter logic. Lines 58-68 check if remainingAttempts <= 0 and mark the message as dead-letter, but lines 98-107 perform the same check after the retry loop. The first check (lines 58-68) should be sufficient. The second check is redundant and could lead to duplicate audit events and metrics. Run security/privacy hardening and MVP release readiness

2 participants