Arc

Arc Privacy Policy

Last updated: 2026-08-08

This policy describes exactly what Arc stores, what (if anything) leaves your device, and when. It is derived directly from the app's source code, not boilerplate — every claim below is backed by a specific file or behavior in this repository, cited inline so it stays honest as the code changes. If this document and the app's actual behavior ever disagree, the code is the bug and this document should be filed as an issue.

Arc has no analytics SDK of any kind — no Segment, Amplitude, Firebase Analytics, Sentry, or similar. We don't know how you use the app beyond what's described below. (Verified: apps/mobile/package.json's dependency list contains none of these; grep the repo yourself if you want to double-check.)

What we store, all the time (on your device only)

Arc is local-first. Every fast, weight entry, protocol setting, streak, and preference lives in a local SQLite database on your device (expo-sqlite, via apps/mobile/src/db). None of this leaves your device unless you explicitly turn on cloud sync (below). This includes:

What leaves your device, and when

Cloud sync (opt-in, Premium only)

If you're a Premium subscriber and choose to sign in (Settings → Account), Arc syncs a subset of your data to a Supabase-hosted database so it's available on your other devices. This is entirely opt-in — free-tier users and any signed-out Premium user never make a single network call related to sync (src/services/sync.ts's runSync gate checks premium first, locally, before anything else touches the network).

What syncs, once you sign in:

Sync data is protected by Postgres Row-Level Security policies scoped to your authenticated user id — no other Arc user, and no unauthenticated caller, can read or write your rows (enforced at the database level, not just in the app; see supabase/migrations/). We (the developer) do not manually inspect user data as a matter of course; the RLS policies exist so we don't have to and so no accidental cross-account leak is possible even from a client bug.

"Delete all data" also deletes your synced cloud copy, if you're signed in. Settings → Delete all data permanently erases everything on your device (db/repo.ts's deleteAllData). If you're a signed-in Premium user, it first deletes your fasts, weights, and synced settings from Supabase too (deletemysync_data(), a database function scoped to your account — see supabase/migrations/), THEN wipes your device — in that order, so a failed cloud delete (e.g. you're offline) aborts the whole operation with nothing deleted rather than silently leaving a stale cloud copy behind. Deleting all data also signs you out locally.

Residual scope, worth knowing: if you have Arc signed in on more than one device, this only deletes what's on Supabase and on THIS device — a different signed-in device isn't reached by this action and keeps its own local copy, which could re-push its data back to Supabase on its own next sync. Full erasure across every device you've ever used requires signing out (or deleting all data) on each one individually. A "delete my account" action that would guarantee no device can ever re-push again is planned alongside a future sync-account-deletion feature; it doesn't exist yet — if you need that guarantee today, contact us (see Contact, below).

Signing out (as opposed to "Delete all data") never touches your local data — it only clears the sync session and local sync cursors. Your fasts, weights, and settings stay on the device exactly as they were; a different account signing in next just starts a fresh sync from scratch.

Health Connect (Android, optional)

If you connect Health Connect (Settings → Connect Health), Arc can:

The OS permission prompt only ever appears when you tap Connect — Arc never requests Health Connect access silently or on a background timer (src/services/health.ts's header comment documents this as a hard rule). iOS HealthKit support exists as unverified source in this codebase (healthKit.ios.ts) but is not currently wired into a shipped build.

Advertising (AdMob, free tier only)

Arc's free tier shows banner ads (History and Stats screens only — never as an interstitial on core actions like starting or ending a fast) via Google AdMob (react-native-google-mobile-ads). Serving an ad means Google's ad SDK can access device identifiers per Google's own advertising policies — this is standard for any AdMob integration, not something Arc adds on top. As of this writing the app ships with Google's public test ad unit ids (see docs/go-live-runbook.md §0/§4) — no real ad inventory is served and no real advertising data is collected until a real AdMob unit id is configured. For users in the EEA, Arc presents a consent form (Google's User Messaging Platform / UMP) before any ad request is made, once Privacy & Messaging is configured on the AdMob side.

Purchasing "Remove ads" (one-time) stops ads from displaying entirely.

Purchases (RevenueCat)

Subscription and one-time purchase state (Premium subscription, Remove Ads) is managed through RevenueCat (react-native-purchases), which communicates with Apple/Google's own purchase APIs and RevenueCat's servers to validate purchase tokens and report entitlement status. As of this writing, RevenueCat is unconfigured (app.json's extra.monetization.revenueCat keys are null) — the app runs in a fully-functional offline demo mode for purchases until this is configured (see docs/go-live-runbook.md). Once configured, purchase tokens (not payment details — Arc never sees your card number) are shared with RevenueCat as part of normal purchase validation.

Data we never collect

Your controls

Contact

Questions about this policy or a data deletion request: motasimhussain@gmail.com

Changes to this policy

If Arc's data practices change, this document will be updated to match — a shipped build always reflects the code it was actually built from, not aspirational future behavior.