feat(privacy+dist): telemetry consent gate + app store distribution prep (#4)

* fix(security): fail closed on biometric init error

H-03: setting isAuthenticated: true on initialization failure was a
security bypass — any crash during biometric setup granted full access.
Fail closed instead; user sees auth prompt on next open.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(security): use Crypto.randomUUID for connection IDs

H-04: Math.random() is not cryptographically random. Connection IDs are
used as SecureStore key suffixes; switch to expo-crypto randomUUID for
a secure source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(deps): pin expo-crypto to ~15.0.9

15.0.10 does not exist on npm; ~15.0.9 is the latest stable in the 15.x series compatible with Expo SDK 54.

* feat: add OpenCode Connect coming-soon waitlist card

Adds a discoverable 'OpenCode Connect — Coming Soon' card to the
add-connection quick-connect screen. Users can enter their email and
tap 'Join Waitlist' to send a pre-filled mailto. No backend required.

* fix(cua): detect actual screen dimensions and fix JSON parsing

- Get real screen size via `wm size` instead of hardcoding 1080x2400;
  emulator is 1080x1920 so y-coordinates were systematically off
- Extract first JSON object via regex when model returns multiple objects
- Use AZURE_OPENAI_MODEL env var for deployment name (defaults gpt-5.4)
- Add AZURE_DEV_AI_* path for Azure AI Foundry endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(security): SHA-pin upload-google-play and sanitize notification bodies

M-02: Pin r0adkll/upload-google-play to commit SHA e738b9d (v1.1.5)
to prevent supply-chain hijack via tag mutation.

M-03: Sanitize all push notification bodies — strip control chars,
truncate to 200 chars. Prevents server-supplied strings (error messages,
file paths from permission patterns, session titles) from leaking
unbounded text into the OS notification drawer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(privacy): add telemetry consent gate for Sentry crash reporting

Sentry was always-on, violating F-Droid anti-feature policy and user
trust norms. Now gated behind explicit opt-in:

- First-launch consent modal (TelemetryConsentModal) shows once on
  fresh install; user can Allow or Decline.
- Consent state persisted in expo-secure-store (survives restarts).
- Settings > Privacy section: crash reporting toggle + privacy policy link.
- initSentry() called only after consent granted — not on app start.

Closes #3 (partial)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(config): add real icons and complete iOS/Android app.json config

- Add 1024×1024 app icon, 432×432 adaptive icon foreground, 200×200 splash
- iOS: push notification entitlement (aps-environment: production), speech/
  microphone/camera/photo usage descriptions for future features, disable
  ITSAppUsesNonExemptEncryption
- Android: adaptive icon with dark background (#0F172A), versionCode: 1
- expo-notifications plugin wired in app.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(dist): add iOS CI workflow, README rewrite, CONTRIBUTING, and LICENSE

- publish-app-store.yml: EAS Build + TestFlight submission; runs on tag/release/
  workflow_dispatch; bumps ios.buildNumber from github.run_number
- README: full rewrite — features, install badges, connection guide, contributing
- CONTRIBUTING.md: contribution guide for OSS contributors
- LICENSE: MIT

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(dist): add store listings, strategy, privacy policy, F-Droid/IzzyOnDroid templates

- distribution/strategy.md: monetization strategy (free client + opencode Cloud)
- distribution/play-listing.md: Google Play store copy (name, description, tags)
- distribution/app-store-listing.md: App Store listing copy
- distribution/privacy-policy.{md,html}: GDPR-compliant privacy policy
- distribution/PLAY_CONSOLE_SETUP.md: Play Console setup runbook
- distribution/ios-enrollment-runbook.md: Apple Developer Program enrollment steps
- distribution/SIGNING-KEY-FINGERPRINTS.md: keystore fingerprint for reproducible builds
- distribution/fdroid-submission/: F-Droid metadata template
- distribution/izzyondroid-submission/: IzzyOnDroid submission template
- distribution/whatsnew/: Play Store release notes (en-US)
- distribution/whatsnew-ios/: TestFlight release notes
- distribution/play-graphics/: Play Store screenshot placeholders
- distribution/app-store-graphics/: App Store screenshot placeholders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(telemetry): handle SecureStore failure + Android back button

- add .catch() on loadTelemetryConsent() so SecureStore rejection
  shows the consent modal instead of blocking startup forever
- add onRequestClose={onDecline} to Modal so Android back button
  records the decline rather than silently dismissing
- fix catch block in telemetry.ts to not clobber _resolved when
  SecureStore read fails mid-session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ci): run gradlew clean to prevent stale modules.json duplicate

Sentry Gradle plugin writes modules.json to src/main/assets; cached
build intermediates contain an old copy → mergeReleaseAssets fails
with 'Duplicate resources'. Running clean before assembleRelease
clears the intermediate state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ci): remove android build output cache causing duplicate modules.json

