Data Flow & Privacy Map

bluesky-social/social-app

Generated by Inkwell Forge — automated codebase documentation analysis. Based on analysis of 131 screens. Subject matter expert review is recommended before distribution.

May 5, 2026

1. Executive Summary

This Data Flow & Privacy Map covers the Bluesky social application — a React Native / Expo mobile application built on the AT Protocol (atproto), a decentralized social networking protocol. The assessment covers 131 screens across iOS and Android platforms, examining data collection, on-device storage, server-side transmission, third-party sharing, and deletion mechanisms.

Overall Privacy Posture Rating: Moderate

The application demonstrates strong privacy-by-design principles in several areas — notably its use of expo-secure-store / Keychain for authentication tokens, its moderation-aware content rendering, and its explicit user controls for notification preferences, content language, and activity privacy. However, several medium-to-high risk gaps were identified, primarily around on-device storage practices, analytics data collection, and the scope of device permissions.

Data Categories Identified:

Top 3 Highest-Risk Privacy Concerns:

  1. Device Contacts Upload (High Risk): The Find Contacts flow (/find-contacts-flow) uploads device phone contacts to Bluesky's servers for matching against registered accounts. This involves third-party PII (contacts who have not consented to the app's data processing) and requires explicit GDPR Article 6 legal basis analysis and potentially Article 9 assessment if contacts include health-related data.

  2. Analytics SDK Data Collection (High Risk): The application uses a custom analytics abstraction (useAnalytics / ax.metric) that collects user behavior data including profile DIDs, post URIs, search queries, feed interactions, and navigation patterns. The underlying analytics provider is not identifiable from the codebase alone, preventing assessment of data transfer mechanisms, retention periods, and DPA status.

  3. Persisted Storage Backup Exposure (Medium Risk): The application uses a persisted storage layer (likely AsyncStorage-backed) for session account data, search history, and preferences. This data is included in iOS iCloud backups and Android Google Drive auto-backups by default, potentially exposing session tokens and browsing history if a device backup is restored to a different device or accessed by a third party.

Assessment Limitations: This assessment is based on documentation-based analysis of 131 screens. It does not include live data flow tracing, device forensics, network traffic inspection, or server-side database inspection. All findings should be verified against the live application before regulatory submission.


2. Methodology & Scope

Regulatory Framework

Privacy Standard

Risk Framework

Mobile Storage Standard

Scope

All 131 screens provided in the documentation were assessed, covering:

Mobile-Specific Scope Additions

Limitations

Based on technical documentation review, not live data flow tracing, database inspection, or device forensics. The specific storage keys, encryption configurations, and retention periods for the persisted storage layer are not fully visible from screen documentation alone.


3. On-Device Storage Privacy Assessment

Storage Mechanism Inventory

