From fa9abc28b9040138afa5649e5dc929a519eb9bc7 Mon Sep 17 00:00:00 2001 From: Evan Jarrett Date: Sat, 10 Jan 2026 15:24:28 -0600 Subject: [PATCH] update privacy policy, add exporting/deleting bluesky posts as part of userdata --- pkg/appview/handlers/delete.go | 6 +- pkg/appview/templates/pages/privacy.html | 88 +++++- pkg/hold/pds/delete.go | 185 ++++++++++++- pkg/hold/pds/delete_test.go | 337 +++++++++++++++++++++++ pkg/hold/pds/xrpc.go | 44 ++- 5 files changed, 642 insertions(+), 18 deletions(-) create mode 100644 pkg/hold/pds/delete_test.go diff --git a/pkg/appview/handlers/delete.go b/pkg/appview/handlers/delete.go index 7edf359..676cafa 100644 --- a/pkg/appview/handlers/delete.go +++ b/pkg/appview/handlers/delete.go @@ -43,6 +43,7 @@ type HoldDeleteResult struct { CrewDeleted bool `json:"crew_deleted,omitempty"` LayersDeleted int `json:"layers_deleted,omitempty"` StatsDeleted int `json:"stats_deleted,omitempty"` + PostsDeleted int `json:"posts_deleted,omitempty"` } // DeleteAccountHandler handles GDPR account deletion requests @@ -267,6 +268,7 @@ func (h *DeleteAccountHandler) deleteFromSingleHold(ctx context.Context, user *d CrewDeleted bool `json:"crew_deleted"` LayersDeleted int `json:"layers_deleted"` StatsDeleted int `json:"stats_deleted"` + PostsDeleted int `json:"posts_deleted"` } if err := json.NewDecoder(resp.Body).Decode(&holdResponse); err != nil { result.Error = fmt.Sprintf("Failed to parse response: %v", err) @@ -278,6 +280,7 @@ func (h *DeleteAccountHandler) deleteFromSingleHold(ctx context.Context, user *d result.CrewDeleted = holdResponse.CrewDeleted result.LayersDeleted = holdResponse.LayersDeleted result.StatsDeleted = holdResponse.StatsDeleted + result.PostsDeleted = holdResponse.PostsDeleted slog.Debug("Successfully deleted data from hold", "component", "delete", @@ -285,7 +288,8 @@ func (h *DeleteAccountHandler) deleteFromSingleHold(ctx context.Context, user *d "user_did", user.DID, "crew_deleted", holdResponse.CrewDeleted, "layers_deleted", holdResponse.LayersDeleted, - "stats_deleted", holdResponse.StatsDeleted) + "stats_deleted", holdResponse.StatsDeleted, + "posts_deleted", holdResponse.PostsDeleted) return result } diff --git a/pkg/appview/templates/pages/privacy.html b/pkg/appview/templates/pages/privacy.html index 12dfcd9..f978f49 100644 --- a/pkg/appview/templates/pages/privacy.html +++ b/pkg/appview/templates/pages/privacy.html @@ -21,7 +21,7 @@

Data Stored on Our Infrastructure

-

Layer Records: We maintain records on our own PDS that reference container image layers you publish. These records are public and link your AT Protocol identity (DID) to content-addressed SHA identifiers.

+

Layer Records: Our hold services (e.g., hold01.atcr.io) maintain records in their embedded PDS that reference container image layers you publish. These records are public and link your AT Protocol identity (DID) to content-addressed SHA identifiers.

OCI Blobs: Container image layers are stored in our object storage (S3). These blobs are content-addressed and deduplicated—meaning identical layers uploaded by different users are stored only once.

@@ -43,6 +43,33 @@

Server Logs: Our logs may include your handle, DID, IP address, timestamps, and actions performed. Logs are currently ephemeral but may be retained in the future for security and debugging purposes.

+ + + +