music on atproto
plyr.fm
1# Offboarding & Data Export
2
3Plyr.fm provides tools for users to export their data and manage their presence on the platform. This document outlines the architecture and workflows for these features.
4
5## Data Export
6
7Users can download a ZIP archive containing all their uploaded tracks in their original format.
8
9### Workflow
10
111. **Initiation**:
12 * User clicks "Export" in the portal.
13 * Frontend calls `POST /exports/media`.
14 * Backend creates a `Job` record (type: `export`) and starts a background task.
15 * Returns an `export_id`.
16
172. **Processing**:
18 * Backend queries all tracks for the user.
19 * Backend streams files from R2 storage into a ZIP archive in memory (using a stream buffer to minimize memory usage).
20 * As tracks are processed, the job progress is updated in the database.
21 * The final ZIP file is uploaded to R2 under the `exports/` prefix.
22 * The R2 object is tagged with `Content-Disposition` to ensure a friendly filename (e.g., `plyr-tracks-2024-03-20.zip`) upon download.
23
243. **Completion & Download**:
25 * Frontend polls the job status via SSE at `/exports/{export_id}/progress`.
26 * Once completed, the job result contains a direct `download_url` to the R2 object.
27 * Frontend triggers a browser download using this URL.
28
29### Storage & Cleanup
30
31* **Location**: Exports are stored in the `audio` bucket under the `exports/` prefix.
32* **Retention**: These files are temporary. An R2 Lifecycle Rule is configured to **automatically delete files in `exports/` after 24 hours**.
33 * This ensures we don't pay for indefinite storage of duplicate data.
34 * Users must download their export within this window.
35
36## Account Deletion
37
38Users can permanently delete their account and all associated data. This is a synchronous, interactive process.
39
40### What Gets Deleted
41
42#### Always Deleted (plyr.fm infrastructure)
43
44| Location | Data |
45|----------|------|
46| **PostgreSQL** | tracks, albums, likes (given), comments (made), preferences, sessions, queue entries, jobs |
47| **R2 Storage** | audio files, track cover images, album cover images |
48
49#### Optionally Deleted (user's ATProto PDS)
50
51If the user opts in, we delete records from their Personal Data Server:
52
53| Collection | Description |
54|------------|-------------|
55| `fm.plyr.track` / `fm.plyr.dev.track` | track metadata records |
56| `fm.plyr.like` / `fm.plyr.dev.like` | like records |
57| `fm.plyr.comment` / `fm.plyr.dev.comment` | comment records |
58
59> **Note**: ATProto deletion requires a valid authenticated session. If the session has expired or lacks required scopes, ATProto records will remain on the user's PDS but all plyr.fm data will still be deleted.
60
61### Workflow
62
631. **Confirmation**: User types their handle to confirm intent
642. **ATProto Option**: Checkbox to opt into deleting ATProto records
653. **Processing**:
66 - Delete R2 objects (audio, images)
67 - Delete database records in dependency order
68 - If opted in: delete ATProto records via PDS API
694. **Session Cleanup**: All sessions invalidated, user logged out
70
71### API
72
73```
74DELETE /account/
75```
76
77**Request Body**:
78```json
79{
80 "confirmation": "handle.bsky.social",
81 "delete_atproto_records": true
82}
83```
84
85**Response** (success):
86```json
87{
88 "deleted": {
89 "tracks": 5,
90 "albums": 1,
91 "likes": 12,
92 "comments": 3,
93 "r2_objects": 11,
94 "atproto_records": 20
95 }
96}
97```
98
99### Important Notes
100
101- **Irreversible**: There is no undo. Export data first if needed.
102- **Likes received**: Likes from other users on your tracks are deleted when your tracks are deleted.
103- **Comments received**: Comments from other users on your tracks are deleted when your tracks are deleted.
104- **ATProto propagation**: Even after deletion from your PDS, cached copies may exist on relay servers temporarily.