Storage Mechanism Encrypted Data Stored Survives Uninstall Backup Eligible Privacy Risk MASVS-STOR
Persisted storage (AsyncStorage-backed, via #/state/persisted) No (plain-text) Session account list, reminders, NUX state, policy update state, search history, profile history No (cleared on uninstall) Yes — included in iOS iCloud backup and Android Google Drive auto-backup by default High — session account data and browsing history backed up to cloud MASVS-STOR-1 concern
Device storage (MMKV-backed, via #/storage) No by default (MMKV supports encryption but configuration not documented) Dev mode flag, activity subscription nudge state, policy update debug override No Yes Medium — non-sensitive flags, but MMKV encryption status unverified MASVS-STOR-1 concern if sensitive data added
expo-secure-store / Keychain (iOS) / Keystore (Android) Yes — platform secure enclave Authentication tokens (access JWT, refresh JWT), session credentials iOS: Persists by default after uninstall unless kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly is used; Android: Cleared on uninstall Excluded from iCloud backup by default; excluded from Android backup Low if used correctly — but iOS Keychain persistence post-uninstall is a right-to-erasure gap MASVS-STOR-1 compliant
SharedPrefs native module (MMKV-backed, expo-bluesky-swiss-army) No by default Notification sound preferences (playSoundChat), background notification handler preferences No Yes Low — non-sensitive notification preferences MASVS-STOR-1 concern if sensitive data added
In-memory only (React state / TanStack Query cache) N/A Feed data, post content, profile views, conversation messages, search results No (lost on app close) No Low — ephemeral, not persisted N/A

(inferred from expo-secure-store and #/state/persisted usage patterns — verify against actual storage key enumeration and encryption configuration)

Biometric Data Handling

The application does not process biometric data at the application layer. Based on the screen documentation:

API / Library Biometric Data Accessed Data Stored On-Device Template Stored by App Privacy Risk
OS-level biometric (Face ID / Touch ID / Fingerprint) Used only for device unlock / app authentication gate No — OS-only No — App only receives boolean authentication result Low — OS handles biometric, app never accesses template

Key finding: GDPR Article 9 special category classification does not apply to this application's biometric handling, as the app uses OS-level APIs that return only a boolean authentication result. The app does not capture, store, or process biometric templates.

Secure Enclave and Keystore Usage

(inferred from expo-secure-store usage — verify against library version changelog)

expo-secure-store wraps iOS Keychain and Android Keystore automatically on supported devices:

[Not documented — WHO: iOS lead; WHAT: What kSecAttrAccessible access class is used for expo-secure-store items? Specifically, is kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly used to prevent Keychain items from surviving app uninstall?; WHERE: Insert in Section 3 — App Uninstall Data Cleanup table, iOS Keychain row]

App Uninstall Data Cleanup

Storage Behavior on Uninstall Residual Data Risk Recommendation
Persisted storage (AsyncStorage-backed) Cleared automatically None N/A
Device storage (MMKV-backed) Cleared automatically None N/A
iOS Keychain (via expo-secure-store) Persists by default unless kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly access class is used High — authentication tokens (access JWT, refresh JWT) may persist after uninstall, allowing re-authentication without user credentials on reinstall Use kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly or explicitly delete all Keychain items on logout
Android Keystore (via expo-secure-store) Cleared on uninstall (Android 9+) Low on modern Android Document minimum Android API level requirement
SharedPrefs (MMKV-backed native module) Cleared automatically None N/A
Platform Storage Backup Behavior User Consent Risk
iOS Persisted storage (AsyncStorage-backed) Included in iCloud backup by default User controls iCloud backup in iOS Settings Session account list, search history, and profile history may be backed up to iCloud and restored to a different device
iOS Keychain (via expo-secure-store) Excluded from iCloud backup by default (unless kSecAttrAccessible allows it) N/A Low
Android Persisted storage (AsyncStorage-backed) Included in Google Drive backup (Android 6+, auto backup) User controls Google account backup Session account data and preferences may back up to Google Drive
Android Keystore (via expo-secure-store) Not backed up N/A Low

Critical finding: The persisted storage layer contains session account data (including stored account credentials for multi-account switching) and search/profile history. This data is included in device backups by default. If a user restores a backup to a new device, their session tokens and browsing history are restored — this may be appropriate for session continuity but represents a privacy risk if the backup is accessed by a third party or restored to an unauthorized device.


4. Device Permission Data Flows

Based on the screen documentation, the following device permissions are requested by the application:


PERM-001: Camera

Field Value
Permission Camera
iOS API AVCaptureDevice (via useCameraPermission hook, openCamera utility)
Android API CAMERA
Data Collected Photos and videos captured by the user for use as profile avatar, post attachments, or message attachments
GDPR Classification Personal Data (photos may contain biometric data of third parties)
Legal Basis Consent (user explicitly initiates camera action)
Purpose Allow users to capture photos/videos for profile setup (onboarding avatar), post composition, and message composition
Data Minimization Camera access is triggered only when user explicitly presses camera button; no background camera access
When Requested When feature is triggered (user presses camera button in composer or profile setup)
Denied Behavior Camera button action does not proceed; no error message documented in screen docs
Permanently Denied Behavior (not documented — requires investigation)
Data Destination Captured image is processed on-device, then uploaded to AT Protocol blob storage on user's PDS (server-side)
Screen Source Feed (/src/view/com/feeds/feed) — ComposerPrompt camera button; Profile setup during onboarding

Source Evidence: Feed screen (/src/view/com/feeds/feed) — Section 6 (User Interactions), Section 13 (Integration Points)

[Not documented — WHO: iOS lead; WHAT: What happens when camera permission is permanently denied — is the user shown a settings redirect prompt?; WHERE: Insert in PERM-001 table, Permanently Denied Behavior row]


PERM-002: Photo Library

Field Value
Permission Photo Library
iOS API PHPhotoLibrary (via usePhotoLibraryPermission, useVideoLibraryPermission, openUnifiedPicker utility)
Android API READ_EXTERNAL_STORAGE / READ_MEDIA_IMAGES / READ_MEDIA_VIDEO (Android 13+)
Data Collected Photos and videos selected by the user from their device library
GDPR Classification Personal Data (photos may contain biometric data, location metadata via EXIF)
Legal Basis Consent (user explicitly initiates photo selection)
Purpose Allow users to select photos/videos for profile avatar, banner, post attachments, and message attachments
Data Minimization Access is triggered only when user explicitly presses gallery button; only selected items are accessed (not full library scan)
When Requested When feature is triggered (user presses gallery button)
Denied Behavior Gallery button action does not proceed
Permanently Denied Behavior (not documented — requires investigation)
Data Destination Selected image/video is processed on-device (resized, compressed), then uploaded to AT Protocol blob storage on user's PDS (server-side). EXIF metadata including GPS location may be included in uploaded files — this is not documented as being stripped.
Screen Source Feed (/src/view/com/feeds/feed) — ComposerPrompt gallery button; Profile header edit dialog; Onboarding profile setup

Source Evidence: Feed screen (/src/view/com/feeds/feed) — Section 6, Section 13

Special assessment — EXIF metadata: Photos selected from the device library may contain EXIF metadata including GPS coordinates, device model, and timestamp. The documentation does not indicate whether EXIF data is stripped before upload. If GPS coordinates are included in uploaded photos, this constitutes precise location data processing under GDPR Article 4(1) and CCPA.

[Not documented — WHO: Backend lead; WHAT: Does the application strip EXIF metadata (including GPS coordinates) from photos before uploading to the AT Protocol blob storage?; WHERE: Insert in PERM-002 table, Data Destination row, and in DC-007 (Photo/Video Data) in the Data Category Inventory]


PERM-003: Contacts

Field Value
Permission Contacts
iOS API CNContactStore (via expo-contacts, Contacts.isAvailableAsync())
Android API READ_CONTACTS
Data Collected Device phone contacts (names, phone numbers, email addresses)
GDPR Classification Sensitive Personal Data — contacts include third-party PII of individuals who have not consented to this app's data processing
Legal Basis Consent (user explicitly initiates Find Contacts flow) — however, the legal basis for processing third-party contacts data (the contacts themselves) requires separate analysis
Purpose Match device contacts against registered Bluesky accounts to help users find people they know
Data Minimization (not documented — requires investigation: are all contacts uploaded, or only hashed phone numbers?)
When Requested When user initiates Find Contacts flow (/find-contacts-flow)
Denied Behavior Admonition error block shown in Intro component; import button not shown
Permanently Denied Behavior Same as denied — Admonition shown
Data Destination Uploaded to Bluesky servers for matching against registered accounts. The getAllListMembers and contact upload APIs are called via the AT Protocol agent.
Screen Source Find Contacts Flow (/find-contacts-flow), Find Contacts Settings (/settings/find-contacts-settings)

Source Evidence: Find Contacts Flow (/find-contacts-flow) — Section 1, Section 5; Find Contacts Settings (/settings/find-contacts-settings) — Section 5

Special assessment — Third-party PII: Contacts data includes PII of third parties (the contacts themselves) who have not consented to the Bluesky application's data processing. Under GDPR, this requires a separate legal basis for processing third-party data. The legitimate interest basis may apply (helping users find friends), but a Legitimate Interest Assessment (LIA) should be conducted. Under CCPA, contacts data may constitute "sensitive personal information" if it includes precise geolocation or other sensitive categories.

[Not documented — WHO: Backend lead; WHAT: (1) Are device contacts uploaded in plaintext or as hashed values (e.g., SHA-256 of phone numbers)? (2) How long are uploaded contacts retained on Bluesky servers? (3) Are contacts deleted from Bluesky servers when the user removes their contact data via the "Remove all contacts" button?; WHERE: Insert in PERM-003 table, Data Destination row, and in PA-009 (Contact Import Processing) in the ROPA section]


5. Data Category Inventory

ID Data Category Classification Examples Found Collection Screens Storage Location On-Device Storage Legal Basis
DC-001 Authentication Credentials Sensitive Access JWT, refresh JWT, session tokens Login Form, Choose Account Form, Signup flow Server DB + On-device Keychain (iOS) / Keystore (Android) via expo-secure-store Contract (account access)
DC-002 Account Identity Personal DID, handle, display name, email address Account Settings, Login Form, Signup flow Server DB + On-device Persisted storage (AsyncStorage-backed) — account list Contract
DC-003 Profile Information Personal Display name, bio/description, avatar image, banner image, date of birth Profile header, Edit Profile Dialog, Account Settings, Onboarding Server DB + On-device (avatar/banner cached) In-memory (TanStack Query cache) Contract
DC-004 Social Graph Personal Follower list, following list, block list, mute list Profile Followers, Profile Follows, Known Followers Server DB None (fetched on demand) Contract
DC-005 Post Content Personal Post text, embedded media, rich text facets, reply context Feed, Post Thread, Conversation Server DB In-memory (TanStack Query cache) Contract
DC-006 Direct Messages Personal Message text, message metadata, conversation members Conversation, Chat List, Inbox Server DB (chat service) In-memory only Contract
DC-007 Photo/Video Data Personal Photos and videos selected from device library or captured by camera; may include EXIF metadata with GPS coordinates Feed (ComposerPrompt), Profile header (avatar/banner), Onboarding Server DB (blob storage) In-memory during selection; uploaded to server Consent
DC-008 Search History Personal Recent search terms (up to 6), recently viewed profile DIDs (up to 10) Search Shell On-device only Persisted storage (AsyncStorage-backed), keyed by account DID Legitimate Interest (personalization)
DC-009 Notification Preferences Personal Push/in-app notification settings per notification type, filter settings Notification Settings screens Server DB + On-device Persisted storage (AsyncStorage-backed) Contract
DC-010 Language Preferences Personal App UI language, primary language, content languages Language Settings On-device Persisted storage (AsyncStorage-backed) Contract
DC-011 Appearance Preferences Personal Color mode, dark theme, font family, font scale, app icon selection Appearance Settings On-device Persisted storage (AsyncStorage-backed) Contract
DC-012 Feed Preferences Personal Saved feeds, pinned feeds, following feed preferences, thread preferences Saved Feeds, Following Feed Preferences, Thread Preferences Server DB + On-device Persisted storage (AsyncStorage-backed) Contract
DC-013 Interest Tags Personal Selected interest categories (e.g., "sports", "tech") Interests Settings, Onboarding Server DB None (fetched from preferences API) Consent
DC-014 Device Contacts Sensitive Phone contacts (names, phone numbers, email addresses) — third-party PII Find Contacts Flow Server DB (uploaded) None (not stored on-device after upload) Consent (with LIA required for third-party data)
DC-015 Age/Date of Birth Sensitive Date of birth (used for age gating — 13+ and 18+ checks) Signup flow, Account Settings (Birthday) Server DB None (not stored on-device) Legal Obligation (COPPA compliance)
DC-016 Email Address Personal Email address for account verification, 2FA, password reset Account Settings, Login Form, Signup flow Server DB On-device (session account object in persisted storage) Contract
DC-017 App Passwords Personal App password names, creation dates, privileged status App Passwords Settings Server DB None (plaintext password shown once, not stored) Contract
DC-018 Activity Subscriptions Personal List of accounts the user has subscribed to for activity notifications Activity Notification Settings Server DB None (fetched on demand) Contract
DC-019 Analytics/Behavioral Data Personal User interactions (post views, feed refreshes, search queries, profile visits, follow actions, navigation patterns), device identifiers All screens (via ax.metric() calls) Third-party analytics service (provider unknown) None (transmitted to analytics service) Consent (if analytics provider requires it) / Legitimate Interest
DC-020 Notification Sound Preferences Personal playSoundChat boolean Messages Settings On-device Native SharedPrefs module (MMKV-backed) Contract
DC-021 Verification Status Personal Account verification status, verification role Profile header, Account Settings Server DB None (fetched from profile API) Contract
DC-022 Starter Pack Data Personal Starter pack name, description, member list, feed list Starter Pack screens Server DB None (fetched on demand) Contract
DC-023 List Data Personal List name, description, member list, list type (mod/curated) List screens Server DB None (fetched on demand) Contract
DC-024 Labeler Subscription Data Personal Subscribed labelers, per-labeler label preferences Verification Settings, Labels section Server DB None (fetched from preferences API) Consent

6. Records of Processing Activities (ROPA)


PA-001: User Authentication and Session Management

Field Value
Purpose Authenticate users and maintain session state across app launches
Legal Basis Performance of Contract (GDPR Art. 6(1)(b))
Data Categories DC-001 (Authentication Credentials), DC-002 (Account Identity), DC-016 (Email Address)
Data Subjects Registered Bluesky users
Recipients Bluesky PDS (Personal Data Server) — AT Protocol backend
On-Device Processing Session tokens validated locally; account list maintained for multi-account switching
On-Device Storage Authentication tokens: Keychain (iOS) / Keystore (Android) via expo-secure-store. Account list (DID, handle, email): Persisted storage (AsyncStorage-backed).
Transfers AT Protocol API calls to user's PDS (may be cross-border depending on PDS location)
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long are session tokens and account records retained on the PDS?; WHERE: Insert in PA-001 table, Retention — Server row]
Retention — On-Device Authentication tokens: Until explicit logout or app uninstall (iOS Keychain may persist post-uninstall). Account list: Until account removed or app uninstalled.
Security Measures Keychain/Keystore encryption for tokens; TLS for API transmission; email verification for sensitive operations
Source Screen(s) Login Form, Choose Account Form, Deactivated, Signup flow

Source Evidence: Login Form (/login/login-form), Choose Account Form (/login/choose-account-form), Account Settings (/settings/account-settings)


PA-002: Profile Data Processing

Field Value
Purpose Display user profiles, enable profile editing, support social graph features
Legal Basis Performance of Contract (GDPR Art. 6(1)(b))
Data Categories DC-003 (Profile Information), DC-004 (Social Graph), DC-021 (Verification Status)
Data Subjects Registered Bluesky users (both profile owners and viewers)
Recipients Bluesky AppView (read); User's PDS (write)
On-Device Processing Profile data cached in TanStack Query in-memory cache; moderation decisions computed client-side via moderateProfile()
On-Device Storage In-memory only (TanStack Query cache, 5-minute GC time by default)
Transfers AT Protocol API calls; cross-border if PDS is in different jurisdiction
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long are profile records retained after account deletion?; WHERE: Insert in PA-002 table, Retention — Server row]
Retention — On-Device In-memory only; cleared when app is closed or cache expires
Security Measures TLS for API transmission; moderation-aware rendering (blur/hide based on labels)
Source Screen(s) Profile Header Standard, Profile Header Labeler, Edit Profile Dialog, Account Settings

PA-003: Direct Messaging

Field Value
Purpose Enable private one-on-one messaging between users
Legal Basis Performance of Contract (GDPR Art. 6(1)(b))
Data Categories DC-006 (Direct Messages), DC-002 (Account Identity)
Data Subjects Registered Bluesky users who send or receive messages
Recipients Bluesky Chat Service (separate from main PDS)
On-Device Processing Messages held in-memory during active conversation; polling every 10 seconds when screen is focused
On-Device Storage In-memory only; no local message persistence documented
Transfers AT Protocol chat API calls to Bluesky chat service; cross-border transfer possible
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long are direct messages retained on the chat service? Are deleted messages purged immediately?; WHERE: Insert in PA-003 table, Retention — Server row]
Retention — On-Device In-memory only; cleared when app is closed
Security Measures TLS for API transmission; age assurance gate (AgeRestrictedScreen); email verification required to send messages
Source Screen(s) Conversation, Chat List, Inbox, Messages Settings

