Goal
Run malware scanning before persistence on every Pantry package publication surface, and expose safe scan metadata in API/package records.
Publish surfaces
POST /publish(multipart and JSON/base64)POST /publish/commit(multipart and JSON/base64, every package in a batch)POST /zig/publishPOST /php/publish
Direct object-storage/builder uploads must either move behind the API gate or document an equivalent trusted scanning gate; no public/installable artifact path may bypass scanning.
Required behavior
- Validate cheap request constraints and duplicates first, then buffer/decode once, scan, and only then persist.
clean: publish normally and return scan metadata.blocked: reject with a stable 422 response and never write tarball/version metadata.review: hold outside public/installable namespaces until an explicit operator decision exists.error: return 503 with retry guidance and never publish.- Batch/commit publication is atomic with respect to scanning: scan all members before writing any member.
- Persist sanitized scan status, engine, signature/database version, timestamp, duration, and artifact SHA-256 with version metadata.
- Never expose internal scanner errors or sensitive archive contents.
Acceptance criteria
- Integration tests prove blocked/error artifacts are absent from metadata and tarball storage.
- Integration tests cover all four routes and both core encodings.
- A multi-package commit batch with one blocked member writes zero members.
- Existing duplicate, ownership, plan-size, checksum, and auth semantics remain intact.
- API documentation specifies status codes and retry behavior.