Ranger
Privacy Policy

This Privacy Policy ("Policy") describes how Ranger ("Ranger," "we," "us," or "our") collects, uses, discloses, retains, and protects information when you access or use the Ranger mobile application for iOS (the "App"), our website and legal pages hosted at our service endpoints (collectively, the "Services"), and any related application programming interfaces ("APIs"), including the Ranger backend API. This Policy applies to all visitors, registered users, Premium subscribers, and any individual who interacts with Ranger features such as wildlife scanning, collection management, leaderboards, the world map, trading cards, quests, and account settings. By downloading, installing, accessing, or using the Services, you acknowledge that you have read and understood this Policy. If you do not agree with our practices, you must discontinue use of the Services and may request account deletion as described herein.

Document Information and Effective Date

Last updated: June 25, 2026. This version supersedes all prior privacy notices, in-app disclosures, and website summaries relating to Ranger data practices. We encourage you to review this Policy periodically because we may update it to reflect changes in our Services, applicable law, or third-party integrations. Material changes will be communicated through reasonable means, which may include in-app notice, updated "Last updated" date, email to the address associated with your account, or publication on our legal pages. Your continued use of the Services after the effective date of an updated Policy constitutes acceptance of the revised terms, except where applicable law requires a different form of consent.

Article I — Definitions and Interpretation

1.1 Defined Terms

  1. Account means the user record created when you register with an email address and password, sign in with Google OAuth, or otherwise authenticate to Ranger, including the associated Django User object, REST framework authentication Token, and linked Profile.
  2. App means the Ranger iOS application distributed as BirdDex, including on-device Core ML models (BirdModel and INatVision_Small_2_fact256_8bit), SwiftUI views, SwiftData local storage, and client-side integrations.
  3. Authentication Token means the opaque API key issued by django-rest-framework authtoken and stored in the iOS Keychain (service identifier douch3b4g.Ranger, account authToken) with legacy mirroring in UserDefaults.
  4. Backend means the Ranger Django REST API deployed at our then-current SITE_BASE_URL (as configured in server environment), including endpoints such as /sightings/, /leaderboard/, /user-sightings/, /nearby-sightings/, /delete-account/, /auth/login/, /auth/registration/, /create-checkout/, /stripe-webhook/, and related routes.
  5. Display Name means the optional Profile.display_name field (max 100 characters) shown on leaderboards and public profile views; when blank, we derive a fallback from User.first_name or the local-part of User.email.
  6. Field-Verified Sighting means a capture where is_field_verified is true (default), indicating live camera capture rather than photo library import.
  7. Library Upload means a sighting submitted with is_field_verified false, available only to Premium (is_premium) users and tracked via photo_library_uploads_this_month.
  8. Personal Data means information that identifies, relates to, describes, is reasonably capable of being associated with, or could reasonably be linked with you, directly or indirectly, as defined under applicable privacy laws.
  9. Premium means a paid subscription status (Profile.is_premium) managed through Stripe checkout sessions, webhooks, and subscription identifiers stored as stripe_customer_id and stripe_subscription_id.
  10. Processing means any operation performed on Personal Data, whether or not by automated means, including collection, recording, organization, structuring, storage, adaptation, alteration, retrieval, consultation, use, disclosure, dissemination, alignment, combination, restriction, erasure, or destruction.
  11. Sighting means a wildlife observation record comprising species, date, optional image, fun_fact, rarity, category, uuid, coordinates, XP, level, and verification metadata stored in the Sighting model.
  12. Services means the App, Backend, website legal pages (/privacy/, /terms/, /support/), checkout success and cancel pages, and all related functionality.
  13. Third-Party Processor means an entity that processes Personal Data on our behalf or at our direction, including Stripe, optional SMTP providers such as SendGrid, Google for OAuth token verification, and client-initiated requests to Facehash.dev and Wikipedia.

1.2 Interpretation Rules

Headings are for convenience only and do not limit the scope of this Policy. References to "including" or "such as" are illustrative and not exhaustive. Where we describe data fields, we refer to actual model attributes and API payloads implemented in our codebase. Where a feature is optional or environment-dependent (for example, SMTP email delivery when EMAIL_HOST is configured), we disclose both the configured behavior and the absence of processing when not enabled.

Article II — Data Controller and Contact

Ranger operates the Services and determines the purposes and means of processing Personal Data described in this Policy. For purposes of United States state privacy laws, Ranger acts as a "business" or "controller" with respect to the processing activities described herein. Our primary contact for privacy inquiries, data subject requests, and security reports is [email protected]. We respond to verified requests within timeframes required by applicable law and in accordance with the procedures in Article XIV of this Policy.

Article III — Summary of Our Data Practices

Ranger is a wildlife collection application. We collect account credentials and profile statistics to operate your collection, synchronize sightings across devices, and power game features. Species identification using Core ML runs on your iPhone; sighting photos you choose to save are transmitted to our servers as base64-encoded payloads (up to 8,000,000 characters per image field) and stored as image files under media/sightings/. We do not sell Personal Data. We do not engage in cross-app tracking for advertising; our PrivacyInfo.xcprivacy manifest declares NSPrivacyTracking as false. We use third-party payment processing through Stripe. Optional password-reset email may be sent via SMTP when configured. Google Sign-In verifies ID tokens server-side. Avatar images are fetched client-side from Facehash.dev using a deterministic seed derived from display name or email. Wikipedia API calls for species information occur client-side from your device.

Article IV — Categories of Personal Data We Collect

The following sections describe each category of data we collect, the source of collection, representative examples drawn from our implementation, whether the data is required or optional, and typical retention. This Article is intended to satisfy transparency obligations under the California Consumer Privacy Act as amended by the California Privacy Rights Act (CCPA/CPRA), and analogous disclosure requirements in other jurisdictions.

4.1 Account and Identity Data

  1. Email Address. Collected at registration via dj-rest-auth at /auth/registration/ using CustomRegisterSerializer with ACCOUNT_AUTHENTICATION_METHOD = email. Stored as User.email. Used for login, password reset, Stripe checkout customer_email, and Google account linking when email matches. Status: Required for email/password accounts.
  2. Password (Hashed). Collected at registration and password change. Processed using Django's password hashers (PBKDF2 or configured algorithm); we do not store plaintext passwords. Google-created accounts receive set_unusable_password(). Status: Required for email/password accounts; not used for Google-only accounts.
  3. Username. Internally set equal to email per CustomRegisterSerializer.get_cleaned_data(); ACCOUNT_USERNAME_REQUIRED = False. Status: System field; not separately collected from users.
  4. First Name. May be populated from Google OAuth given_name on first Google login. Status: Optional.
  5. Google ID Token. Transmitted to POST /google-login/ for server verification via https://oauth2.googleapis.com/tokeninfo; not stored persistently after verification. Status: Required only for Google Sign-In flow.
  6. Authentication Token Key. Opaque string returned as key from registration, login, and Google login; stored server-side in authtoken Token model; client stores in Keychain and UserDefaults authToken. Status: Required for authenticated API access.
  7. User ID. Integer primary key (user.id) included in leaderboard responses, checkout metadata, and public profile queries. Status: System-generated.

