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.
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.
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.
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.
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
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)
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.
Reviewed every non-test hunk + spot-checked test updates. Findings: none blocking.
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.