Getting Started
- Fork the repository: https://github.com/JointSave-org/Joint_Save
- Clone your fork:
git clone https://github.com/<your-username>/Joint_Save.git
cd Joint_Save
- Create a new branch:
git checkout -b feat/pool-archival-cleanup
Overview
As JointSave grows, completed and inactive pools accumulate in the Explore page and My Groups tab, cluttering the UI and degrading performance. Currently, there is no mechanism to archive completed pools, remove inactive pools from discovery, or clean up stale data. The pools table in Supabase has a status column but no automated transitions occur.
Checked frontend/app/explore/page.tsx — fetches all pools via /api/pools without filtering by status. The My Groups tab shows all pools the user is a member of regardless of completion status. Pool contracts remain deployed on-chain indefinitely.
This issue adds an automated archival system that identifies completed/inactive pools, moves them to an archived state, hides them from discovery views (while preserving historical data), and provides an archival dashboard for reviewing past pools.
Requirements
Database Changes
- Add to
pools table:
archived_at (timestamptz, nullable)
archive_reason (text, nullable): completed, inactive_90d, admin_archived, emergency_withdrawn
- Migration:
ALTER TABLE pools ADD COLUMN archived_at timestamptz, ADD COLUMN archive_reason text
Automated Archival Logic
- New Vercel Cron endpoint:
POST /api/cron/archive-pools
- Runs daily at 02:00 UTC
- Criteria for archival:
- Completed pools: status = 'completed' and
completed_at is older than 7 days (grace period for viewing)
- Inactive pools: no activity in
pool_activity for 90 days AND all members have empty deposits (never deposited or fully withdrawn)
- Emergency withdrawn: status = 'emergency_withdrawn' and
emergency_withdrawn_at is older than 30 days
- Sets
archived_at and archive_reason for matching pools
- Sends a summary notification to each affected pool's admin
- Logs archival actions in a new
archive_log table
Frontend Changes
API Changes
GET /api/pools — add archived query param (default: false) to include/exclude archived pools
PUT /api/pools/[id]/archive — manual admin archival (body: reason)
PUT /api/pools/[id]/unarchive — reverse archival (admin only)
Data Preservation
- Archived pools retain all Supabase data (pool metadata, members, activity)
- On-chain contract data is immutable and unaffected
- Archived pools can still be viewed in read-only mode
- Historical data export remains available for archived pools
Acceptance Criteria
Getting Started
Overview
As JointSave grows, completed and inactive pools accumulate in the Explore page and My Groups tab, cluttering the UI and degrading performance. Currently, there is no mechanism to archive completed pools, remove inactive pools from discovery, or clean up stale data. The
poolstable in Supabase has astatuscolumn but no automated transitions occur.Checked
frontend/app/explore/page.tsx— fetches all pools via/api/poolswithout filtering by status. TheMy Groupstab shows all pools the user is a member of regardless of completion status. Pool contracts remain deployed on-chain indefinitely.This issue adds an automated archival system that identifies completed/inactive pools, moves them to an archived state, hides them from discovery views (while preserving historical data), and provides an archival dashboard for reviewing past pools.
Requirements
Database Changes
poolstable:archived_at(timestamptz, nullable)archive_reason(text, nullable):completed,inactive_90d,admin_archived,emergency_withdrawnALTER TABLE pools ADD COLUMN archived_at timestamptz, ADD COLUMN archive_reason textAutomated Archival Logic
POST /api/cron/archive-poolscompleted_atis older than 7 days (grace period for viewing)pool_activityfor 90 days AND all members have empty deposits (never deposited or fully withdrawn)emergency_withdrawn_atis older than 30 daysarchived_atandarchive_reasonfor matching poolsarchive_logtableFrontend Changes
Modify Explore page:
Modify My Groups page:
New component:
frontend/components/shared/archived-pool-card.tsxModify pool detail page for archived pools:
API Changes
GET /api/pools— addarchivedquery param (default: false) to include/exclude archived poolsPUT /api/pools/[id]/archive— manual admin archival (body: reason)PUT /api/pools/[id]/unarchive— reverse archival (admin only)Data Preservation
Acceptance Criteria