Repository navigation
fix: a replaced archive is graded from its new bytes (P-868) - #10
Hidden character warning
Conversation
`archive::expand` skipped any entry whose output file already existed, so a student who re-uploaded `bob_hw.zip` under the same name was graded on the first upload's files, and an entry dropped from the new archive stayed in the extraction directory, where the scan picked it up as a student of its own. The Canvas loader shares `expand` and had the same fault. `expand` now clears its target before opening the archive, so the directory holds exactly what the archive yields now. A replacement that will not open grades nothing rather than its predecessor's files. The local target is named by the archive's file name instead of its stem. Clearing a stem-named directory would let `hw.zip` and `hw.tar` destroy each other's extraction, and the stem of `...zip` is `..`, which would delete the submissions directory itself. A record graded before this change lists `.scriptmark_extracted/<stem>/` paths, so `rescore` refuses it as changed; grade again.
The scan lists the extraction directory, so a truncated file left by a failed write (disk full) was graded as a student named after the file. Review follow-ups: the extraction root sits inside the scanned directory, not beside it; the odd-name test also pins where each archive lands.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (6)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughArchive expansion and discovery now refresh extracted contents and use full archive filenames for extraction directories. Tests cover archive replacement during scanning, loading, and grading. The notes submodule reference also changed. ChangesArchive extraction and replacement
Notes submodule reference
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to Archive extraction now rebuilds from the current archive contents. Tests cover the replacement, loading, and grading paths. No concrete merge-blocking issue was found. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to Refreshing extraction fixes stale grading and separates same-stem archives. However, refresh now recursively deletes directories whose ownership is assumed rather than enforced. Modified bundle paths or redirected extraction parents could extend deletion outside the intended workspace. Normal student upload names remain constrained. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 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 |
A student who re-uploaded
bob_hw.zipunder the same name was graded on the first upload:archive::expandskipped any entry whose output file already existed and never cleared its directory. Because the scan lists that directory, an entry dropped from the new archive also stayed and came back as a student of its own (a droppedutil.pybecamelocal:util). The Canvas loader sharesexpand, so a re-downloaded attachment at the same path had the same fault. Reproduced through the CLI: bob scored 50 before and after uploading the fix. With this branch the scores are 50 and then 100.expandnow clears its target before opening the archive and writes every entry. The directory then holds exactly what the archive yields now. A replacement that will not open grades nothing instead of its predecessor's files, and a failed write removes its partial file.The local target is
.scriptmark_extracted/<archive file name>/, no longer<stem>/. Clearing a stem-named directory would lethw.zipandhw.tardelete each other's files. Worse, the stem of...zipis.., so the scan directory itself would be removed. Canvas keepsattachments/<id>/<stem>.extracted, since that directory holds one archive per id.Consequences before merging
<stem>/paths, sorescorerefuses it as "submitted files changed". Grade again.bundle::loadre-expands,previewandcheckincluded. A read-only submissions directory or bundle reportsArchiveUnreadableinstead of reusing an old extraction. Running two commands over the same submissions at once is unsupported.<stem>/directories stay on disk until removed by hand. Nothing reads them.Tests
Nine new tests, all failing before the fix except the guard for an unchanged archive. In
archive.rs: same-name same-size content, a dropped entry and a renamed entry, an unchanged archive expanded twice, and an unreadable replacement. Indiscovery.rs: a replacement with no phantom student,bob_hw.zipandbob_hw.tarside by side, and...zip/..zip. One Canvas bundle reload test, and the report's steps through the CLI intests/record.rs.cargo test --workspace: 418 passed.cargo clippy --workspace --all-targets -- -D warnings,cargo fmt --checkandgit diff --checkare clean. A five-lens review in which two refuters checked each finding found no deletion-safety issues; its three surviving minor findings are fixed. Design and validation notes:notes/scriptmark/docs/plans/2026-10-04-p868-fresh-archive-extraction.md(notesf7bba71).🤖 Generated with Claude Code
Summary by CodeRabbit