PA-004: Content Feed Processing

Field Value
Purpose Display personalized and algorithmic content feeds; track post engagement for feed feedback
Legal Basis Performance of Contract (GDPR Art. 6(1)(b)); Legitimate Interest for feed personalization (GDPR Art. 6(1)(f))
Data Categories DC-005 (Post Content), DC-019 (Analytics/Behavioral Data), DC-012 (Feed Preferences)
Data Subjects Registered Bluesky users
Recipients Bluesky AppView; Feed Generator servers (third-party); Analytics service (provider unknown)
On-Device Processing Feed items cached in TanStack Query; post view tracking (40% visible for 500ms); feed feedback signals (like/dislike) sent to feed generators
On-Device Storage In-memory only (TanStack Query cache)
Transfers AT Protocol API calls; feed generator API calls (third-party servers); analytics events to unknown provider
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long are feed interaction signals retained by feed generators?; WHERE: Insert in PA-004 table, Retention — Server row]
Retention — On-Device In-memory only; 5-minute GC time by default
Security Measures TLS for API transmission; moderation-aware rendering
Source Screen(s) Feed, Search Shell (Explore), Topic, Hashtag

PA-005: Search and Discovery

Field Value
Purpose Enable content and user discovery; personalize search results
Legal Basis Performance of Contract (GDPR Art. 6(1)(b)); Legitimate Interest for search history (GDPR Art. 6(1)(f))
Data Categories DC-008 (Search History), DC-019 (Analytics/Behavioral Data)
Data Subjects Registered Bluesky users
Recipients Bluesky AppView (search API); Analytics service
On-Device Processing Search terms stored locally (up to 6); profile history stored locally (up to 10 DIDs); search queries augmented with user DID for personalization
On-Device Storage Persisted storage (AsyncStorage-backed), keyed by account DID: [did, 'searchTermHistory'] and [did, 'searchAccountHistory']
Transfers AT Protocol search API calls; analytics events
Retention — Server N/A (search history is on-device only)
Retention — On-Device Until user clears history (individual items removable via X button) or account is removed
Security Measures History scoped to account DID (prevents cross-account leakage); unauthenticated users use 'pwi' key
Source Screen(s) Search Shell (/search/shell)