4.2 Profile, Gameplay, and Statistical Data

  1. display_name: CharField max_length=100 on Profile model; shown on leaderboard, user-sightings, and nearby map as catcher name.
  2. total_sightings: PositiveIntegerField; recalculated from Sighting count via Profile.recalculate_stats().
  3. unique_species: Count of distinct species strings (case-insensitive) among your sightings.
  4. current_streak: Consecutive calendar days with at least one sighting, computed by compute_streak_from_sightings(); resets if gap exceeds one day.
  5. max_streak: Historical maximum of current_streak.
  6. rare_count, epic_count, legendary_count: Tallies by rarity tier (common, uncommon, rare, epic, legendary).
  7. badges_unlocked: PositiveIntegerField; may be updated via POST /update-stats/ with badges_unlocked in request body.
  8. is_premium: Boolean indicating Premium subscription status; set via Stripe checkout, verify-checkout, and webhooks.
  9. stripe_customer_id: Stripe customer identifier stored on Profile when checkout completes.
  10. stripe_subscription_id: Stripe subscription identifier; used for cancellation on account deletion and webhook subscription updates.
  11. photo_library_uploads_this_month: Monthly counter for Premium library imports; reset by reset_library_count_if_needed() at month boundary.
  12. last_photo_upload_reset: Date tracking monthly library upload counter reset.
  13. explorer_level: Derived from total_xp as max(1, int(total_xp ** 0.5 / 5) + 1).
  14. total_xp: Sum of per-sighting xp values assigned by rarity (10/25/50/100/250).
  15. explorer_score: Computed ranking metric: total_sightings + unique_species*5 + legendary_count*20 + epic_count*10 + rare_count*3 + current_streak*2; used for leaderboard ordering.
  16. last_updated: Auto-updated DateTime on Profile saves.

4.3 Sighting and Media Data

When you save a capture, the App POSTs JSON to /sightings/ with fields validated and persisted in the Sighting model. Images are accepted as image_base64 with optional data-URI prefix; permitted extensions are jpeg, jpg, png, and webp; maximum encoded length is 8,000,000 characters. Decoded files are saved to sightings/{uuid}.{ext} via Django ImageField.

  1. uuid: UUIDField, client-supplied or server-generated; idempotency check prevents duplicate uuid per user.
  2. species: Required string, max 200 characters after strip.
  3. date: ISO 8601 datetime parsed with fromisoformat.
  4. image / image_base64: Optional photo of the observed wildlife; stored on server filesystem and returned base64-encoded in GET responses.
  5. fun_fact: TextField; may include Wikipedia-sourced content assembled on-device.
  6. rarity: One of common, uncommon, rare, epic, legendary; determines xp and level.
  7. category: Defaults to Bird; supports broader wildlife categories.
  8. is_field_verified: True for live camera captures; false for Premium library uploads.
  9. latitude, longitude: Optional FloatFields attached when location is available for map features.
  10. level, xp: Gameplay metadata computed from rarity at creation.
  11. created_at: Server timestamp auto-set on insert.

4.4 On-Device and Client-Side Data

  • SwiftData BirdSighting records mirroring server fields including imageData stored locally on device.
  • Keychain storage for authToken with kSecAttrAccessibleAfterFirstUnlock.
  • UserDefaults keys: authToken (legacy mirror), userEmail, isPremium, photoLibraryUploadsThisMonth — declared in PrivacyInfo.xcprivacy under NSPrivacyAccessedAPICategoryUserDefaults with reason CA92.1 (access info stored in app group shared with same-app extensions or for app functionality).
  • Core ML inference via Vision VNCoreMLModel using BirdModel and INatVision_Small_8bit models; camera frames processed locally without transmission to third-party AI services for identification.
  • Camera and Photo Library access via iOS permissions for scanning and Premium library import.
  • CoreLocation coordinates for World Map nearby query and optional sighting geotagging.
  • Client-side HTTP requests to en.wikipedia.org/w/api.php for species extracts; Facehash.dev /api/avatar with query parameters name and size=128.

4.5 Payment and Transaction Data

Premium subscriptions are processed by Stripe. When you initiate checkout via POST /create-checkout/, we create a Stripe Checkout Session with payment_method_types card, your customer_email, and metadata user_id. Stripe collects payment card details directly; we receive session identifiers, customer IDs, subscription IDs, payment status, and webhook events (checkout.session.completed, customer.subscription.updated, customer.subscription.deleted). We do not store full payment card numbers on Ranger servers.

4.6 Technical, Log, and Security Data

Our Django deployment may log request errors, invalid image warnings (logged at WARNING with user id), health check probes (/health/ and /health/?deep=1 for database connectivity), and Stripe webhook verification failures. Logs are retained for operational troubleshooting for a limited period consistent with our infrastructure practices. We implement API rate limiting via DRF throttling (default anon 60/minute, user 300/minute unless overridden by environment variables).

Article V — Legal Bases and Purposes of Processing

  1. Contract Performance: Processing account, sighting, profile, and sync data is necessary to provide the Services you request, including maintaining your collection, calculating streaks and XP, and enabling cross-device access when authenticated.
  2. Legitimate Interests: We process leaderboard rankings, nearby spawn map data, and anti-abuse throttling based on legitimate interests in operating community features, promoting engagement, and securing our API, balanced against your rights.
  3. Consent: Where required by law, we rely on consent for optional features such as precise location attachment to sightings, photo library imports (Premium), and marketing communications if ever introduced. iOS permission prompts provide device-level consent for camera, photos, and location.
  4. Legal Obligation: We may process and retain data to comply with tax, accounting, fraud prevention, and lawful requests from authorities, and to honor consumer rights requests.
  5. Vital Interests and Public Interest: Not a primary basis for Ranger processing; included for completeness under GDPR Article 6 framing for international users.

