#194: orphan-file sweep + drop Attachment.deletedAt #249

Merged
fable-5 merged 2 commits from feat/194-orphan-sweep into main 2026-07-30 13:45:57 +02:00
Collaborator

Implements #194:

  • Nightly orphan-file sweep (OrphanSweepService, job orphan-file-sweep per the operations.md jobs table), two directions:
    1. UNCLAIMED rows: attachments whose pageId is still null after a 24h grace period were claimed by nothing (no collab persist, no page upload, no import) - reclaimed: row + file + quota released. The grace period protects the paste-then-insert window (proven by test).
    2. STRAY files: bytes on the uploads volume without a database row (crash between file write and row insert) - removed once older than the grace period.
  • DELIBERATE DEVIATION from the issue text, documented in schema comment + operations.md: claimed attachments whose page content no longer embeds them are NOT auto-deleted. Analysis of the attachments panel (#61) showed insert-into-document is OPTIONAL there - claimed files are user-managed page assets, so content-reference sweeping would destroy user data (e.g. a PDF uploaded to the panel and never inserted). The pond file manager already flags unclaimed files as orphans - the sweep automates exactly that product definition; claimed-but-unembedded cleanup stays a human decision.
  • Attachment.deletedAt removed by migration (never written; both purge and sweep hard-delete). The never-true deletedAt:null filters in files/export attachment queries went with it - their removal surfaced in 3 existing suites which now pass without the phantom column.

Tested: new orphan-sweep.e2e.db.test.ts (reclaim past grace incl. quota assert, fresh protected, claimed protected despite age, stray old removed / stray fresh kept); api full suite 459 green vs fresh DB (migration applies on boot); typecheck + lint green.

Refs #194 (close manually after green CI + merge).

Generated with Claude Code (Claude Fable 5)

Implements #194: - Nightly orphan-file sweep (OrphanSweepService, job orphan-file-sweep per the operations.md jobs table), two directions: 1. UNCLAIMED rows: attachments whose pageId is still null after a 24h grace period were claimed by nothing (no collab persist, no page upload, no import) - reclaimed: row + file + quota released. The grace period protects the paste-then-insert window (proven by test). 2. STRAY files: bytes on the uploads volume without a database row (crash between file write and row insert) - removed once older than the grace period. - DELIBERATE DEVIATION from the issue text, documented in schema comment + operations.md: claimed attachments whose page content no longer embeds them are NOT auto-deleted. Analysis of the attachments panel (#61) showed insert-into-document is OPTIONAL there - claimed files are user-managed page assets, so content-reference sweeping would destroy user data (e.g. a PDF uploaded to the panel and never inserted). The pond file manager already flags unclaimed files as orphans - the sweep automates exactly that product definition; claimed-but-unembedded cleanup stays a human decision. - Attachment.deletedAt removed by migration (never written; both purge and sweep hard-delete). The never-true deletedAt:null filters in files/export attachment queries went with it - their removal surfaced in 3 existing suites which now pass without the phantom column. Tested: new orphan-sweep.e2e.db.test.ts (reclaim past grace incl. quota assert, fresh protected, claimed protected despite age, stray old removed / stray fresh kept); api full suite 459 green vs fresh DB (migration applies on boot); typecheck + lint green. Refs #194 (close manually after green CI + merge). Generated with Claude Code (Claude Fable 5)
fable-5 added 1 commit 2026-07-30 13:20:18 +02:00
#194: orphan-file sweep, drop the unused Attachment.deletedAt
Some checks failed
CI / Lint, typecheck, test (pull_request) Successful in 5m1s
CI / Build container images (pull_request) Successful in 2m48s
CI / Auth e2e pack (pull_request) Failing after 3m12s
CI / Import/export fidelity gate (pull_request) Has been skipped
0bc36aa58c
Nightly sweep with two directions: attachments still unclaimed (pageId
null) after a 24 h grace period - claimed by no collab persist, page
upload, or import - are reclaimed (row, file, quota released); files on
the uploads volume without a database row (drift after a crashed
upload) are removed once older than the grace period. The grace period
protects the paste-then-insert window.

Deliberate deviation from the issue's content-reference idea, documented
in schema comment and operations.md: claimed attachments whose page
content no longer embeds them are NOT auto-deleted. The page attachments
panel lists claimed files as user-managed objects (inserting into the
document is optional there), so 'not embedded' is not 'unused' - an
auto-delete would destroy panel assets. Humans clean those up in the
panel or the pond file manager, which flags orphans already.

Attachment.deletedAt is removed by migration - deletion is hard
everywhere (sweep, purge, manual), there is no soft-delete state; the
never-true deletedAt:null filters in files/export queries went with it.

Refs #194

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0168Ph5uBmHm8X28CSVpbpnJ
fable-5 added 1 commit 2026-07-30 13:31:06 +02:00
adjust the maintenance-job count fence: 6 jobs with the orphan sweep
All checks were successful
CI / Lint, typecheck, test (pull_request) Successful in 4m58s
CI / Auth e2e pack (pull_request) Successful in 7m50s
CI / Import/export fidelity gate (pull_request) Successful in 53s
CI / Build container images (pull_request) Successful in 1m12s
CD / Build and push images (push) Successful in 16s
CD / Deploy to Test (push) Successful in 16s
CD / Smoke tests against Test (push) Successful in 1m21s
CD / Promote to Int (push) Successful in 12s
CI / Lint, typecheck, test (push) Successful in 5m5s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 7m36s
CI / Import/export fidelity gate (push) Successful in 55s
02c1f18fe1
The system panel spec pins the registered-job count on purpose; the
orphan-file-sweep registration (#194) is the deliberate sixth row (CI
run 493 caught exactly this, 14x resolved to 6).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0168Ph5uBmHm8X28CSVpbpnJ
fable-5 merged commit 02c1f18fe1 into main 2026-07-30 13:45:57 +02:00
Sign in to join this conversation.
No description provided.