Caching android/app/build/intermediates and android/app/.cxx causes
two issues:
1. Stale modules.json in intermediates → Duplicate resources error
2. .cxx CMake artifacts reference absolute paths → ninja clean fails

Keeping only Gradle distribution cache (~/.gradle) which is safe.
Expo prebuild regenerates android sources fresh each run anyway.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Den
2026-05-25 17:42:03 -07:00
committed by GitHub
parent 7ea41216c8
commit 2b9b571d6e
51 changed files with 3463 additions and 98 deletions

View File

@@ -0,0 +1,164 @@
# OpenCode Mobile — Privacy Policy
**Effective date:** 2026-05-24
**Operator:** VIBE TECHNOLOGIES, LLC
**App:** OpenCode Mobile (`ai.opencode.mobile`)
> **Summary:** OpenCode Mobile does not collect your code, prompts, AI responses, server URLs, or any chat content. All AI traffic goes directly from the app to your own opencode server. We use Sentry only for anonymous crash diagnostics, and only with your consent.
---
## 1. Who We Are
OpenCode Mobile is developed and distributed by **VIBE TECHNOLOGIES, LLC**, a Washington State limited liability company.
- Address: 519 S Henderson St, Seattle, WA 98108-4522, USA
- Contact: support@vibebrowser.app
- Source code: https://github.com/dzianisv/opencode-mobile (MIT license)
---
## 2. Data We Do NOT Collect
We never collect, transmit to our servers, or share with third parties:
- Your code, files, or repository content
- Your prompts, chat messages, or AI responses
- Your opencode server URL, IP address, or hostname
- Authentication tokens, API keys, or credentials you enter
- Account information, email addresses, or names
- Location data
- Photos, microphone recordings, or camera data (these go only to your own server if you attach them to a message)
- Contacts, calendar, or any other personal data
All communication between the app and your AI coding agent travels directly between your device and your self-hosted opencode server. VIBE TECHNOLOGIES, LLC never sees this traffic.
---
## 3. Data We Do Collect (Crash Diagnostics)
With your explicit consent (shown at first launch), we collect anonymous crash diagnostic data via **Sentry** to help us identify and fix bugs.
| Data type | What is captured | What is NOT captured |
|---|---|---|
| Device info | Device model, OS version, screen resolution, app version | Serial number, IMEI, advertising ID |
| Crash / error reports | Stack traces, exception types and messages, source file names and line numbers | Variable values; no user data in scope |
| Breadcrumbs | Screen names and function call sequence leading to the crash | Message bodies, server URLs, prompt text — all stripped by our URL-scrubbing filter |
| App version | Version string and build number | — |
URL scrubbing: before any event is sent to Sentry, our code strips all server URLs, authentication tokens, and query parameters. No server hostname or port number ever leaves your device via Sentry.
---
## 4. Consent and Control
Crash reporting is **opt-in and off by default**. On first launch you will see a consent prompt. You can change this at any time:
- Open the app → **Settings** → **Privacy** → **Crash reporting** toggle.
- When the toggle is off, Sentry is never initialised and no data leaves your device.
---
## 5. Third-Party Services
We use one third-party service for diagnostics:
- **Sentry** — crash and error monitoring.
- Privacy policy: https://sentry.io/privacy/
- Data is sent to Sentry's US-based servers and retained for approximately 90 days per Sentry's default data-retention policy.
We use no advertising networks, analytics platforms, social SDKs, or any other third-party data collection services. The app contains no ads and no ad SDKs.
---
## 6. Data Retention
Crash reports sent to Sentry are retained for approximately 90 days, after which they are automatically deleted per Sentry's retention defaults.
We do not operate our own servers that store your data; there is no VIBE TECHNOLOGIES back end involved in normal app usage.
---
## 7. Your Rights
You have the right to:
- **Opt out** — disable crash reporting at any time in Settings → Privacy.
- **Request deletion** — email support@vibebrowser.app with subject "Data deletion request" and we will request deletion of any crash events associated with your device from Sentry.
- **Access** — request a summary of what diagnostic data (if any) we hold about your device by emailing the same address.
Residents of the EU/EEA/UK may exercise rights under GDPR/UK GDPR. California residents may exercise rights under the CCPA.
---
## 8. Children
OpenCode Mobile is a developer tool intended for users aged 18 and over. We do not knowingly collect any data from children under 13 (or under 16 in the EU).
---
## 9. Security
All diagnostic data is transmitted over HTTPS (TLS 1.2+) to Sentry. We do not transmit any data over unencrypted connections.
---
## 10. Changes to This Policy
If we make material changes to this policy, we will update the effective date and, where feasible, notify users via an in-app notice. The latest version is always available at:
https://www.vibebrowser.app/opencode-mobile/privacy
---
## 11. Contact
VIBE TECHNOLOGIES, LLC
519 S Henderson St
Seattle, WA 98108-4522
USA
Email: support@vibebrowser.app
---
## Apple-Specific Addendum (iOS / App Store)
This addendum addresses Apple's specific privacy disclosure requirements for iOS apps distributed through the Apple App Store.
### App Tracking Transparency (ATT)
OpenCode Mobile does **not** use Apple's App Tracking Transparency (`AppTrackingTransparency`) framework. The app does **not**:
- Access the IDFA (Identifier for Advertisers)
- Use any cross-app or cross-website tracking
- Participate in any advertising network
- Profile users for advertising or marketing purposes
No ATT permission prompt is ever shown to users because there is nothing to track.
### Apple Privacy Nutrition Label Data Categories
The following table maps our data practices to Apple's official App Privacy categories (as required in App Store Connect):
| Apple Category | Sub-category | Collected? | Linked to identity? | Used for tracking? |
|---|---|---|---|---|
| Contact Info | Name, email, phone, address | No | N/A | No |
| Health & Fitness | Any | No | N/A | No |
| Financial Info | Any | No | N/A | No |
| Location | Precise or coarse | No | N/A | No |
| Sensitive Info | Any | No | N/A | No |
| Contacts | Any | No | N/A | No |
| User Content | Emails, messages, audio, gameplay, other | No | N/A | No |
| Browsing History | Any | No | N/A | No |
| Search History | Any | No | N/A | No |
| Identifiers | User ID | No | N/A | No |
| Identifiers | Device ID | Yes (Sentry anonymous ID) | No — not linked to Apple ID or personal info | No |
| Purchases | Any | No | N/A | No |
| Usage Data | Product interaction | No | N/A | No |
| Diagnostics | Crash Data | Yes (Sentry, with consent) | No | No |
| Diagnostics | Performance Data | Yes (Sentry, with consent) | No | No |
| Diagnostics | Other Diagnostic Data | No | N/A | No |
**Summary for App Store Connect App Privacy section**:
- Data Linked to You: **None**
- Data Not Linked to You: **Crash Data, Performance Data** (Sentry diagnostics, when user consents)
- Tracking: **No**