feat(boards,gallery): archive -> soft-delete-to-Trash (closes #1667, #1668, #1669) #1672

Merged
shridhar.sabat merged 0 commits from feat/archive-to-trash-196 into dev 2026-10-15 15:03:29 +00:00
shridhar.sabat commented 2026-10-15 13:45:12 +00:00 (Migrated from gitea.ai-automation-hub.tech)

Unifies boards (Collection) and gallery decks (MoodboardGalleryItem) from is_archived onto the is_deleted + deleted_at soft-delete-to-Trash model. Closes #1667, closes #1668, closes #1669 (milestone #196).

What changed

  • Backend: models gain is_deleted (server_default FALSE) + deleted_at; boot self-heal RENAMES the tier is_archived columns (binned rows preserved, race-safe per #1613); GET params ?include_deleted / ?deleted; gallery bulk-delete answers {deleted, skipped} on both paths; single DELETE answers {ok, hard}; PATCH drops is_* flags; NEW POST /moodboard-gallery/{id}/restore -> {ok, restored, id} (manage + owner-or-admin, whole family #1264). Ownership semantics (#1511, #1181, #1274) unchanged. Purge paths untouched.
  • Frontend: Boards card menu and BoardDetail now show ONE Move to Trash (soft); the live-list permanent-Delete is gone (purge lives only in Trash). Gallery sheet: Archive toggle removed; live -> Move to Trash, trash -> Restore + Delete forever. Client fns renamed (deleteBoard, listDeletedBoards, restoreGalleryItem).
  • Docs: smoke_test_boards.py + phase-A plan follow the new contract.

Kept deliberately (out of scope): garment status='archived' lifecycle, ArchiveMasthead branding + archive copy, TNA wfx archived count.

Verification (all re-run by the reviewer, not taken from builder reports)

  • Backend: py_compile clean; fastapi-route-check OK; 148/148 key suites pass in the sapl-sapl-dev-backend image (sqlite); self-heal proof script ALL CHECKS PASSED in the tier image (RENAME preserves binned rows, 2nd run no-op, ADD fallback, missing-table bail); git grep is_archived/include_archived is zero outside the two RENAME modules.
  • Frontend (merged tree): npm run typecheck clean; eslint zero findings on all touched files; npm run build OK (dist + sw); node --test src/lib 147/147; no window.confirm/select; archive hits on touched files are KEEP items only.
  • Localhost visual gate on the merged bundle (real-shape mocks): 16/16 PASS at 1440x900 + 390x844, zero pageerrors — menu shows Move to Trash only, detail shows one Move to Trash button, sheet shows Move to Trash with no Archive toggle.
  • Live-dev BEFORE shots captured (badge dev-88cc857): card menu Archive+Delete, detail Archive+Delete, sheet Archive+Move to Trash. AFTER shots will follow post-merge.

Deploy note: backend ships a boot self-heal (RENAME on first boot). After merge, verify dev PG has collections.is_deleted + moodboard_gallery_items.is_deleted with binned rows intact, then run the live AFTER probe.

Note: dev PRs run no CI gate (deploy-dev.yml is deploy+smoke on push only), so the evidence above is the gate. Awaiting your go-ahead to merge.

Unifies boards (Collection) and gallery decks (MoodboardGalleryItem) from is_archived onto the is_deleted + deleted_at soft-delete-to-Trash model. Closes #1667, closes #1668, closes #1669 (milestone #196). What changed - Backend: models gain is_deleted (server_default FALSE) + deleted_at; boot self-heal RENAMES the tier is_archived columns (binned rows preserved, race-safe per #1613); GET params ?include_deleted / ?deleted; gallery bulk-delete answers {deleted, skipped} on both paths; single DELETE answers {ok, hard}; PATCH drops is_* flags; NEW POST /moodboard-gallery/{id}/restore -> {ok, restored, id} (manage + owner-or-admin, whole family #1264). Ownership semantics (#1511, #1181, #1274) unchanged. Purge paths untouched. - Frontend: Boards card menu and BoardDetail now show ONE Move to Trash (soft); the live-list permanent-Delete is gone (purge lives only in Trash). Gallery sheet: Archive toggle removed; live -> Move to Trash, trash -> Restore + Delete forever. Client fns renamed (deleteBoard, listDeletedBoards, restoreGalleryItem). - Docs: smoke_test_boards.py + phase-A plan follow the new contract. Kept deliberately (out of scope): garment status='archived' lifecycle, ArchiveMasthead branding + archive copy, TNA wfx archived count. Verification (all re-run by the reviewer, not taken from builder reports) - Backend: py_compile clean; fastapi-route-check OK; 148/148 key suites pass in the sapl-sapl-dev-backend image (sqlite); self-heal proof script ALL CHECKS PASSED in the tier image (RENAME preserves binned rows, 2nd run no-op, ADD fallback, missing-table bail); git grep is_archived/include_archived is zero outside the two RENAME modules. - Frontend (merged tree): npm run typecheck clean; eslint zero findings on all touched files; npm run build OK (dist + sw); node --test src/lib 147/147; no window.confirm/select; archive hits on touched files are KEEP items only. - Localhost visual gate on the merged bundle (real-shape mocks): 16/16 PASS at 1440x900 + 390x844, zero pageerrors — menu shows Move to Trash only, detail shows one Move to Trash button, sheet shows Move to Trash with no Archive toggle. - Live-dev BEFORE shots captured (badge dev-88cc857): card menu Archive+Delete, detail Archive+Delete, sheet Archive+Move to Trash. AFTER shots will follow post-merge. Deploy note: backend ships a boot self-heal (RENAME on first boot). After merge, verify dev PG has collections.is_deleted + moodboard_gallery_items.is_deleted with binned rows intact, then run the live AFTER probe. Note: dev PRs run no CI gate (deploy-dev.yml is deploy+smoke on push only), so the evidence above is the gate. Awaiting your go-ahead to merge.
shridhar.sabat (Migrated from gitea.ai-automation-hub.tech) reviewed 2026-10-15 13:45:26 +00:00
shridhar.sabat (Migrated from gitea.ai-automation-hub.tech) left a comment

Reviewed every non-test hunk + spot-checked test updates. Findings: none blocking.

  • Contracts match front-to-back: Board/Gallery JSON is_deleted + deleted_at; ?include_deleted/?deleted; bulk {deleted, skipped}; single {ok, hard}; POST restore {ok, restored, id} present on both entities.
  • Restore/purge resolve any-state rows (gallery _visible_item_or_404 has no flag filter; boards lookup is by id) so Trash actions cannot 404 on the row shown.
  • Self-heal is RENAME-first (no binned-row loss), DEFAULT FALSE fallback, race-tolerant, boot-wired, proven standalone in the tier image.
  • Purge cascades untouched; ownership gates (#1511/#1181) and honest counts (#1274) preserved and still asserted by the updated tests.
  • No new test files (no workflow registration needed); no new deps; no hardcoded secrets; no window.confirm/native selects; docs updated in the merge commit.

Local gate evidence is in the PR body. Awaiting Shridhar's merge approval; AFTER-merge plan: deploy check, PG column census, live AFTER screenshots, close-out.

Reviewed every non-test hunk + spot-checked test updates. Findings: none blocking. - Contracts match front-to-back: Board/Gallery JSON is_deleted + deleted_at; ?include_deleted/?deleted; bulk {deleted, skipped}; single {ok, hard}; POST restore {ok, restored, id} present on both entities. - Restore/purge resolve any-state rows (gallery _visible_item_or_404 has no flag filter; boards lookup is by id) so Trash actions cannot 404 on the row shown. - Self-heal is RENAME-first (no binned-row loss), DEFAULT FALSE fallback, race-tolerant, boot-wired, proven standalone in the tier image. - Purge cascades untouched; ownership gates (#1511/#1181) and honest counts (#1274) preserved and still asserted by the updated tests. - No new test files (no workflow registration needed); no new deps; no hardcoded secrets; no window.confirm/native selects; docs updated in the merge commit. Local gate evidence is in the PR body. Awaiting Shridhar's merge approval; AFTER-merge plan: deploy check, PG column census, live AFTER screenshots, close-out.
Sign in to join this conversation.