Article VI — How We Use Personal Data

  1. Account Creation and Authentication: Register users via email/password; issue tokens; verify Google ID tokens against GOOGLE_IOS_CLIENT_ID audience; invalidate tokens on logout and account deletion.
  2. Collection Synchronization: Store and retrieve sightings via GET/POST /sightings/; return base64 images to authenticated owner; recalculate profile stats after each sighting.
  3. Leaderboard: Compute explorer_score for all profiles; expose top 50 ranks with display_name, stats, and user_id via GET /leaderboard/ (AllowAny).
  4. Public Profile Cards: Expose top 12 rarest sightings with base64 images via GET /user-sightings/?user_id= (AllowAny).
  5. Nearby Map: Return other users' sightings within radius_km (default 15, max 50) using haversine distance; includes species, rarity, coordinates, catcher display name, up to 100 results.
  6. Premium Entitlements: Enforce library upload restriction for non-Premium users; track monthly library count; sync is_premium via Stripe.
  7. Password Reset: When EMAIL_HOST is configured (e.g., SendGrid SMTP), send reset links via /auth/password/reset/; otherwise console backend in development.
  8. Account Deletion: DELETE /delete-account/ cancels Stripe subscription, deletes image files, sightings, profile, and user record.
  9. Customer Support: Respond to inquiries sent to [email protected] regarding account access, deletion, and billing disputes coordinated with Stripe.

Article VII — On-Device Processing and Local Storage

A distinguishing characteristic of Ranger is that wildlife identification is performed on your iPhone using Apple Vision and Core ML models bundled with the App. When you point the camera at a bird or other wildlife subject, frame analysis occurs locally. We do not transmit live camera frames to cloud-based species recognition vendors for the Core ML identification path implemented in ScanView.swift. Identified species names, rarity assignments, fun facts (potentially enriched via Wikipedia API calls initiated by your device), and optional photos are then saved locally in SwiftData and optionally synchronized to our servers when you are logged in.

Authentication tokens are stored in the iOS Keychain to reduce exposure compared to plaintext storage alone. We maintain a UserDefaults mirror of authToken for backward compatibility during Keychain migration. On logout or session expiry (HTTP 401), RangerSession.clear() removes Keychain entries and UserDefaults keys userEmail, isPremium, and photoLibraryUploadsThisMonth.

Article VIII — Disclosure, Sharing, and Sale of Personal Data

8.1 No Sale of Personal Data

Ranger does not sell Personal Data as "sell" is defined under the CCPA/CPRA. We do not exchange Personal Data for monetary or other valuable consideration. We do not license email lists to data brokers. We do not provide sighting photos to advertising networks.

8.2 No Cross-App Advertising Tracking

Our Apple Privacy Manifest sets NSPrivacyTracking to false and declares an empty NSPrivacyTrackingDomains array. Collected data types (email, photos/videos, precise location) are marked linked to the user, not used for tracking, and purposes limited to App Functionality. We do not use the advertising identifier (IDFA) for Ranger analytics or ad attribution in the codebase reviewed for this Policy.

8.3 Categories of Recipients

  1. Stripe, Inc.: Payment processing, subscription lifecycle, checkout sessions, fraud signals inherent to payment networks.
  2. Google LLC: OAuth ID token verification via tokeninfo endpoint; subject to Google's policies when you choose Google Sign-In.
  3. SMTP Email Provider (optional): Transactional email delivery for password reset when EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_PORT, and EMAIL_USE_TLS are configured; SendGrid is a common provider but not exclusive.
  4. Facehash.dev: Avatar image generation; your device requests https://www.facehash.dev/api/avatar?name={seed}&size=128 where seed is derived from email local-part or display_name via FacehashAvatar.seedName().
  5. Wikimedia Foundation (Wikipedia API): Client-side species information retrieval; requests originate from your device to en.wikipedia.org.
  6. Infrastructure Providers: Hosting for Django API, SQLite or DATABASE_URL-configured database, media file storage on server filesystem, reverse proxy (Caddy), and TLS termination as deployed.
  7. Other Users (by feature design): Leaderboard statistics, public top-12 sighting cards, and nearby map spawn details as described in Article IX.

Article IX — Community, Social, and Map Features

9.1 Public Leaderboard

GET /leaderboard/ is accessible without authentication (AllowAny). For up to fifty profiles, we publish rank, display_name (or derived fallback), total_sightings, unique_species, current_streak, legendary count, explorer score, and user_id. Sighting photographs are not included in leaderboard responses. Any user or visitor with network access can view these statistics and use user_id to query additional public sighting card data.

9.2 Public User Sightings (Top 12 Cards)

GET /user-sightings/?user_id={id} is accessible without authentication. We return display_name, aggregate stats, and up to twelve sightings selected by rarity ordering (legendary highest). For each sighting we include uuid, species, date, fun_fact, rarity, category, and image_base64 when an image file exists on the server. This means wildlife photos you have synchronized may be viewable by anyone who knows or discovers your numeric user_id, for your rarest captures. This design supports trading-card style sharing within the App but is not a private-by-default photo album.

9.3 Nearby Sightings Map

Authenticated users may call GET /nearby-sightings/?lat={}&lng={}&radius_km={} to discover other players' catches near a coordinate. We exclude your own sightings and entries without coordinates. Returned fields include uuid, species, rarity, category, level, latitude, longitude, distance_km, catcher display name, and is_field_verified. Default radius is 15 km; maximum allowed is 50 km; up to 100 results sorted by distance. Attaching latitude and longitude to your sightings therefore enables other authenticated users to see species and location information in proximity searches.

Article X — Third-Party Processor Details

Stripe

PCI-DSS compliant payment processor. Receives email, user_id metadata, subscription events. Privacy: https://stripe.com/privacy

Google OAuth

Validates id_token audience and email_verified flag. We do not receive your Google password.

SendGrid / SMTP

Optional; only processes email addresses and reset tokens when outbound SMTP configured.

Facehash.dev

Receives hashed avatar seed string derived from public display name or email local-part; no Ranger server-side proxy.

Wikipedia

Receives search terms derived from species names; no account linkage from Ranger servers.

Article XI — Data Retention

We retain Personal Data for as long as your Account is active or as needed to provide the Services, unless a longer retention period is required or permitted by law. The following retention principles apply based on our current implementation:

  1. Account and Profile Data: Retained until you delete your account via in-app Delete Account (DELETE /delete-account/) or we terminate the account for violations.
  2. Sighting Records and Images: Retained until account deletion; image files explicitly deleted from storage during DeleteAccountView processing.
  3. Authentication Tokens: Retained until logout (token deleted) or account deletion.
  4. Stripe Identifiers: Removed when Profile is deleted; subscription cancellation attempted via stripe.Subscription.cancel on deletion.
  5. On-Device SwiftData: Remains on your device until you uninstall the App or clear local data; not remotely wiped by account deletion unless the App implements such cleanup on logout.
  6. Server Logs: Retained for a limited operational window; not intended as long-term archival of Personal Data.
  7. Password Reset Tokens: Managed by Django/dj-rest-auth defaults; ephemeral.

Article XII — Security Measures and Limitations

