Skip to content

fix(evidence-export): address two follow-up review findings from prod deploy PR#2641

Merged
tofikwest merged 3 commits intomainfrom
fix/evidence-export-review-feedback
Apr 22, 2026
Merged

fix(evidence-export): address two follow-up review findings from prod deploy PR#2641
tofikwest merged 3 commits intomainfrom
fix/evidence-export-review-feedback

Conversation

@tofikwest
Copy link
Copy Markdown
Contributor

@tofikwest tofikwest commented Apr 22, 2026

Summary

Fixes two issues cubic flagged on the production deploy PR #2640, plus adds regression tests for automation-only and mixed-org scenarios that weren't covered explicitly in #2639.

Fixes

P1 — Client-disconnect detection could falsely abort successful exports

evidence-export.controller.ts listened on req.once('close'). In Node 16+ req.close fires on both client disconnect AND normal request completion, which could falsely abort a successful export in a timing window. The guard was res.writableEnded which becomes true as soon as .end() is called, not when data is actually flushed — leaving a small window where an abnormal close could be incorrectly treated as normal.

Fix: listen only on res.close and distinguish completion via res.writableFinished (true only after all data is flushed and the 'finish' event fires).

P2 — Placeholder vs success filename collision

The collision tracker was being fed the raw attachment name, and the _MISSING_<name>.txt wrapping was applied after tracking. A legitimate upload literally named _MISSING_foo.txt plus a missing upload named foo could both end up at the same final ZIP entry path.

Fix: pass the full final name (including any _MISSING_ wrapping and .txt suffix) through the tracker so collisions are resolved on what actually ends up in the ZIP.

Also included

Regression tests from a separate follow-up covering:

  • Per-task export with automations only (no attachments) → verifies no 01-attachments/ folder is created and no S3 calls are made
  • Per-task export with neither automations nor attachments → verifies ZIP contains only the summary PDF
  • Org-wide export with automations only (no attachments anywhere) → verifies the classic pre-feat(evidence-export): include task attachments and stream large ZIPs #2639 structure is preserved
  • Org-wide export mixing an attachment-only task with an automation-only task → verifies both appear correctly

Test plan

  • 38 tests pass: cd apps/api && npx jest src/tasks/evidence-export
  • Typecheck clean in evidence-export/ files
  • Manual: export for a task with attachments and automations — verify no behavior regression
  • Manual: hit the per-task export endpoint, close the browser tab mid-download, check API logs for Client disconnected during export (…); aborting archive
  • Manual: hit per-task export on a completing response — verify no aborting archive log appears

Linear

Follow-up on CS-279

🤖 Generated with Claude Code


Summary by cubic

Fixes false export aborts on normal completion and prevents _MISSING_ placeholder filename collisions in evidence ZIPs. Adds regression tests for automation-only, summary-only, and mixed-org exports. Linear: CS-279.

  • Bug Fixes
    • Client disconnect handling: listen on res.close only and gate by res.writableFinished to avoid aborting completed downloads; remove req.close listener.
    • Filename collisions: dedupe on the final ZIP entry name (including _MISSING_ prefix and .txt), so real files like _MISSING_foo.txt don’t collide with placeholders for missing foo.

Written for commit 8c655b3. Summary will update on new commits.

tofikwest and others added 2 commits April 22, 2026 17:57
Add explicit regression tests for the three scenarios that aren't covered
by the attachment-focused happy path:

- Per-task export with automations but no attachments: verifies the
  01-attachments/ folder is NOT created, no S3 calls are made, and the
  summary PDF is rendered with attachmentsCount=0 (line omitted).
- Per-task export with neither automations nor attachments: verifies the
  ZIP contains only the summary PDF.
- Org-wide export where no task has attachments (classic pre-PR scenario):
  verifies manifest shows totalAttachments=0 and no 01-attachments/
  folders appear anywhere. Matches exact shape of old behaviour.
- Org-wide export mixing an automation-only task with an attachment-only
  task: verifies both appear in the same ZIP with correct contents.

All 36 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues cubic flagged on the production deploy PR (#2640):

1. Client-disconnect detection was listening on `req.once('close')`. In
   Node 16+ `req.close` fires on both disconnect AND normal request
   completion, which could falsely abort a successful export. Now we
   listen only on `res.close` and distinguish normal completion via
   `res.writableFinished` (true only after the full response is flushed,
   unlike `writableEnded` which only reflects that `.end()` was called).

2. Filename collisions were deduplicated against the raw attachment name,
   then wrapped into `_MISSING_<name>.txt` for placeholders. A legitimate
   upload named `_MISSING_foo.txt` plus a missing upload named `foo` could
   therefore both land at the same final ZIP path. Now the tracker sees
   the full final name (including any `_MISSING_` wrapping) so the
   collision is resolved on what actually ends up in the ZIP.

Added two regression tests: normal-completion does not abort, and
success/placeholder names don't collide in the final ZIP path. 38 tests
pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

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

Project Deployment Actions Updated (UTC)
comp-framework-editor Ready Ready Preview, Comment Apr 22, 2026 10:22pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app Skipped Skipped Apr 22, 2026 10:22pm
portal Skipped Skipped Apr 22, 2026 10:22pm

Request Review

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

Auto-approved: Small, well-tested bug fixes for evidence export: improves client-disconnect handling and filename collision logic. Low risk with comprehensive regression tests.

@vercel vercel Bot temporarily deployed to Preview – app April 22, 2026 22:21 Inactive
@vercel vercel Bot temporarily deployed to Preview – portal April 22, 2026 22:21 Inactive
@tofikwest tofikwest merged commit 0ac9c80 into main Apr 22, 2026
10 checks passed
@tofikwest tofikwest deleted the fix/evidence-export-review-feedback branch April 22, 2026 22:23
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.29.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants