Server side of haverstack/core#64. Core gets collectAttachmentGarbage({ graceMs?, dryRun? }) (owner-only on ScopedStack); the wire gets an optional owner-only endpoint, which this server — as the reference implementation — should ship.
Endpoint
POST /attachments/gc — owner-only (requireOwner), body { "graceMs"?: number, "dryRun"?: boolean } → { "deleted": [fileId...], "reclaimedBytes": number }.
Semantics are entirely core's (soft-deleted records count as references; a file's own _attachment@1 records don't, but recent ones defer collection via the grace period; deletion goes through the deleteAttachment path). The server adds the wire mapping, plus:
- Scheduling/automation is explicitly a server concern per core #64 — decide whether this server offers any (e.g. optional interval env var) or stays invoke-only. Leaning invoke-only for v1;
dryRun makes a cron-from-outside workflow safe.
- Note the interaction with
DELETE /attachments/:fileId: once core #63/#64 land, the 409 reference check also covers file-ref content references and soft-deleted records — server tests asserting current delete behavior will need updating.
Sequencing
Blocked on haverstack/core#63 (file-ref field kind) then haverstack/core#64 (BlobAdapter.listFiles(), the sweep itself). Do not ship a GC endpoint before file-ref reference semantics exist — it would delete content-referenced files (the exact blind spot core #63 documents).
Work items
Refs haverstack/core#64, haverstack/core#63, haverstack/core#60 (soft-delete-counts rationale), #32.
Server side of haverstack/core#64. Core gets
collectAttachmentGarbage({ graceMs?, dryRun? })(owner-only onScopedStack); the wire gets an optional owner-only endpoint, which this server — as the reference implementation — should ship.Endpoint
POST /attachments/gc— owner-only (requireOwner), body{ "graceMs"?: number, "dryRun"?: boolean }→{ "deleted": [fileId...], "reclaimedBytes": number }.Semantics are entirely core's (soft-deleted records count as references; a file's own
_attachment@1records don't, but recent ones defer collection via the grace period; deletion goes through thedeleteAttachmentpath). The server adds the wire mapping, plus:dryRunmakes a cron-from-outside workflow safe.DELETE /attachments/:fileId: once core #63/#64 land, the 409 reference check also coversfile-refcontent references and soft-deleted records — server tests asserting current delete behavior will need updating.Sequencing
Blocked on haverstack/core#63 (
file-reffield kind) then haverstack/core#64 (BlobAdapter.listFiles(), the sweep itself). Do not ship a GC endpoint beforefile-refreference semantics exist — it would delete content-referenced files (the exact blind spot core #63 documents).Work items
docs/api.mdentryRefs haverstack/core#64, haverstack/core#63, haverstack/core#60 (soft-delete-counts rationale), #32.