We implement administrative, technical, and organizational measures designed to protect Personal Data, including password hashing, token authentication, HTTPS via reverse proxy in production (SECURE_PROXY_SSL_HEADER, optional SECURE_SSL_REDIRECT), CSRF protection for session-based web flows, CORS restrictions when CORS_ALLOWED_ORIGINS is set, upload size limits (DATA_UPLOAD_MAX_MEMORY_SIZE default 10MB), image base64 length cap (8,000,000), Stripe webhook signature verification, and rate throttling.

Despite our efforts, no method of transmission over the Internet or electronic storage is completely secure. We cannot guarantee absolute security. You are responsible for safeguarding your device, iOS passcode, and authentication token. If you believe your account has been compromised, contact [email protected] and use in-app logout to invalidate tokens.

In the event of a data breach affecting Personal Data, we will notify affected individuals and regulators as required by applicable law.

Article XIII — International Data Transfers

Ranger is operated from the United States with framing under Delaware and U.S. law as described in our Terms of Service. If you access the Services from outside the United States, your Personal Data may be transferred to, stored, and processed in the United States and wherever our service providers maintain facilities (including Stripe and Google global infrastructure). Such transfers may involve countries that do not provide the same level of data protection as your jurisdiction. Where required, we implement appropriate safeguards such as standard contractual clauses or rely on adequacy decisions. By using the Services, you acknowledge such transfers for globally distributed processing necessary to operate Ranger.

Article XIV — Your Privacy Rights and Choices

  1. Access: Request confirmation and copies of Personal Data we process about you, including account email, profile stats, and sighting metadata.
  2. Correction: Update display name and account information through in-app Profile settings and password change endpoints.
  3. Deletion: Delete your account in-app (Profile → Delete Account), triggering server-side removal of user, profile, sightings, and images, and Stripe subscription cancellation when configured.
  4. Portability: Request export of your data in a structured format where technically feasible; authenticated GET /sightings/ returns your collection data.
  5. Restriction and Objection: Object to certain processing based on legitimate interests where applicable law provides such rights.
  6. Withdraw Consent: Withdraw consent for optional processing (e.g., location) by disabling iOS permissions and refraining from attaching coordinates.
  7. Non-Discrimination: We will not discriminate against you for exercising privacy rights under CCPA/CPRA.

Submit requests to [email protected]. We may verify identity by requiring login or confirming control of the registered email. Authorized agents may submit requests under CCPA with proof of authorization.

Article XV — California Privacy Rights (CCPA/CPRA)

Categories Collected (Last 12 Months)

Identifiers (email, user id, tokens); customer records (profile stats); commercial information (Premium status, Stripe IDs); internet activity (API usage subject to logs); audio/visual information (sighting photos); geolocation data (sighting coordinates); inferences (explorer score, rarity tallies).

Business Purposes

Providing the App, processing payments, security, debugging, account management, community features.

Sensitive Personal Information

Precise geolocation when attached to sightings; we use it only for stated map and collection purposes and do not use sensitive personal information to infer characteristics for unrelated purposes.

Right to Know

California residents may request categories and specific pieces of Personal Data collected, sources, purposes, and disclosures.

Right to Delete

California residents may delete Personal Data via in-app account deletion or by contacting [email protected].

Right to Correct

California residents may correct inaccurate Personal Data via profile settings or support request.

Right to Opt-Out of Sale/Sharing

We do not sell or share Personal Data for cross-context behavioral advertising; no opt-out link is required for sale because no sale occurs.

Shine the Light

California Civil Code § 1798.83: we do not disclose Personal Data to third parties for their direct marketing purposes in exchange for compensation.

Article XVI — Children's Privacy

Ranger is not directed to children under 13 years of age (or the minimum age required in your jurisdiction). We do not knowingly collect Personal Data from children under 13. If you are a parent or guardian and believe your child has provided Personal Data to Ranger without verifiable parental consent, contact [email protected] and we will delete such information upon verification.

Article XVII — Do Not Track and Global Privacy Control

Ranger does not respond to browser Do Not Track (DNT) signals because the App is a native iOS application without browser-based tracking cookies. Our website legal pages are informational and do not deploy behavioral advertising trackers. We honor Global Privacy Control (GPC) signals where legally required for web experiences; however, because we do not sell or share Personal Data for cross-context behavioral advertising, GPC primarily confirms our default practice of non-sale. California residents may contact [email protected] with privacy inquiries regardless of signal mechanics.

Article XVIII — Cookies, Local Storage, and Apple Privacy Manifest

The iOS App does not use browser cookies. It uses UserDefaults for app functionality keys (userEmail, isPremium, photoLibraryUploadsThisMonth, legacy authToken) as disclosed to Apple with NSPrivacyAccessedAPICategoryUserDefaults reason CA92.1. Keychain stores authentication tokens. SwiftData persists local sightings. Django web pages may use session cookies for admin and authentication flows on the website; REST API authentication uses Token header rather than browser cookies for the App.

Article XIX — Changes to This Policy

We may update this Policy to reflect new features (e.g., additional API endpoints), new processors, regulatory changes, or security improvements. The "Last updated" date at the top indicates the latest revision. Material changes affecting how we use Personal Data will be communicated through appropriate channels. Prior versions may be available upon request to [email protected].

Article XX — Contact Information

For privacy questions, data subject requests, security vulnerability reports, or complaints: Email [email protected]. For Stripe billing disputes, you may also contact Stripe support per your receipt. If you are unsatisfied with our response, you may lodge a complaint with your local data protection authority where applicable.

Appendix A — API Endpoint Data Flow Reference

  1. POST /auth/registration/ — Input: email, password1, password2. Effect: Creates User, Profile, Token.
  2. POST /auth/login/ — Input: email, password. Effect: Returns Token key.
  3. POST /auth/password/reset/ — Input: email. Effect: Sends reset email if SMTP configured.
  4. POST /auth/password/change/ — Input: old_password, new_password1, new_password2. Effect: Updates hashed password.
  5. POST /google-login/ — Input: id_token. Effect: Verifies Google token; returns Token.
  6. POST /logout/ — Input: Authorization Token. Effect: Deletes Token.
  7. GET/POST /sightings/ — Input: Sighting fields, image_base64. Effect: List/create user sightings.
  8. GET /my-profile/ — Input: Authorization Token. Effect: Returns profile stats and Premium info.
  9. POST /update-stats/ — Input: badges_unlocked. Effect: Syncs badge count; recalculates stats.
  10. GET /leaderboard/ — Input: none (public). Effect: Top 50 ranked profiles.
  11. GET /user-sightings/ — Input: user_id query param (public). Effect: Top 12 rarest with images.
  12. GET /nearby-sightings/ — Input: lat, lng, radius_km. Effect: Nearby others' catches.
  13. POST /create-checkout/ — Input: Authorization Token. Effect: Stripe Checkout URL.
  14. POST /verify-checkout/ — Input: session_id. Effect: Confirms Premium status.
  15. POST /stripe-webhook/ — Input: Stripe-signed payload. Effect: Subscription events.
  16. DELETE /delete-account/ — Input: Authorization Token. Effect: Full account erasure.
  17. GET /health/ — Input: optional deep=1. Effect: Service status.

