Clean up download filenames#2320
Conversation
Switch election/jurisdiction timestamp names to a filesystem-safe YYYY-MM-DDTHHMMZ format (no colons, no microseconds) so downloaded filenames are readable across all OSes. For the audit inputs bundle, drop the route handler's separate isoformat placeholder name and let the background task write both bundle.file.name and storage_path from the same outer_filename, so local-dev downloads match production. Also drop the redundant .zip in the hash filename. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add FILENAME_DATETIME_REGEX and scrub_filename_datetime for the new YYYY-MM-DDTHHMMZ format used in Content-Disposition headers, and switch the six filename assertions in test_reports/test_ballots/test_batches to use it. The original scrub_datetime is unchanged so report-body timestamps (still full isoformat) continue to be scrubbed correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jonahkagan
left a comment
There was a problem hiding this comment.
I don't really have context on this feature - I think @arsalansufi built it. But seems fine to me
There was a problem hiding this comment.
Pull request overview
This PR standardizes and simplifies download filenames (CSV reports and batch file bundles), addressing OS-unfriendly characters (e.g., : and +00:00) and making SHA256 hash downloads more discoverable by switching to a .txt file.
Changes:
- Update timestamp-in-filename formatting to
YYYY-MM-DDTHHMMZfor UTC, avoiding+00:00and colons. - Rename generated batch bundle hash file to a clearer
*-sha256-hash.txtnaming scheme. - Align local-dev and staging/prod outer bundle download filenames by setting
File.namefrom the background worker; update tests to scrub the new filename datetime format.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
server/util/csv_download.py |
Changes timestamp formatting used in downloadable CSV filenames to a filesystem-friendly UTC format. |
server/api/batch_files.py |
Updates bundle File.name handling and renames the hash sidecar file to a .txt filename. |
server/tests/helpers.py |
Adds a scrubber for the new filename datetime format used in Content-Disposition assertions. |
server/tests/batch_comparison/test_batches.py |
Updates Content-Disposition assertions to use the new scrubber. |
server/tests/api/test_reports.py |
Updates report download filename assertions for the new timestamp format. |
server/tests/api/test_ballots.py |
Updates ballot retrieval list download filename assertions for the new timestamp format. |
.basedpyright/baseline.json |
Updates the basedpyright baseline to reflect the changed typing diagnostics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@eventualbuddha built this! But overall, many possible options here. And these updates are in line with what I was imagining. Just something to make it easier for Georgia to open and view the hash |
|
The change from the initial ticket to make the hash file easier to open was straightforward, yeah. Dropping |
Closes #2293
sha256sumtotxtso downloaded files could be easily opened by the OS.+00:00. I replaced that withZfor UTC indication. I noticed Add UTC timezone to all timestamps #903 changedelection_timestamp_nameto use the UTC ISO format, but I don't think we need that here since it is used as the filename and not displayed on the frontend, which is what the PR was protecting against. Feel free to correct me if I'm missing something (or if you suggest a different filename format)./in Finder which made the filename even harder to parse. Removed the remaining colon.zipfrom the hash filename because it made the name harder to read and didn't seem to add much.file.name(set by route handler, not used in staging/prod) but staging/prod rely on thefile.storage_pathfilename (set by task) as parsed by the browser. They had different values because they used slightly different formats. I aligned them to share the same filename, now both set by the worker. I think this is fine and leaves things more consistent.Example local file downloaded on mac (before):
Example local file downloaded on mac (after):
Example staging file downloaded on mac (before):
Expected staging file downloaded on mac (after):
Open to feedback for sure