Feature Owner: Jethro Magdaleno Lagmay
Module: Dashboards
Priority: High (Data Loss Prevention)
Sprint #12: Sprint 12
Date: June 30, 2026
EXECUTIVE SUMMARY
What is this feature? A transition from a "Hard Delete" model to a "Soft Delete" model for Background Assets. It introduces a dedicated Trash Bin where deleted assets are stored for a 30-day grace period before they can be permanently purged.
Why does it matter? Accidental deletions previously resulted in immediate, irrecoverable data loss (database row dropped, file removed from bucket). This safety net heavily improves Creator UX and drastically reduces potential support tickets for lost work.
What’s the MVP scope?
Database schema updates (
deleted_at,expires_at).Creation of
/creator/trashUI dashboard with a dynamic countdown badge.API endpoints for Soft Delete, Restore, and Purge.
Explicitly scoped to Background Assets only (does not include Audio or Characters yet).
Manual user purge (Automated backend Cron cleanup is deferred to a future sprint).
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
Pain Point: Clicking "Delete" on an asset instantly destroys the file.
Emotional: Extreme frustration and panic when a high-value asset is accidentally removed.
Functional: Creators must manually re-upload and re-link assets if a mistake is made.
Business Impact: Increased risk of churn for power users; support team burdened with impossible "restore data" requests.
Future State (With Feature) Assets are safely moved out of view but remain in the database for 30 days. Creators have full autonomy to restore their own files or permanently destroy them to free up storage.
Marketing Hook "Never lose your hard work to an accidental click again. Introducing the Creator Trash Bin—your 30-day safety net."
2. 4D FRAMEWORK MAPPING
Diagnose: Identified data loss vulnerability during the Background Asset deletion flow.
Design: Designed a dedicated Trash Bin interface adhering to WyzLab v1.3 tokens (Orange for destructive, Gold for warnings), including a strict "Type DELETE" modal.
Develop: Updated Supabase schema, built Next.js App Router API endpoints with strict Zod validation, and mitigated Next.js aggressive client/server caching.
Deliver: Deployed with a critical SQL migration prerequisite. Feature is actively working in the staging/dev environment.
3. USER FLOWS
Entry Point Background Assets Dashboard > Click Trash Icon on Asset OR Click "Trash Bin" button in header.
Success Criteria
Trashed asset immediately disappears from the main library.
Trashed asset appears in the Trash Bin with an accurate countdown.
Restored asset immediately returns to the main library.
Main Flow (Happy Path)
User clicks "Delete" on a background asset.
Asset moves to Trash Bin (soft delete).
User navigates to Trash Bin.
User clicks "Restore" -> Asset is back in Library.
OR User clicks "Purge" -> User types "DELETE" in modal -> Asset is permanently wiped from Storage and DB.
Edge Cases
Next.js caching serving stale UI (Mitigated via
cache: "no-store").Invalid UUID payloads sent to API (Mitigated via Zod).
Malicious user attempts to delete another creator's asset (Mitigated via
creator_idmatching).
Decision Points
Does the user want to restore or purge?
Is the user sure they want to purge? (Modal barrier).
4. INFORMATION ARCHITECTURE
Primary Information (Always visible): Asset Thumbnail (or generic preview), Asset Name.
Secondary Information: Asset Type (e.g., IMAGE, VIDEO), Time Remaining Badge (e.g., "30d left").
Tertiary Information (Hidden until needed): Purge confirmation warning text and text input field.
Actions
Primary CTA: Restore (moves asset back).
Secondary Actions: Purge (opens destructive modal), Cancel (closes modal).
5. WIREFRAMES
N/A - Built directly into code based on existing component library.
6. WIREFLOWS
Background Assets Page -> [Soft Delete Action] -> Trash Bin Page -> [Restore Action] -> Background Assets Page -> OR [Purge Action] -> Purge Modal -> [Type DELETE] -> Asset Destroyed
7. PROTOTYPE
Already synced in the development server.
8. BACKEND SCHEMA
Database Tables Table: public.asset_metadata
Added:
deleted_at(TIMESTAMPTZ, DEFAULT NULL)Added:
expires_at(TIMESTAMPTZ, DEFAULT NULL)
Indexes
CREATE INDEX idx_asset_metadata_deleted_at ON public.asset_metadata(deleted_at);(Critical for fast.is("deleted_at", null)queries).CREATE INDEX idx_asset_metadata_creator_id ON public.asset_metadata(creator_id);
Constraints & RLS Policies
All destructive/mutative API routes manually verify
creator_idmatches the authenticated user before executing Supabase commands.
9. API ENDPOINTS
GET /api/creator/list-assets(Modified)Returns all assets where
deleted_at IS NULL.
GET /api/creator/get-trash-assets(New)Returns all assets where
deleted_at IS NOT NULL.
DELETE /api/creator/delete-assets(Refactored)Zod Validated:
asset_id(UUID).Performs Soft Delete (
UPDATE deleted_at = NOW()).
PATCH /api/creator/restore-assets(New)Zod Validated:
asset_id(UUID).Clears Trash timestamps (
UPDATE deleted_at = NULL).
DELETE /api/creator/purge-assets(New)Zod Validated:
asset_id(UUID).Hard Delete: Removes from Supabase
public-assetsbucket (including.jpgthumbnails for videos), thenDELETE FROM asset_metadata.
10. DATA REQUIREMENTS
Frontend Needs
Array of
AssetTypeobjects mapped properly (convertingfile_nametoname,file_urltourl).Calculation of days remaining between
now()anddeleted_at + 30 days.
API Calls Frontend Will Make
Uses custom hook
useBackgroundAssets()for main library.Directly fetches
/get-trash-assetson the Trash page.Dispatches
DELETEandPATCHrequests on user interaction.
Caching Strategy
Server:
export const dynamic = "force-dynamic";andrevalidate = 0;on GET routes.Client:
cache: "no-store"added tofetch()in theuseBackgroundAssetshook to prevent "Ghost Assets".
11. PERFORMANCE CONSIDERATIONS
Database Optimization: The
idx_asset_metadata_deleted_atindex prevents full-table scans when the main dashboard filters out trashed items.Caching Strategy: Cache is explicitly bypassed. While this slightly increases DB hits, it is strictly necessary to maintain immediate UI consistency for soft-deletes.
API Response Time: Expected < 200ms. Storage bucket deletions during Purge may take slightly longer (~400ms).
12. SECURITY & AUTHORIZATION
Who can access this feature? Authenticated Creators only.
Authorization Logic
Backend verifies JWT session via
authenticateUser().Supabase DB
.eq("creator_id", creator_id)acts as a tenant barrier, ensuring a user can never fetch, update, or purge an asset they do not own.
Data Validation Strict z.string().uuid() validation on all incoming payload bodies via Zod. Rejects malformed requests with 400 Bad Request.
13. ERROR HANDLING
400 Bad Request: Zod validation fails (e.g., missing or malformed
asset_id).403 Forbidden: Asset
creator_iddoes not match the authenticated user.404 Not Found: Asset ID does not exist in the database.
500 Internal Error: Supabase connection failure or storage bucket removal failure. Handled via
catch (err) { err instanceof Error ... }and relayed to UI via Sonner toasts.
14. TESTING CHECKLIST
Happy Path
[x] Click Delete -> Asset moves to Trash.
[x] Navigate to Trash -> Asset is visible with accurate Days Left badge.
[x] Restore Asset -> Instantly returns to Background Assets.
[x] Purge Asset -> Type DELETE in modal -> File permanently deleted.
Edge Cases
[x] Ensure deleted items do not persist on the main dashboard (Ghost Assets).
[x] Pass invalid string format to Purge API -> Rejected by Zod.
[x] Attempt to purge asset without typing exactly "DELETE" in modal -> Button remains disabled.
[x] Ensure thumbnail images load correctly in Trash UI, or fall back cleanly if URL is broken.
15. OPEN QUESTIONS
Automated Cleanup: When will we implement the Supabase Edge Function / PG_CRON job to automatically wipe assets where
expires_at < NOW()? (Targeting next Sprint).Feature Parity: Should we immediately expand this logic to Quests and Character assets, or observe usage data first?
16. OUT OF SCOPE
Automated background task to permanently wipe files older than 30 days.
Trash Bin support for Quests, Characters, or Audio Assets.
Multi-select bulk restore/purge.
17. SUCCESS METRICS
Primary: Zero (0) support tickets requesting manual data recovery for accidentally deleted background assets over the next 30 days.
Secondary: Telemetry showing a healthy ratio of
restore-assetsusage vspurge-assetsusage, proving the safety net is being utilized.
18. DEPENDENCIES
This feature depends on:
Supabase PostgreSQL Database (schema updates).
Supabase Storage (Public Bucket file deletion logic).
Authenticated User Context.
These features depend on this:
Future global Trash Bin implementation will inherit this
deleted_atarchitectural pattern.
19. TIMELINE & OWNERSHIP
Implemented: June 30, 2026
Owner: Jethro Magdaleno Lagmay
Document Version
v1.0 - Initial document