Appendix B — Field-Level Retention Schedule (Prose Table)

User.email — Retention period: Life of account. Deletion trigger: Deleted on account deletion. Purpose: Login, billing, support.

User.password hash — Retention period: Life of account. Deletion trigger: Deleted on account deletion. Purpose: Authentication.

Token.key — Retention period: Until logout/deletion. Deletion trigger: Deleted on logout or account deletion. Purpose: API auth.

Profile.display_name — Retention period: Life of account. Deletion trigger: Deleted with profile. Purpose: Leaderboard display.

Profile.stripe_customer_id — Retention period: Life of account. Deletion trigger: Deleted with profile. Purpose: Billing.

Profile.stripe_subscription_id — Retention period: Life of account. Deletion trigger: Cancelled then deleted. Purpose: Premium.

Sighting.image file — Retention period: Life of account. Deletion trigger: File deleted on account deletion. Purpose: Collection/media.

Sighting.latitude/longitude — Retention period: Life of account. Deletion trigger: Deleted with sighting. Purpose: Map features.

Server logs — Retention period: Short operational window. Deletion trigger: Rotated/archived. Purpose: Security/debug.

Keychain authToken — Retention period: Until logout. Deletion trigger: Removed by RangerSession.clear(). Purpose: Client auth.

UserDefaults keys — Retention period: Until logout. Deletion trigger: Removed on logout. Purpose: Client state cache.

Appendix C — Premium and Photo Library Upload Logic

Free tier users may capture wildlife using the live camera (is_field_verified=true). POST /sightings/ returns HTTP 403 with premium_required when is_field_verified is false and Profile.is_premium is false. Premium users may import from the photo library; each such sighting increments photo_library_uploads_this_month. The counter resets when last_photo_upload_reset month differs from current month via reset_library_count_if_needed(). Client mirrors count in UserDefaults photoLibraryUploadsThisMonth and syncs from server responses.

Appendix D — Image Processing and Size Limits

Server enforces MAX_IMAGE_B64_LEN = 8,000,000 on the base64 string. DATA_UPLOAD_MAX_MEMORY_SIZE defaults to 10,485,760 bytes (10 MB) for Django request bodies. Supported image formats after data-URI parsing: jpeg, jpg, png, webp. Invalid base64 or malformed data-URI headers result in sighting creation without image (warning logged) rather than rejecting the entire sighting, except when species or date validation fails.

Appendix E — Glossary of Rarity and XP Values

Rarity tiers and XP assigned at sighting creation per RARITY_XP mapping: common=10, uncommon=25, rare=50, epic=100, legendary=250. Level derived via max(1, int((xp/50.0)**0.5)+1) on server; client BirdRarity enum mirrors equivalent catchXP values. Explorer level uses total_xp: max(1, int(total_xp**0.5/5)+1).

Appendix F — Additional Operational Disclosures

Account Security Best Practices

We recommend using a unique, strong password for your Ranger account, enabling device passcode and biometric lock on your iPhone, and logging out on shared devices. Because API tokens function as bearer credentials, anyone with access to your unlocked device and App could potentially issue authenticated requests until logout. Google Sign-In users should secure their Google account with two-factor authentication.

Email Communications

We send transactional emails only: password reset messages when requested through ForgotPasswordView calling /auth/password/reset/, and potentially account-related notices if we enable email verification (ACCOUNT_EMAIL_VERIFICATION is optional in current configuration). We do not send promotional newsletters based on the current codebase. DEFAULT_FROM_EMAIL defaults to [email protected].

Administrative Access

Authorized Ranger administrators may access user data through Django admin for support, abuse investigation, and system maintenance. Admin list_display for Profile includes user, display_name, is_premium, total_sightings, explorer_level, current_streak; search_fields include user email and display_name.

CORS and API Access

In DEBUG mode, CORS_ALLOW_ALL_ORIGINS may be true; in production, CORS_ALLOWED_ORIGINS environment variable restricts browser origins. The iOS App uses native URLSession rather than browser CORS.

Webhook Integrity

StripeWebhookView rejects requests without STRIPE_WEBHOOK_SECRET configured (HTTP 503), validates signatures, processes checkout.session.completed by matching metadata user_id or customer_email, and updates is_premium on subscription updated/deleted events.

Haversine Distance Calculation

Nearby feature uses Earth radius 6371 km for great-circle distance between query lat/lng and sighting coordinates, filtering by radius_km parameter.

Duplicate Sighting Prevention

POST /sightings/ returns status already_exists when uuid collides for the same user, supporting idempotent sync from client-generated UUIDs.

Session Expiry Handling

HTTP 401 responses trigger RangerAPIClient.handleUnauthorized, clearing session and posting rangerSessionExpired notification.

Explorer Score Transparency

Leaderboard ranking uses a deterministic formula documented in Profile.explorer_score() so users can understand how sightings, diversity, rarity counts, and streak affect rank.

Facehash Seed Algorithm

FacehashAvatar.seedName lowercases and trims input, splitting email at @ to use local-part only, ensuring consistent avatars between email-based profile and display names.

Appendix G — Comprehensive Category-by-Category Examples

Identifiers

  • Your email address [email protected] stored as the primary account identifier.
  • Numeric user_id=42 returned in leaderboard JSON for correlation with public profile endpoint.
  • UUID v4 per sighting such as 550e8400-e29b-41d4-a716-446655440000 stored in Sighting.uuid.
  • REST authentication token string in Authorization: Token header format.
  • Stripe customer id cus_xxx and subscription id sub_xxx stored on Profile for billing continuity.

Demographic and Profile

  • Optional display_name RangerDave shown on leaderboard instead of email local-part.
  • Google given_name populated to User.first_name on first OAuth login.
  • Explorer level 7 computed when total_xp crosses corresponding threshold.

Commercial Information

  • is_premium true after successful Stripe checkout session payment_status paid.
  • Checkout session metadata user_id linking payment to Django user.
  • photo_library_uploads_this_month incrementing on each library-sourced sighting.

Internet and API Activity

  • GET /nearby-sightings/ queries logged at infrastructure level with IP and timestamp.
  • Rate limit counters for anon and user throttle classes per DRF configuration.
  • Health deep check database probe when ?deep=1 without exposing user data.

Audio-Visual

  • JPEG sighting photo of a Cardinal encoded as image_base64 in POST body.
  • Trading card imageData in local SwiftData persistent store.
  • Facehash avatar PNG retrieved for seed name rangerdave.