PA-006: Notification Preference Management

Field Value
Purpose Allow users to configure notification delivery preferences per notification type
Legal Basis Performance of Contract (GDPR Art. 6(1)(b))
Data Categories DC-009 (Notification Preferences), DC-020 (Notification Sound Preferences)
Data Subjects Registered Bluesky users
Recipients Bluesky PDS (preferences API); Native OS notification service (APNs/FCM)
On-Device Processing Notification sound preference stored in native SharedPrefs module; push notification token managed by OS
On-Device Storage Notification sound: Native SharedPrefs (MMKV-backed). Push notification token: Managed by OS (APNs/FCM), not directly by app.
Transfers Preferences written to AT Protocol PDS; push notification tokens transmitted to APNs (iOS) or FCM (Android)
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long are notification preferences retained after account deletion?; WHERE: Insert in PA-006 table, Retention — Server row]
Retention — On-Device Until app uninstall
Security Measures TLS for API transmission
Source Screen(s) All notification settings screens under /settings/notification-settings/

PA-007: Account Creation (Signup)

Field Value
Purpose Create new AT Protocol accounts on the Bluesky network
Legal Basis Performance of Contract (GDPR Art. 6(1)(b)); Legal Obligation for age verification (GDPR Art. 6(1)(c) — COPPA)
Data Categories DC-002 (Account Identity), DC-015 (Age/Date of Birth), DC-016 (Email Address), DC-001 (Authentication Credentials)
Data Subjects New users registering for Bluesky
Recipients Bluesky PDS; hCaptcha (CAPTCHA verification)
On-Device Processing Age validation (is13(), is18()) performed client-side; CAPTCHA challenge rendered in WebView/iframe
On-Device Storage None during signup; credentials stored in Keychain after successful account creation
Transfers Account creation API call to PDS; CAPTCHA verification to hCaptcha servers
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long is date of birth retained after account creation? Is it stored or only used for age verification?; WHERE: Insert in PA-007 table, Retention — Server row]
Retention — On-Device Date of birth: Not stored on-device after signup. Email: Stored in session account object in persisted storage.
Security Measures CAPTCHA verification; email verification; age gating (13+ required, 18+ for certain features)
Source Screen(s) Signup flow screens (/signup/*)

PA-008: Analytics and Behavioral Tracking

Field Value
Purpose Track user interactions for product analytics, feature usage measurement, and recommendation improvement
Legal Basis [Not documented — WHO: DPO; WHAT: What is the legal basis for analytics data collection? Is user consent obtained? Is legitimate interest relied upon, and if so, has an LIA been conducted?; WHERE: Insert in PA-008 table, Legal Basis row]
Data Categories DC-019 (Analytics/Behavioral Data)
Data Subjects All app users (authenticated and unauthenticated)
Recipients Unknown analytics provider (abstracted behind useAnalytics() / ax.metric())
On-Device Processing Events collected synchronously at interaction points; transmitted to analytics service
On-Device Storage None documented (events appear to be transmitted immediately)
Transfers Analytics events transmitted to unknown provider; cross-border transfer possible
Retention — Server [Not documented — WHO: DPO; WHAT: What is the analytics provider's data retention period? Where is analytics data stored geographically?; WHERE: Insert in PA-008 table, Retention — Server row]
Retention — On-Device None (events transmitted immediately)
Security Measures [Not documented — WHO: Engineering lead; WHAT: Is analytics data anonymized or pseudonymized before transmission? Are user DIDs transmitted in analytics events?; WHERE: Insert in PA-008 table, Security Measures row]
Source Screen(s) All screens (analytics calls present throughout the application)

PA-009: Contact Import and Matching

Field Value
Purpose Help users find Bluesky accounts of people they know by matching device contacts against registered users
Legal Basis Consent (GDPR Art. 6(1)(a)) for the user's own data; separate legal basis required for third-party contacts data — Legitimate Interest (GDPR Art. 6(1)(f)) with LIA required
Data Categories DC-014 (Device Contacts)
Data Subjects The authenticated user; third-party individuals whose contact information is uploaded
Recipients Bluesky servers (contact matching service)
On-Device Processing Contacts read from device; availability checked via expo-contacts; uploaded to server for matching
On-Device Storage None (contacts not stored on-device after upload)
Transfers Contact data uploaded to Bluesky servers; cross-border transfer possible
Retention — Server [Not documented — WHO: Backend lead; WHAT: (1) How long are uploaded contacts retained? (2) Are contacts deleted when user removes data via "Remove all contacts"? (3) Are contacts stored as plaintext or hashed?; WHERE: Insert in PA-009 table, Retention — Server row]
Retention — On-Device None
Security Measures User must explicitly initiate the flow; "Remove all contacts" option available in settings
Source Screen(s) Find Contacts Flow (/find-contacts-flow), Find Contacts Settings (/settings/find-contacts-settings)

PA-010: Account Deletion

Field Value
Purpose Enable users to permanently delete their Bluesky account
Legal Basis Legal Obligation (GDPR Art. 17 — Right to Erasure)
Data Categories DC-001 through DC-024 (all data categories)
Data Subjects Registered Bluesky users requesting deletion
Recipients Bluesky PDS; Bluesky Chat Service
On-Device Processing Chat service notified before PDS deletion; session cleared after deletion
On-Device Storage All on-device data cleared on app uninstall (except iOS Keychain items if not explicitly deleted)
Transfers Deletion API calls to PDS and chat service
Retention — Server [Not documented — WHO: Backend lead; WHAT: How long does it take for account data to be fully purged from all Bluesky servers after deletion? Are backups purged?; WHERE: Insert in PA-010 table, Retention — Server row]
Retention — On-Device AsyncStorage/MMKV: Cleared on uninstall. iOS Keychain: May persist post-uninstall — explicit deletion required.
Security Measures Two-factor deletion flow (email code + password); chat service notified; session invalidated
Source Screen(s) Account Settings (/settings/account-settings) — Delete Account dialog

7. Screen-by-Screen Data Flows

Due to the large number of screens (131) in scope, this section presents representative high-risk and high-complexity screens in detail. Lower-risk screens with similar patterns are grouped by category.


7.1 Inbox (/messages/inbox)

Data Profile:

Aspect Assessment
Data Collection No — displays existing conversations
Data Display Yes — conversation member profiles (avatar, display name, handle), last message preview, unread count
Data Modification Yes — mark as read, accept/reject/delete conversations, block users
Data Deletion Yes — leave/delete conversations
External Sharing No direct third-party sharing; analytics events fired on conversation open
Sensitive Data Yes — direct message content previews; age-assurance gated
On-Device Storage In-memory only (TanStack Query cache)
Device Permissions None
Privacy Risk Level Medium

Data Collection Points:

Field Data Category Required Validation Legal Basis On-Device Storage Notes
N/A N/A N/A N/A N/A N/A No user input collected on this screen

Data Flows:

Privacy Concerns:


DF-001: Analytics Event on Conversation Open

Field Value
Risk Level Low
Data Affected DC-019 (Analytics/Behavioral Data)
Regulation GDPR Art. 6 (legal basis for analytics); CCPA §1798.100
Description ax.metric('chat:open', {logContext: 'ChatsList'}) is fired when a user opens a conversation. This transmits behavioral data to an unknown analytics provider. The legal basis for this analytics collection is not documented.
Evidence Inbox screen documentation Section 10: "ax.metric('chat:open', {logContext: 'ChatsList'}) — analytics event fired when a non-deleted-account conversation row is tapped."
Recommendation Identify the analytics provider; ensure a DPA is in place; document the legal basis for analytics collection; consider whether messaging behavior analytics requires explicit consent given the sensitive nature of messaging data.

7.2 Find Contacts Flow (/find-contacts-flow)

Data Profile:

Aspect Assessment
Data Collection Yes — device contacts (names, phone numbers, email addresses)
Data Display Yes — matched Bluesky profiles
Data Modification Yes — follow matched users
Data Deletion Yes — remove all contact data
External Sharing Yes — contacts uploaded to Bluesky servers
Sensitive Data Yes — third-party PII (device contacts)
On-Device Storage None (contacts not stored on-device)
Device Permissions Contacts (READ_CONTACTS / CNContactStore)
Privacy Risk Level High

Data Collection Points:

Field Data Category Required Validation Legal Basis On-Device Storage Notes
Device contacts DC-014 Yes (for feature) Contacts.isAvailableAsync() check Consent None Third-party PII — contacts have not consented to Bluesky processing

Data Flows:

Privacy Concerns:


DF-002: Third-Party PII in Contact Upload

Field Value
Risk Level High
Data Affected DC-014 (Device Contacts)
Regulation GDPR Art. 6 (legal basis for third-party data), Art. 13/14 (transparency), Art. 35 (DPIA may be required); CCPA §1798.140 (sensitive personal information)
Description Device contacts include PII of third parties (the contacts themselves) who have not consented to Bluesky's data processing. The legal basis for processing this third-party data is not documented. A Legitimate Interest Assessment (LIA) is required if legitimate interest is relied upon.
Evidence Find Contacts Settings documentation Section 5: "Contact data uploaded to Bluesky servers for matching against registered accounts."
Recommendation (1) Conduct a Legitimate Interest Assessment (LIA) for contact data processing. (2) Determine whether contacts are uploaded as plaintext or hashed — hashing would significantly reduce privacy risk. (3) Ensure the privacy notice discloses contact data processing. (4) Consider whether a DPIA is required under GDPR Art. 35 (large-scale processing of personal data).

DF-003: Contact Data Retention Unknown

Field Value
Risk Level High
Data Affected DC-014 (Device Contacts)
Regulation GDPR Art. 5(1)(e) (storage limitation), Art. 17 (right to erasure)
Description The retention period for uploaded contact data on Bluesky servers is not documented. It is unclear whether the "Remove all contacts" button in settings triggers immediate deletion from all server systems including backups.
Evidence Find Contacts Settings documentation Section 5: "agent.app.bsky.contact.removeData({}) — notifies chat service of deletion."
Recommendation Document the contact data retention period. Verify that "Remove all contacts" triggers complete deletion from all server systems. Communicate the retention period to users in the privacy notice.

7.3 Account Settings (/settings/account-settings)

Data Profile:

Aspect Assessment
Data Collection Yes — email, password, handle, date of birth
Data Display Yes — current email, email verification status, handle, automation label status
Data Modification Yes — all account credentials and identity
Data Deletion Yes — account deactivation and deletion
External Sharing No direct third-party sharing
Sensitive Data Yes — email address, password, date of birth
On-Device Storage None (all data server-side)
Device Permissions Clipboard (for DNS record copying)
Privacy Risk Level Medium

Privacy Concerns:


DF-004: Chat Data Export Contains Sent Messages Only

Field Value
Risk Level Low
Data Affected DC-006 (Direct Messages)
Regulation GDPR Art. 20 (data portability)
Description The chat data export (chat.bsky.actor.exportAccountData) exports only sent messages, not received messages. This may not satisfy GDPR Art. 20 data portability requirements, which require all personal data provided by the data subject.
Evidence Account Settings documentation Section 5: "The JSONL export contains only sent messages, not received messages (noted in UI copy)."
Recommendation Assess whether the current export scope satisfies GDPR Art. 20 data portability requirements. Consider whether received messages should also be exportable.

DF-005: iOS Keychain Persistence Post-Uninstall

Field Value
Risk Level High
Data Affected DC-001 (Authentication Credentials)
Regulation GDPR Art. 17 (right to erasure), Art. 32 (security of processing); MASVS-STOR-1
Description Authentication tokens stored in iOS Keychain via expo-secure-store may persist after app uninstall by default. If a user uninstalls the app expecting all data to be deleted, their authentication tokens may remain accessible on the device and could be used to re-authenticate on reinstall without entering credentials.
Evidence On-Device Storage Privacy Assessment (Section 3): iOS Keychain persists by default unless kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly is used.
Recommendation (1) Verify the kSecAttrAccessible access class used by expo-secure-store. (2) If not already using kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, implement explicit Keychain item deletion on logout. (3) Document this behavior in the privacy notice.

7.4 Search Shell (/search/shell)

Data Profile:

Aspect Assessment
Data Collection Yes — search queries, profile interaction history
Data Display Yes — search results (posts, profiles, feeds), trending topics, suggested accounts
Data Modification No
Data Deletion Yes — individual search history items removable
External Sharing Yes — analytics events for search interactions
Sensitive Data No
On-Device Storage Persisted storage (AsyncStorage-backed) — search history and profile history
Device Permissions None
Privacy Risk Level Medium

Data Collection Points:

Field Data Category Required Validation Legal Basis On-Device Storage Notes
Search query text DC-008 (Search History) No None Legitimate Interest Persisted storage (AsyncStorage-backed), keyed by [did, 'searchTermHistory'] Up to 6 terms stored; user can delete individual items
Viewed profile DIDs DC-008 (Search History) No None Legitimate Interest Persisted storage (AsyncStorage-backed), keyed by [did, 'searchAccountHistory'] Up to 10 DIDs stored; 400ms delay before storage

Privacy Concerns:


DF-006: Search History in Device Backup

Field Value
Risk Level Medium
Data Affected DC-008 (Search History)
Regulation GDPR Art. 32 (appropriate technical measures); MASVS-STOR-1
Description Search history (recent search terms and recently viewed profile DIDs) is stored in persisted storage (AsyncStorage-backed) which is included in iOS iCloud backups and Android Google Drive auto-backups by default. This means a user's search history could be restored to a different device or accessed via a backup.
Evidence Search Shell documentation Section 12: "useStorage(account, [did, 'searchTermHistory']) — Stores up to 6 recent search term strings, keyed by account DID."
Recommendation Assess whether search history needs to be included in device backups. If not, implement backup exclusion for these storage keys. Alternatively, document this behavior in the privacy notice.

DF-007: Analytics Events Include Profile DIDs and Search Queries

Field Value
Risk Level Medium
Data Affected DC-019 (Analytics/Behavioral Data)
Regulation GDPR Art. 6 (legal basis), Art. 25 (data minimization)
Description Multiple analytics events in the Search screen transmit profile DIDs and search query content to an unknown analytics provider: ax.metric('search:autocomplete:press', {profileDid, position}), ax.metric('search:recent:press', {profileDid, position}), ax.metric('suggestedUser:seen', {suggestedDid, ...}).
Evidence Search Shell documentation Section 10: Multiple ax.metric calls with profileDid and suggestedDid parameters.
Recommendation Identify the analytics provider. Assess whether profile DIDs constitute personal data in the analytics context. Consider pseudonymizing DIDs before transmission. Ensure the legal basis for analytics collection is documented.

7.5 Conversation (/messages/conversation)

Data Profile:

Aspect Assessment
Data Collection No (messages composed in child component)
Data Display Yes — message content, sender profiles
Data Modification No
Data Deletion No
External Sharing No
Sensitive Data Yes — direct message content; age-assurance gated
On-Device Storage In-memory only
Device Permissions None
Privacy Risk Level Medium

Privacy Concerns:


DF-008: Age Assurance Gate for Messaging

Field Value
Risk Level Low
Data Affected DC-006 (Direct Messages)
Regulation GDPR Art. 8 (children's data); applicable national age verification laws
Description The AgeRestrictedScreen wrapper enforces age assurance before rendering the conversation screen. This is a positive privacy control. However, the specific age threshold and verification mechanism are not documented in the screen documentation.
Evidence Conversation documentation Section 2: "AgeRestrictedScreen wrapper enforces age-related access control."
Recommendation Document the age threshold for messaging access and the verification mechanism used by AgeRestrictedScreen. Ensure this is disclosed in the privacy notice.

7.6 Signup Flow (Multiple Screens)

Data Profile:

Aspect Assessment
Data Collection Yes — email, password, handle, date of birth, CAPTCHA verification
Data Display No
Data Modification No
Data Deletion No
External Sharing Yes — CAPTCHA data to hCaptcha
Sensitive Data Yes — date of birth, email, password
On-Device Storage None during signup
Device Permissions None
Privacy Risk Level Medium

Privacy Concerns:


DF-009: hCaptcha Third-Party Data Processing

Field Value
Risk Level Medium
Data Affected DC-019 (Analytics/Behavioral Data) — device fingerprinting by hCaptcha
Regulation GDPR Art. 28 (processor requirements), Art. 13 (transparency)
Description The CAPTCHA step loads hCaptcha in a WebView/iframe, which may collect device information (IP address, browser fingerprint, behavioral data) for bot detection. This is a third-party data processor relationship that requires a Data Processing Agreement (DPA).
Evidence Captcha Web documentation Section 13: "hCaptcha domains allowlisted: js.hcaptcha.com, newassets.hcaptcha.com, api2.hcaptcha.com."
Recommendation Verify that a DPA is in place with hCaptcha. Disclose hCaptcha data processing in the privacy notice. Assess whether hCaptcha's data collection is proportionate to the bot-detection purpose.

8. Data Flow Inventory

Master table of all identified data flows, sorted by risk level:

ID Screen Data Category Direction Destination Storage Mechanism Risk Level Regulation Recommendation Phase
DF-002 Find Contacts Flow DC-014 (Device Contacts) Out Bluesky servers None (server-side) High GDPR Art. 6, 13, 35 Phase 1 (Immediate)
DF-003 Find Contacts Flow DC-014 (Device Contacts) Out Bluesky servers None High GDPR Art. 5(1)(e), 17 Phase 1 (Immediate)
DF-005 Account Settings DC-001 (Auth Credentials) On-Device iOS Keychain Keychain High GDPR Art. 17, 32; MASVS-STOR-1 Phase 1 (Immediate)
DF-001 Inbox DC-019 (Analytics) Out Unknown analytics provider None Low GDPR Art. 6; CCPA Phase 2 (Short-Term)
DF-006 Search Shell DC-008 (Search History) On-Device Persisted storage (backup-eligible) AsyncStorage-backed Medium GDPR Art. 32; MASVS-STOR-1 Phase 2 (Short-Term)
DF-007 Search Shell DC-019 (Analytics) Out Unknown analytics provider None Medium GDPR Art. 6, 25 Phase 2 (Short-Term)
DF-009 Signup (Captcha) DC-019 (Analytics) Out hCaptcha None Medium GDPR Art. 28, 13 Phase 2 (Short-Term)
DF-004 Account Settings DC-006 (Direct Messages) Out User device (export) None Low GDPR Art. 20 Phase 3 (Medium-Term)
DF-008 Conversation DC-006 (Direct Messages) In In-memory In-memory Low GDPR Art. 8 Phase 4 (Backlog)

9. Third-Party Data Sharing

Service Integration Method Data Shared Purpose Legal Basis DPA Required Transfer Mechanism Risk Level
Bluesky PDS (Personal Data Server) AT Protocol XRPC API DC-001 through DC-023 (all user data) Core social platform functionality Contract N/A (first-party service) TLS; cross-border if PDS in different jurisdiction Low (first-party)
Bluesky Chat Service AT Protocol XRPC API (with DM_SERVICE_HEADERS) DC-006 (Direct Messages) Direct messaging Contract N/A (first-party service) TLS Low (first-party)
Bluesky AppView AT Protocol XRPC API DC-003, DC-004, DC-005 (profile, social graph, posts) Content aggregation and search Contract N/A (first-party service) TLS Low (first-party)
Feed Generator Servers (third-party) AT Protocol XRPC API DC-005 (Post content context), DC-019 (feed feedback signals) Custom algorithmic feeds Legitimate Interest Yes — DPA required TLS; cross-border possible Medium
hCaptcha WebView/iframe (web), WebView (native) Device fingerprint, behavioral data, IP address Bot detection during signup Legitimate Interest / Consent Yes — DPA required TLS; cross-border (hCaptcha servers) Medium
Unknown Analytics Provider Custom useAnalytics() abstraction DC-019 (user interactions, profile DIDs, post URIs, search queries, navigation patterns) Product analytics Unknown — requires investigation Yes — DPA required Unknown High
APNs (Apple Push Notification Service) iOS OS-level Device push token, notification metadata Push notifications Contract N/A (Apple standard service) TLS Low
FCM (Firebase Cloud Messaging) Android OS-level Device push token, notification metadata Push notifications Contract N/A (Google standard service) TLS Low

Critical finding — Unknown Analytics Provider: The application uses a custom analytics abstraction (useAnalytics() / ax.metric()) throughout all 131 screens. The underlying analytics provider is not identifiable from the codebase documentation. This is a significant gap:

[Not documented — WHO: DPO and Engineering lead; WHAT: (1) What is the underlying analytics provider behind useAnalytics()? (2) Is a DPA in place with this provider? (3) What data transfer mechanism is used for cross-border transfers? (4) What is the data retention period? (5) Is user consent obtained for analytics collection?; WHERE: Insert in Section 9 (Third-Party Data Sharing) — Unknown Analytics Provider row, and in PA-008 (Analytics and Behavioral Tracking) in the ROPA section]


10. Data Retention & Deletion

Data Category Retention — Server Retention — On-Device Storage Storage Mechanism Deletion Mechanism Right to Erasure Notes
DC-001 (Auth Credentials) [Not documented] Until logout or uninstall (iOS Keychain may persist post-uninstall) Keychain (iOS) / Keystore (Android) Explicit logout; app uninstall (Android); explicit Keychain deletion required on iOS Supported (logout clears tokens) iOS Keychain persistence post-uninstall is a right-to-erasure gap
DC-002 (Account Identity) [Not documented] Until account removed from device or app uninstalled Persisted storage (AsyncStorage-backed) Account removal; app uninstall Supported (account deletion API) Account list in persisted storage includes email and handle
DC-003 (Profile Information) [Not documented] In-memory only (5-min GC) TanStack Query cache App close; cache expiry Supported (account deletion API)
DC-006 (Direct Messages) [Not documented] In-memory only TanStack Query cache App close Supported (account deletion API notifies chat service) Export includes sent messages only
DC-008 (Search History) N/A (on-device only) Until user clears or account removed Persisted storage (AsyncStorage-backed) Individual item deletion (X button); account removal N/A (on-device only) Included in device backups
DC-009 (Notification Preferences) [Not documented] Until app uninstall Persisted storage + Native SharedPrefs App uninstall Supported (account deletion)
DC-014 (Device Contacts) [Not documented] None (not stored on-device) N/A "Remove all contacts" button in settings Supported (remove data API) Retention period on server unknown
DC-015 (Age/Date of Birth) [Not documented] None N/A Account deletion Supported
DC-019 (Analytics/Behavioral Data) [Not documented — analytics provider unknown] None (transmitted immediately) N/A [Unknown — depends on analytics provider] [Unknown] Critical gap — analytics provider and retention unknown

Mobile-specific retention considerations:

  1. iOS Keychain persistence post-uninstall: Authentication tokens stored via expo-secure-store may persist after app uninstall on iOS. This is a GDPR Art. 17 right-to-erasure concern. Users who uninstall the app expecting all data to be deleted may have authentication tokens remaining on their device.

  2. AsyncStorage backup exposure: Search history, profile history, and session account data stored in persisted storage (AsyncStorage-backed) are included in iOS iCloud backups and Android Google Drive auto-backups by default. If a user restores a backup to a new device, this data is restored — assess whether this is appropriate for each data type.

  3. App uninstall as deletion trigger: App uninstall clears AsyncStorage/MMKV data on both platforms. However, server-side data (posts, profile, messages, followers) requires an API-level deletion flow via the account deletion feature in Account Settings.


11. Privacy Risk Assessment

Risk ID Risk Description Likelihood Impact Risk Level Data Categories NIST Function Recommendation
PR-001 Unknown analytics provider collecting behavioral data including profile DIDs and search queries without documented legal basis or DPA High High Critical DC-019 Govern Identify analytics provider; establish DPA; document legal basis; assess consent requirements
PR-002 Device contacts (third-party PII) uploaded to Bluesky servers without documented legal basis for third-party data processing High High Critical DC-014 Govern Conduct LIA; document legal basis; assess DPIA requirement; verify hashing of contact data
PR-003 iOS Keychain authentication tokens persisting after app uninstall, creating right-to-erasure gap Medium High High DC-001 Protect Use kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly or implement explicit Keychain deletion on logout
PR-004 Search history and session account data in device backups (iCloud/Google Drive) without user awareness Medium Medium High DC-008, DC-002 Communicate Assess backup exclusion for sensitive storage keys; document in privacy notice
PR-005 EXIF metadata (including GPS coordinates) potentially included in uploaded photos Medium High High DC-007 Protect Implement EXIF stripping before photo upload; document in privacy notice
PR-006 Contact data retention period on Bluesky servers unknown; unclear if "Remove all contacts" triggers complete deletion Medium High High DC-014 Govern Document retention period; verify deletion completeness; communicate to users
PR-007 hCaptcha third-party data processing during signup without documented DPA or user disclosure Low Medium Medium DC-019 Govern Verify DPA with hCaptcha; disclose in privacy notice
PR-008 Feed generator servers (third-party) receiving feed feedback signals without documented DPA Low Medium Medium DC-005, DC-019 Govern Identify feed generator operators; establish DPAs where required
PR-009 Analytics events transmitting profile DIDs without pseudonymization Medium Medium Medium DC-019 Protect Pseudonymize DIDs before analytics transmission; assess data minimization
PR-010 Chat data export (GDPR Art. 20 portability) includes only sent messages, not received messages Low Low Low DC-006 Govern Assess whether current export scope satisfies Art. 20 requirements

12. Remediation Recommendations

Phase 1: Immediate (0-7 days) — Critical Privacy Risks

Phase 2: Short-Term (1-4 weeks) — High-Risk Items

Phase 3: Medium-Term (1-3 months) — Medium-Risk Items

Phase 4: Backlog — Low-Risk Items and Best Practice Improvements


13. Glossary

AT Protocol (atproto): The open, decentralized social networking protocol developed by Bluesky. Defines the API lexicons, data models, and federation mechanisms used by the Bluesky application. All API calls use AT Protocol XRPC methods.

APNs (Apple Push Notification Service): Apple's push notification delivery service for iOS devices. Device push tokens are transmitted to APNs for notification delivery.

AsyncStorage: A React Native key-value storage system that stores data as plain-text JSON on the device. Data is included in iOS iCloud backups and Android Google Drive auto-backups by default. Not encrypted.

BCR (Binding Corporate Rules): A data transfer mechanism under GDPR that allows multinational companies to transfer personal data within their corporate group across borders.

CCPA/CPRA: California Consumer Privacy Act / California Privacy Rights Act. California state privacy laws granting consumers rights over their personal data.

DID (Decentralized Identifier): A globally unique, persistent identifier for an AT Protocol user account (e.g., did:plc:abc123). Used as the canonical identity key throughout the application.

DPA (Data Processing Agreement): A contract required under GDPR Art. 28 between a data controller and a data processor, governing how the processor handles personal data on behalf of the controller.

DPIA (Data Protection Impact Assessment): A process required under GDPR Art. 35 for processing activities that are likely to result in high risk to individuals' rights and freedoms.

expo-secure-store: An Expo library that wraps iOS Keychain and Android Keystore for encrypted key-value storage. Used for storing authentication tokens.

FCM (Firebase Cloud Messaging): Google's push notification delivery service for Android devices.

GDPR (General Data Protection Regulation): EU regulation governing the processing of personal data of EU residents.

GAID (Google Advertising ID): A unique, user-resettable identifier for advertising on Android devices. Not documented as used in this application.

Handle: A human-readable username in the AT Protocol (e.g., alice.bsky.social). Handles can change; DIDs are permanent.

hCaptcha: A third-party CAPTCHA service used during signup to verify that users are human. Collects device fingerprint and behavioral data.

IDFA (Identifier for Advertisers): A unique, user-resettable identifier for advertising on iOS devices. Not documented as used in this application.

iCloud backup: Apple's cloud backup service for iOS devices. AsyncStorage data is included in iCloud backups by default.

ISO/IEC 27701:2019: International standard for Privacy Information Management Systems (PIMS), extending ISO/IEC 27001 with privacy-specific controls.

Keychain (iOS): Apple's secure credential storage system on iOS. Used by expo-secure-store to store authentication tokens. Keychain items may persist after app uninstall depending on the kSecAttrAccessible access class.

Keystore (Android): Android's hardware-backed key storage system. Used by expo-secure-store to store authentication tokens. Keystore items are cleared on app uninstall (Android 9+).

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: An iOS Keychain access class that restricts items to the current device and requires a device passcode. Items with this class are cleared when the app is uninstalled.

LIA (Legitimate Interest Assessment): A three-part test required under GDPR when relying on legitimate interest as the legal basis for data processing: purpose test, necessity test, and balancing test.

MASVS-STOR: OWASP Mobile Application Security Verification Standard — Storage controls. Defines requirements for secure on-device data storage in mobile applications.

MMKV: A high-performance key-value storage library for mobile applications. Used in this application via the expo-bluesky-swiss-army native module (SharedPrefs) and potentially as the backing store for the persisted storage layer.

NIST Privacy Framework v1.0: A voluntary framework for managing privacy risk, organized around five functions: Identify, Govern, Control, Communicate, and Protect.

PDS (Personal Data Server): In the AT Protocol, the server that hosts a user's data repository. Users may self-host or use a third-party PDS.

PII (Personally Identifiable Information): Information that can be used to identify an individual, either directly or in combination with other data.

ROPA (Records of Processing Activities): A documentation requirement under GDPR Art. 30 for organizations to maintain records of their data processing activities.

SCC (Standard Contractual Clauses): Pre-approved contract clauses issued by the European Commission for transferring personal data from the EU to third countries.

SecureStore (Expo): Expo's wrapper around iOS Keychain and Android Keystore, providing encrypted key-value storage. See expo-secure-store.

Secure Enclave: Apple's dedicated security chip in iPhone 5s and later, used for hardware-backed cryptographic operations including Keychain key storage.

Special Category Data (GDPR Art. 9): Data requiring heightened protection: racial/ethnic origin, political opinions, religious beliefs, genetic data, biometric data (used for identification), health data, sex life/sexual orientation. Biometric data processed by OS-level APIs (Face ID, Touch ID) does not fall under this category for this application.

TanStack Query (React Query): A data-fetching and caching library used throughout the application. Data is stored in-memory with a default 5-minute garbage collection time. Not persisted to disk.

XRPC: The remote procedure call protocol used by AT Protocol for client-server communication. Queries (reads) use GET; procedures (writes) use POST.