Files
opencode-mobile/distribution/fdroid-submission/metadata.yml
Den 2b9b571d6e 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>
2026-05-25 17:42:03 -07:00

108 lines
4.2 KiB
YAML

# F-Droid metadata for ai.opencode.mobile
# Target file path in fdroiddata: metadata/ai.opencode.mobile.yml
#
# BEFORE FILING THE MR:
# 1. Replace <SIGNING_KEY_SHA256_FINGERPRINT> with the actual colon-separated hex fingerprint
# (found in distribution/SIGNING-KEY-FINGERPRINTS.md)
# 2. Replace <FIRST_GITHUB_RELEASE_TAG> with the first tag that has a signed APK attached
# (e.g. v0.2.4)
# 3. Verify the build steps produce a matching APK against AllowedAPKSigningKeys
#
# Do NOT file this MR until:
# - First Google Play release is live (establishes signing key in production use)
# - Sentry opt-in gate is merged to main (anti-feature Tracking avoided)
# - You have the exact colon-separated SHA-256 key fingerprint confirmed
Categories:
- Development
License: MIT
AuthorName: VIBE TECHNOLOGIES, LLC
AuthorEmail: support@vibebrowser.app
WebSite: https://opencode.vibebrowser.app
SourceCode: https://github.com/dzianisv/opencode-mobile
IssueTracker: https://github.com/dzianisv/opencode-mobile/issues
Changelog: https://github.com/dzianisv/opencode-mobile/releases
Summary: Drive your self-hosted AI coding agent from your phone
Description: |-
OpenCode Mobile is a free, open-source (MIT) client for the opencode AI coding
agent (sst/opencode). Connect to your self-hosted opencode server and drive
AI-powered coding sessions from your phone — no proprietary backend, no mandatory
accounts, no tracking by default.
'''Key features'''
* Multiple connection types — local network, secure tunnels (Cloudflare, ngrok),
or any self-hosted opencode instance
* Biometric unlock — fingerprint / PIN to keep your sessions private
* Real-time streaming chat — watch your AI agent think and respond live
* File diff viewer — see exactly what code changes the agent proposes
* Multi-session management — start, resume, and switch between coding sessions
* Tool call approval — review and approve agent actions before they run
'''Self-hosted first'''
The app requires your own opencode server. Your AI traffic goes directly to your
backend (Claude, GPT, Gemini, local models — your choice). No middleman required.
An optional hosted backend ("opencode Cloud") is planned as a future paid service,
but the client is always free and fully functional without it.
'''Crash reporting'''
Sentry crash reporting is opt-in with default OFF. Code, prompts, and AI responses
never leave your own server.
'''Anti-features'''
NonFreeNet: the opencode server you connect to may connect to proprietary AI
services (OpenAI, Anthropic, Google). The app itself contains no proprietary
network code.
AntiFeatures:
NonFreeNet:
en-US: >-
The app connects to a user-self-hosted opencode server which may in turn
connect to proprietary AI services (OpenAI API, Anthropic API, Google Gemini).
The app itself is fully open source and does not require any specific provider.
RepoType: git
Repo: https://github.com/dzianisv/opencode-mobile
Builds:
- versionName: '1.0.0'
versionCode: 1
commit: <FIRST_GITHUB_RELEASE_TAG>
subdir: android
sudo:
- apt-get update
- apt-get install -y nodejs npm
init:
- npm install --prefix .. --legacy-peer-deps
- npx --prefix .. expo prebuild --platform android --non-interactive
gradle:
- release
ndk: 26.1.10909125
# Node 20+ required for Expo SDK 52+
# prebuild regenerates android/ from app.json + package.json
# The signed AAB/APK is then compared against AllowedAPKSigningKeys
prebuild:
- cd .. && npm install --legacy-peer-deps
- cd .. && npx expo prebuild --platform android --non-interactive
# AllowedAPKSigningKeys pins our release signing key.
# F-Droid will serve our pre-signed APK rather than re-signing with their key.
# This requires reproducible builds (identical output across machines).
AllowedAPKSigningKeys: <SIGNING_KEY_SHA256_FINGERPRINT_LOWERCASE_NO_COLONS>
AutoUpdateMode: Version v%v
UpdateCheckMode: Tags
UpdateCheckData: https://raw.githubusercontent.com/dzianisv/opencode-mobile/main/app.json|"version":\s*"([^"]+)"|.|.
CurrentVersion: '1.0.0'
CurrentVersionCode: 1