Geolocation

  • latitude 40.7128 longitude -74.0060 attached to Central Park sighting.
  • Device location from CoreLocation for nearby query center point.
  • distance_km 2.34 rounded in nearby API response.

Inferences

  • explorer_score 1247 ranking you 12th on leaderboard.
  • rarity epic inferred from model confidence and game rules client-side before upload.
  • current_streak 5 indicating consecutive daily engagement.

Appendix H — Extended Legal and Regulatory Commentary

United States Federal Framing

While the United States does not have a single comprehensive federal privacy statute equivalent to the GDPR, Ranger adheres to applicable sectoral and state laws. Our Delaware corporate framing aligns with common choice-of-law provisions in our Terms. Federal Trade Commission Act Section 5 prohibits unfair or deceptive practices; we strive to ensure this Policy accurately describes actual codebase behavior as of the Last updated date.

State Privacy Laws Beyond California

Residents of Virginia (VCDPA), Colorado (CPA), Connecticut (CTDPA), Utah (UCPA), Texas (TDPSA), Oregon (OCPA), Montana (MCDPA), and other enacting states may have rights similar to those described in Article XV. Contact [email protected] to exercise rights. We do not discriminate against users exercising statutory privacy rights.

European Economic Area and UK GDPR

Where the GDPR applies, our lawful bases are set forth in Article V. Data subjects have rights of access, rectification, erasure, restriction, portability, objection, and complaint to a supervisory authority. International transfers rely on appropriate safeguards as described in Article XIII. Our representative and DPO contacts, if required at scale, will be published in an updated Policy revision.

Canada PIPEDA

Canadian users may contact [email protected] for access and challenge requests regarding Personal Information handled under PIPEDA principles of accountability, identifying purposes, consent, limiting collection, limiting use, accuracy, safeguards, openness, individual access, and challenging compliance.

Australia Privacy Act

Australian users may request access and correction of personal information. We handle cross-border disclosures consistent with APP 8 using contractual protections with processors.

Brazil LGPD

For Brazilian data subjects, processing bases include consent, contract, and legitimate interest as applicable. Contact [email protected] for LGPD requests.

Nevada Privacy Law

Nevada residents may submit verified requests directing us not to sell covered information. As we do not sell covered information, no sale opt-out mechanism is necessary beyond this disclosure.

Appendix I — Detailed Narrative Disclosures for Each Processing Activity

Registration Email Password

When you submit email and password through LoginView registration mode, the App POSTs to /auth/registration/ with password1 and password2. CustomRegisterSerializer removes the username field from the public API shape while internally assigning username equal to email for Django compatibility. Upon success, the server creates a User row, triggers post_save signals to create an empty Profile via create_profile receiver, and issues an authtoken Token returned to the client. The client stores the token via RangerSession.setToken, which writes to Keychain and UserDefaults, and saves userEmail in AppStorage. This processing is necessary to perform our contract with you to provide an account-backed collection experience.

This processing activity (registration_email_password) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Registration Google Oauth

Google Sign-In supplies an id_token to POST /google-login/. The server requests Google's tokeninfo endpoint, validates HTTP 200, checks email_verified, compares aud to GOOGLE_IOS_CLIENT_ID environment variable, extracts email and optional given_name, get_or_create User by email with username=email, sets unusable password for new users, and returns Token key. Google passwords never transit to Ranger. This flow reduces password management burden while linking your Ranger identity to your verified Google email.

This processing activity (registration_google_oauth) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Login Logout

Email login POSTs to /auth/login/ with email and password; Django authenticates against hashed password; Token returned. Logout POSTs to /logout/ with Authorization header; server deletes auth_token. Client RangerSession.clear removes Keychain and UserDefaults entries. Logout is immediate for API purposes; other devices holding old tokens cannot authenticate after deletion.

This processing activity (login_logout) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Password Reset Smtp

ForgotPasswordView POSTs email to /auth/password/reset/. When EMAIL_HOST is configured, Django SMTP backend sends message through configured host (commonly SendGrid with EMAIL_HOST_USER and EMAIL_HOST_PASSWORD). If SMTP is not configured, development console backend prints email to logs without delivery. Reset links are time-limited per dj-rest-auth and django-allauth defaults.

This processing activity (password_reset_smtp) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Password Change

ProfileSettingsView submits old and new passwords to /auth/password/change/. Validators enforce UserAttributeSimilarity, MinimumLength, CommonPassword, and NumericPassword rules per AUTH_PASSWORD_VALIDATORS.

This processing activity (password_change) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Sighting Create Camera

ScanView captures camera frame, runs Vision Core ML models, presents identified species, and on save constructs BirdSighting with isFieldVerified true. Sync POST includes image_base64 from JPEG data, species string, rarity, fun_fact, uuid, date, optional coordinates. Server validates rarity against ALLOWED_RARITIES set, computes xp and level, decodes image, saves file, recalculates profile stats.

This processing activity (sighting_create_camera) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Sighting Create Library Premium

Premium users select PHPicker items in ScanView. Non-premium attempts show paywall. Library uploads set is_field_verified false; server increments photo_library_uploads_this_month after successful save.

This processing activity (sighting_create_library_premium) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Sighting List Sync

GET /sightings/ returns all user sightings ordered by date descending with full metadata and base64 images for client reconciliation with SwiftData.

This processing activity (sighting_list_sync) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Profile Stats Recalc

Profile.recalculate_stats queries all sightings to recompute totals, unique species, rarity counts, total_xp, explorer_level, and streak. Called after sighting create, on my-profile GET, user-sightings GET, and update-stats POST.

This processing activity (profile_stats_recalc) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Badge Sync

Client quests may track badges locally; POST /update-stats/ sends badges_unlocked integer to persist on Profile.

This processing activity (badge_sync) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Leaderboard Public

AllowAny permission means no token required. Any network client can fetch ranked stats. This supports App LeaderboardView but exposes competitive metrics publicly by design.

This processing activity (leaderboard_public) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

User Sightings Public

AllowAny with user_id parameter exposes top dozen rarest captures including photos. user_id is enumerable in principle though not sequentially advertised.

This processing activity (user_sightings_public) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Nearby Map Authenticated

Requires valid Token. MapView sends lat/lng from RangerLocationManager. Other users' spawn pins display species and catcher names. Coordinates reveal approximate catch locations.

This processing activity (nearby_map_authenticated) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Stripe Checkout

CreateCheckoutSessionView requires authentication, Stripe keys, and STRIPE_PRICE_ID. Returns hosted checkout URL; client opens Safari/ASWebAuthenticationSession flow.

This processing activity (stripe_checkout) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Stripe Verify

