Found while debugging why uploaded blog images weren't loading (staging files never promoted — the blog-media-processor couldn't reach ClamAV because its stack wasn't on the clamav overlay; fixed in spikersoft-infrastructure master).
Bug
Publication and scanning are fully decoupled:
Adult accounts are auto-approved: the post is Published with PublishedAt set before the scan pipeline even starts.
When a scan comes back dirty, BlogMediaOrchestrator.HandleScanCompletedAsync only marks the media record (SecurityScanStatus=Quarantined, ProcessingStatus=Failed). The post stays Published.
The API serializes quarantined media out to clients like any other media (empty URL → broken image).
The flagged file is left in /app/uploads/blogs forever — the blog pipeline has no quarantine directory, unlike the file-movement service.
Because scanning fails closed, a ClamAV outage takes the same quarantine path as a real virus — so any post-level consequence would let an infra blip unpublish posts.
Fix
Scanner outage ≠ verdict:BlogMediaScanConsumer now throws on connection failures so the existing DLQ/retry machinery (5s/30s/300s, then DLQ with auto-retry) re-delivers the scan request. Media stays Pending; the post is untouched. Virus detected / scan-error verdicts / missing file remain fail-closed.
Quarantine unpublishes: on a definitive dirty verdict the orchestrator moves the post Published → PendingReview (clears PublishedAt, IsAutoApproved=false) and appends the scan verdict to ReviewNotes. Moderation flow already exists: approve republishes, reject discards.
Quarantined media is never served:BlogController filters media with SecurityScanStatus=Quarantined out of all responses.
Dirty files leave staging: moved to BlogMedia:QuarantinePath (/app/quarantine/blogs, prefixed with the workflow id). Requires the quarantine bind mount on the blog-media-processor stack (added in spikersoft-infrastructure master).
Found while debugging why uploaded blog images weren't loading (staging files never promoted — the blog-media-processor couldn't reach ClamAV because its stack wasn't on the `clamav` overlay; fixed in spikersoft-infrastructure master).
## Bug
Publication and scanning are fully decoupled:
1. Adult accounts are auto-approved: the post is `Published` with `PublishedAt` set **before** the scan pipeline even starts.
2. When a scan comes back dirty, `BlogMediaOrchestrator.HandleScanCompletedAsync` only marks the media record (`SecurityScanStatus=Quarantined`, `ProcessingStatus=Failed`). The post stays `Published`.
3. The API serializes quarantined media out to clients like any other media (empty URL → broken image).
4. The flagged file is left in `/app/uploads/blogs` forever — the blog pipeline has no quarantine directory, unlike the file-movement service.
5. Because scanning fails closed, a ClamAV *outage* takes the same quarantine path as a real virus — so any post-level consequence would let an infra blip unpublish posts.
## Fix
- **Scanner outage ≠ verdict:** `BlogMediaScanConsumer` now throws on connection failures so the existing DLQ/retry machinery (5s/30s/300s, then DLQ with auto-retry) re-delivers the scan request. Media stays Pending; the post is untouched. Virus detected / scan-error verdicts / missing file remain fail-closed.
- **Quarantine unpublishes:** on a definitive dirty verdict the orchestrator moves the post `Published → PendingReview` (clears `PublishedAt`, `IsAutoApproved=false`) and appends the scan verdict to `ReviewNotes`. Moderation flow already exists: approve republishes, reject discards.
- **Quarantined media is never served:** `BlogController` filters media with `SecurityScanStatus=Quarantined` out of all responses.
- **Dirty files leave staging:** moved to `BlogMedia:QuarantinePath` (`/app/quarantine/blogs`, prefixed with the workflow id). Requires the quarantine bind mount on the blog-media-processor stack (added in spikersoft-infrastructure master).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found while debugging why uploaded blog images weren't loading (staging files never promoted — the blog-media-processor couldn't reach ClamAV because its stack wasn't on the
clamavoverlay; fixed in spikersoft-infrastructure master).Bug
Publication and scanning are fully decoupled:
PublishedwithPublishedAtset before the scan pipeline even starts.BlogMediaOrchestrator.HandleScanCompletedAsynconly marks the media record (SecurityScanStatus=Quarantined,ProcessingStatus=Failed). The post staysPublished./app/uploads/blogsforever — the blog pipeline has no quarantine directory, unlike the file-movement service.Fix
BlogMediaScanConsumernow throws on connection failures so the existing DLQ/retry machinery (5s/30s/300s, then DLQ with auto-retry) re-delivers the scan request. Media stays Pending; the post is untouched. Virus detected / scan-error verdicts / missing file remain fail-closed.Published → PendingReview(clearsPublishedAt,IsAutoApproved=false) and appends the scan verdict toReviewNotes. Moderation flow already exists: approve republishes, reject discards.BlogControllerfilters media withSecurityScanStatus=Quarantinedout of all responses.BlogMedia:QuarantinePath(/app/quarantine/blogs, prefixed with the workflow id). Requires the quarantine bind mount on the blog-media-processor stack (added in spikersoft-infrastructure master).