After redirect to checkout success page, client may POST session_id to verify-checkout to confirm metadata user_id matches authenticated user before marking Premium.

This processing activity (stripe_verify) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Stripe Webhook

Server-to-server events update Premium without client action; signature verified with STRIPE_WEBHOOK_SECRET.

This processing activity (stripe_webhook) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Account Deletion

ProfileSettingsView DELETE to /delete-account/ removes all personal records and attempts Stripe subscription cancel. Irreversible.

This processing activity (account_deletion) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Coreml Identification

BirdModel and INatVision models classify images on Neural Engine/GPU locally. No cloud ML API keys in ScanView identification path.

This processing activity (coreml_identification) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Wikipedia Client

fetchWikipediaInfo queries Wikipedia search API with species string; extracts title and intro text for fun facts. Ranger servers never proxy this request.

This processing activity (wikipedia_client) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Facehash Avatar

AsyncImage loads avatar URL built from seedName(display_name or email). Third party sees seed string and size parameter only.

This processing activity (facehash_avatar) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Swiftdata Local

BirdDexApp SwiftData container persists BirdSighting between launches for offline collection viewing.

This processing activity (swiftdata_local) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Keychain Token

kSecAttrAccessibleAfterFirstUnlock balances security and background sync capability.

This processing activity (keychain_token) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Userdefaults Cache

AppStorage mirrors premium and library upload count for SwiftUI reactive UI; CA92.1 declared to Apple.

This processing activity (userdefaults_cache) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Location Permissions

Map and optional sighting geotag require When In Use authorization via CoreLocation.

This processing activity (location_permissions) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Camera Permissions

NSCameraUsageDescription required for live scanning.

This processing activity (camera_permissions) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Photo Library Permissions

Photo library access gated behind Premium for imports.

This processing activity (photo_library_permissions) is conducted in accordance with the data minimization principle to the extent practical for game functionality: we only collect fields present in API payloads and model definitions, we do not require sighting images for account operation though images are central to the collection experience, and we segregate public leaderboard statistics from optional photograph disclosure through separate API endpoints with distinct permission classes (AllowAny on leaderboard and user-sightings versus IsAuthenticated on personal sightings list and create).

Appendix J — Risk Disclosures and User Responsibilities

Public Exposure Of User Id Linked Top-12 Photos

Regarding Public exposure of user id linked top-12 photos, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Public exposure of user id linked top-12 photos, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Public exposure of user id linked top-12 photos, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Geolocation Precision On World Map

Regarding Geolocation precision on world map, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Geolocation precision on world map, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Geolocation precision on world map, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Bearer Token Device Compromise

Regarding Bearer token device compromise, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Bearer token device compromise, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Bearer token device compromise, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Third-Party Processor Availability

Regarding Third-party processor availability, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Third-party processor availability, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Third-party processor availability, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

User-Generated Wildlife Misidentification

Regarding User-generated wildlife misidentification, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding User-generated wildlife misidentification, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding User-generated wildlife misidentification, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Premium Subscription Auto-Renewal Via Stripe

Regarding Premium subscription auto-renewal via Stripe, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Premium subscription auto-renewal via Stripe, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Premium subscription auto-renewal via Stripe, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Data Residue In Backups

Regarding Data residue in backups, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Data residue in backups, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Data residue in backups, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Jurisdictional Law Conflicts

Regarding Jurisdictional law conflicts, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 1 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Jurisdictional law conflicts, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 2 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Regarding Jurisdictional law conflicts, users should understand that digital services involve inherent uncertainties. Ranger implements technical measures described in Article XII, but users remain responsible for decisions about what data to submit, including whether to sync photos, attach GPS coordinates, choose a recognizable display_name, or subscribe to Premium. We encourage reviewing Profile settings, using Delete Account when leaving the service, and contacting [email protected] promptly for incidents. This disclosure iteration 3 emphasizes transparency without expanding scope of collection beyond codebase-defined behavior.

Appendix K — Complete Model Field Reference with Privacy Notes

django.contrib.auth.models.User.id (Auto-increment PK): Internal identifier; exposed as user_id in public APIs. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

django.contrib.auth.models.User.email (EmailField): Primary account identifier; login credential. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

django.contrib.auth.models.User.password (CharField hashed): Never exposed via API. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

django.contrib.auth.models.User.first_name (CharField): Optional; Google given_name; leaderboard fallback. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

django.contrib.auth.models.User.username (CharField): Mirrors email internally. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

rest_framework.authtoken.models.Token.key (CharField): Secret bearer token. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.user (OneToOneField): Links profile to user. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.display_name (CharField(100)): Public leaderboard name. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.total_sightings (PositiveIntegerField): Derived stat. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.unique_species (PositiveIntegerField): Derived stat. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.current_streak (PositiveIntegerField): Derived engagement metric. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.max_streak (PositiveIntegerField): Historical engagement. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.rare_count (PositiveIntegerField): Gamification. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.epic_count (PositiveIntegerField): Gamification. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.legendary_count (PositiveIntegerField): Gamification. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.badges_unlocked (PositiveIntegerField): Client-synced. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.is_premium (BooleanField): Entitlement flag. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.stripe_customer_id (CharField(100)): Billing reference. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.stripe_subscription_id (CharField(100)): Subscription reference. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.photo_library_uploads_this_month (PositiveIntegerField): Usage metering. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.last_photo_upload_reset (DateField): Metering reset anchor. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.explorer_level (PositiveIntegerField): Derived from XP. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.total_xp (PositiveIntegerField): Sum of sighting XP. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Profile.last_updated (DateTimeField): Audit timestamp. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.user (ForeignKey): Owner linkage. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.uuid (UUIDField): Client-sync id. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.species (CharField(200)): Wildlife label. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.date (DateTimeField): Observation time. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.image (ImageField): Stored media file. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.fun_fact (TextField): Descriptive content. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.rarity (CharField(20)): Game tier. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.category (CharField(50)): Taxonomic grouping. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.is_field_verified (BooleanField): Capture source flag. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.latitude (FloatField nullable): Geo coordinate. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.longitude (FloatField nullable): Geo coordinate. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.level (PositiveIntegerField): Per-capture level. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.xp (PositiveIntegerField): Per-capture XP. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

core.models.Sighting.created_at (DateTimeField auto): Server creation time. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

BirdSighting (SwiftData).imageData (Data?): Local photo bytes. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

BirdSighting (SwiftData).uuid (String): Sync key with server. This field is processed only as necessary for the functionality described elsewhere in this Policy. Users cannot directly edit all derived statistics on the server; many profile counters are recalculated from underlying sighting records to ensure integrity. If you delete individual sightings in future feature releases, recalculation logic would adjust dependent fields accordingly; current deletion path removes all sightings on account deletion.

Appendix L — CPRA Sensitive Personal Information Limitations

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #1: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #2: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #3: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #4: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #5: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #6: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #7: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #8: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #9: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #10: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #11: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #12: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #13: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #14: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #15: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #16: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #17: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #18: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #19: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Ranger uses precise geolocation data elements (latitude and longitude floats on Sighting records) solely to provide map and nearby spawn functionality as described in Articles IV and IX. We do not use precise geolocation to infer sensitive characteristics such as health status, religious affiliation, union membership, or genetic information. We do not combine geolocation with third-party data brokers. CPRA sensitive personal information limitation statement #20: our collection is proportionate to the wildlife gaming context, optional at capture time when coordinates are omitted, and deletable through account deletion without separate retention carve-outs for sensitive categories beyond operational backups if any.

Appendix M — Security Control Matrix (Descriptive)

Control: Password hashing via Django hashers. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Token authentication for API. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Stripe webhook HMAC verification. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: CSRF middleware for web forms. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: XFrameOptionsMiddleware clickjacking protection. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: SecurityMiddleware security headers. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: WhiteNoise static file serving. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: SSL redirect in non-DEBUG production. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: HSTS 31536000 seconds with subdomains. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Secure session and CSRF cookies in production. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: CORS origin allowlist in production. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: DRF rate throttling. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Image upload size caps. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Rarity enum validation. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: Species length validation. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: iOS Keychain for token storage. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Control: 401 unauthorized session clearing. This measure contributes to defense-in-depth but does not eliminate all risk. Effectiveness depends on deployment configuration, secret management for DJANGO_SECRET_KEY and STRIPE keys, timely security patching of Django and dependencies, and secure VPS administration for hosts such as 62.146.178.206 referenced in RangerAPIConfig.

Appendix N — Privacy Frequently Asked Questions

Does Ranger sell my email?

No. We do not sell Personal Data.

Additional context for 'Does Ranger sell my email?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Are my photos public?

Not on the leaderboard. Your top 12 rarest synced sightings may be viewable via /user-sightings/ by anyone with your user_id.

Additional context for 'Are my photos public?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Does AI run in the cloud?

Core ML identification runs on your iPhone. Photos are uploaded only when you save/sync sightings.

Additional context for 'Does AI run in the cloud?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Who processes payments?

Stripe processes card payments; we store Stripe customer and subscription IDs.

Additional context for 'Who processes payments?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

How do I delete everything?

Profile → Delete Account in the App.

Additional context for 'How do I delete everything?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Is Google login required?

No. Email/password registration is available.

Additional context for 'Is Google login required?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

What is Facehash?

A third-party avatar API your device calls with a seed derived from your name.

Additional context for 'What is Facehash?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Does Wikipedia see my account?

No. Wikipedia receives search queries from your device, not your Ranger credentials.

Additional context for 'Does Wikipedia see my account?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

What is is_field_verified?

True for live camera; false for Premium photo library imports.

Additional context for 'What is is_field_verified?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

What are my CCPA rights?

Know, delete, correct, non-discrimination; see Article XV.

Additional context for 'What are my CCPA rights?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Do you honor GPC?

We do not sell data; see Article XVII.

Additional context for 'Do you honor GPC?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

What UserDefaults keys are used?

userEmail, isPremium, photoLibraryUploadsThisMonth, legacy authToken.

Additional context for 'What UserDefaults keys are used?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Why CA92.1?

Apple-required reason code for UserDefaults access for app functionality.

Additional context for 'Why CA92.1?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Is NSPrivacyTracking enabled?

No, false in PrivacyInfo.xcprivacy.

Additional context for 'Is NSPrivacyTracking enabled?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

What happens on logout?

Token deleted server-side; Keychain and UserDefaults cleared client-side.

Additional context for 'What happens on logout?': This FAQ entry summarizes Ranger's codebase-backed practices as of June 25, 2026. For legal interpretations, refer to the main Articles above. Contact [email protected] for account-specific questions not answered here.

Appendix O — Data Subject Request Handling Procedures

Step 1 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 1 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 2 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 2 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 3 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 3 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 4 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 4 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 5 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 5 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 6 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 6 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 7 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 7 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 8 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 8 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 9 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 9 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 10 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 10 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 11 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 11 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 12 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 12 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 13 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 13 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 14 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 14 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 15 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 15 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 16 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 16 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 17 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 17 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 18 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 18 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 19 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 19 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 20 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 20 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 21 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 21 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 22 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 22 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 23 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 23 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 24 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 24 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 25 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 25 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 26 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 26 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 27 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 27 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 28 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 28 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 29 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 29 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 30 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 30 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 31 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 31 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 32 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 32 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 33 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 33 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 34 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 34 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 35 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 35 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 36 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 36 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 37 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 37 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 38 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 38 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 39 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 39 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 40 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 40 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 41 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 41 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 42 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 42 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 43 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 43 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 44 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 44 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 45 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 45 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 46 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 46 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 47 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 47 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 48 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 48 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 49 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 49 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Step 50 in our internal request handling framework: Upon receiving a privacy request at [email protected], we authenticate the requester through account email verification or in-app authenticated actions where applicable. For deletion requests, prefer in-app Delete Account for immediate automated execution via DeleteAccountView. For access requests, we compile data from User, Profile, Sighting, and Token tables associated with the verified account. For correction requests, direct users to Profile settings for display_name and password change flows. We document request receipt date, verification method, actions taken, and completion date. Response timeframe targets statutory deadlines (e.g., 45 days under CCPA with extension notice if needed). Step 50 emphasizes consistent treatment regardless of jurisdiction when rights overlap.

Appendix P — Version History

June 25, 2026: Comprehensive Policy aligned with Ranger API, BirdDex iOS client, Stripe integration, public leaderboard and user-sightings behavior, nearby map, Core ML on-device processing, Facehash and Wikipedia client integrations, PrivacyInfo.xcprivacy declarations, and CCPA/CPRA disclosures.

June 21, 2026: Prior abbreviated website summary superseded by this document.

Appendix Q — Acknowledgment

BY USING RANGER, YOU ACKNOWLEDGE THAT YOU HAVE READ THIS PRIVACY POLICY, UNDERSTAND THAT PUBLIC FEATURES EXPOSE CERTAIN STATISTICS AND TOP SIGHTING IMAGES AS DESCRIBED, UNDERSTAND THAT ON-DEVICE PROCESSING DIFFERS FROM SERVER SYNCHRONIZATION, AND AGREE TO THE COLLECTION, USE, AND DISCLOSURE OF YOUR INFORMATION AS DESCRIBED HEREIN. IF YOU DO NOT AGREE, DISCONTINUE USE AND DELETE YOUR ACCOUNT.

Privacy Policy Terms of Service Support Home