* fix(metrics): repair review triage — correct secret wiring, privacy-safe aggregated issues - triage-reviews.yml read secrets.GOOGLE_SERVICE_ACCOUNT_JSON, which doesn't exist; map the real PLAY_STORE_SERVICE_ACCOUNT_JSON secret onto the env var the script expects. - triage-reviews.py rewritten to maintain a single sanitized, deduped "Play Store Review Triage" issue instead of one public issue per review. The old version leaked reviewer full names and verbatim review text into public GitHub issues and spammed the tracker. The new version aggregates actionable (<=3 star) reviews into one issue with rating counts, a word-frequency theme summary (no quoted sentences), and opaque review_id references for Play Console lookup. An embedded HTML comment marker (matching the product-intelligence.mjs pattern) holds the current actionable review_id set so runs update in place and skip entirely when nothing changed. - product-intelligence.yml referenced the nonexistent SENTRY_PRODUCT_INTELLIGENCE_TOKEN secret, causing the daily cron to fail silently (#60). Fall back to SENTRY_AUTH_TOKEN when the dedicated read-only token isn't configured. - docs/playstore.md: document that Play Console is still the only trusted source for acquisition/uninstall metrics (product-intelligence.mjs defers this), and that review-based signals are sourced via the Android Publisher API through PLAY_STORE_SERVICE_ACCOUNT_JSON. Closes #61. Refs #60. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NJKAQ6HAikWGQK7PGZ5Y4E * fix(triage): fail visibly when GOOGLE_SERVICE_ACCOUNT_JSON is missing Review finding on PR #78: env_client() exited 0 on missing credentials, so the scheduled workflow would report success while silently doing nothing — contradicting issue #61's 'missing credentials fail visibly' done-criteria. --------- Co-authored-by: engineer <engineer@gray-knight-m1.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
8.4 KiB
Google Play Store — opencode-mobile
Operational doc for shipping ai.opencode.mobile to Google Play under VIBE TECHNOLOGIES, LLC.
For full company facts (D-U-N-S, address, governor, etc.) see ~/.agents/skills/vibetechnologies-llc/SKILL.md and Bitwarden item GOOGLE_PLAY_CONSOLE_ACCOUNT.
Account state (as of 2026-05-24)
| Field | Value |
|---|---|
| Google account (owner) | vibeteaichnologies@gmail.com |
| Developer Account ID | 8842655543970815326 |
| Account type | Organization — VIBE TECHNOLOGIES, LLC |
| Developer name (public) | VIBE TECHNOLOGIES, LLC |
| D-U-N-S | 142059652 |
| Console URL | https://play.google.com/console/u/2/developers/8842655543970815326 |
| Registration fee | ✅ $25 paid via Mercury virtual card (Bitwarden: MERCURY_VIRTUAL_CARD_PLAY_CONSOLE) |
| Payments profile | ✅ linked, D-U-N-S verified |
| Website ownership | ✅ verified — https://agentlabs.cc/ (Search Console auto-detected meta tag) |
| Contact email | ✅ support@agentlabs.cc verified |
| Identity verification | ❌ pending — needs governor ID upload at Home → Verify your identity |
| Phone verification | ⏸ auto after identity |
| API access (GCP link) | ⏸ blocked on identity (URL /api-access redirects home) |
| Create app | ⏸ blocked on identity |
| First AAB upload | ⏸ blocked on app creation |
Linked GCP resources
| Resource | Value |
|---|---|
| Project | opencode-mobile-deploy |
| Service account | playstore-deploy@opencode-mobile-deploy.iam.gserviceaccount.com |
| API enabled | androidpublisher.googleapis.com |
| SA JSON key | ✅ in Bitwarden item PLAY_STORE_SERVICE_ACCOUNT_JSON + GitHub secret of same name |
What's already done
- ✅ gcloud authed as
vibeteaichnologies@gmail.com - ✅ GCP project + API + service account + JSON key
- ✅ JSON key saved to Bitwarden + set as GitHub secret
- ✅ Signed release AAB built:
android/app/build/outputs/bundle/release/app-release.aab(58.5 MB, sha256ae3a8aa498dfa188226ec5db06ba51cc77cf94c6a311be097f1c47534b2aff61) - ✅ Play Developer account created + $25 paid
- ✅ Payments profile linked w/ D-U-N-S 142059652
- ✅ Website + email verifications complete
- ✅ CI workflow
.github/workflows/publish-play-store.ymlpatched:- versionCode auto-bumped from
github.run_number(was hardcoded1, would have failed on 2nd release) - r0adkll/upload-google-play pinned to v1.1.5
whatsNewDirectory: distribution/whatsnewadded
- versionCode auto-bumped from
- ✅ Listing copy drafted:
distribution/play-listing.md - ✅ Release notes scaffold:
distribution/whatsnew/whatsnew-en-US
What's left to do — eligibility checklist
| # | Item | Owner | Blocking? |
|---|---|---|---|
| 1 | Upload governor ID for identity verification | User | 🔴 yes |
| 2 | App icon — real 512×512 PNG (current assets/icon.json is placeholder) |
Agent | ✅ done — assets/icon.png (1024×1024 master), distribution/play-graphics/icon-512.png (512×512 store upload) |
| 3 | Adaptive icon — 432×432 foreground PNG | Agent | ✅ done — assets/adaptive-icon.png (432×432, transparent bg) |
| 4 | Feature graphic — 1024×500 PNG | Agent | ✅ done — distribution/play-graphics/feature-graphic.png |
| 5 | At least 2 phone screenshots (1080×1920 or similar) | Agent | ✅ done — distribution/play-graphics/phone-{01,02,03}.png (1080×2400 each; 3 screens: connection, chat, diff viewer) |
| 6 | Privacy policy — live at https://dzianisv.github.io/opencode-mobile/privacy/ | Agent | ✅ done — live & verified (HTTP 200) on gh-pages; distribution/privacy-policy.html (source), distribution/privacy-policy.md (markdown mirror) |
| 7 | Data safety form answers (drafted in distribution/play-listing.md) |
User (in Console after app created) | ✅ verified — no analytics/ad SDKs found; crash logs updated to "Optional (opt-in, default OFF)" per new consent gate |
| 8 | Content rating questionnaire (IARC, drafted) | User (in Console after app created) | ✅ verified — no violence/sexual/gambling/UGC; "interact with other users" = No (user talks to own AI agent) |
| 9 | App access — reviewer instructions for self-hosted opencode (drafted) | User | ✅ verified — instructions accurate; npm install -g opencode-ai && opencode serve flow confirmed in play-listing.md |
| 10 | Sentry opt-in consent gate (for F-Droid parity + GDPR friendly) | Agent | ✅ done — src/lib/telemetry.ts (consent store), src/components/TelemetryConsentModal.tsx (first-launch modal), app/_layout.tsx (gated init), app/(tabs)/settings.tsx (Privacy section toggle) |
| 11 | Closed testing recruitment — 12+ testers, 14 days | User | ⏸ post-Internal-track |
Publishing process (after identity verified)
- (manual) Setup → API access → Link
opencode-mobile-deploy. Grantplaystore-deploy@…"Release to production, exclude devices, and use Play App Signing". - (manual) Create app
ai.opencode.mobile. Fill listing fromdistribution/play-listing.md. - (manual) Upload graphic assets + privacy policy URL.
- (manual) Complete Data safety + Content rating + App access forms.
- (manual, first time only) Upload
app-release.aabto Internal testing track → add tester emails → publish. - (automated thereafter)
git tag v0.2.x && git push --tags→ CI builds + publishes to Internal.
After 14 days on Closed testing with 12+ active testers → promote to Production.
Files in repo
.github/workflows/publish-play-store.yml— CI automationdistribution/play-listing.md— store listing copydistribution/whatsnew/whatsnew-en-US— release notesdistribution/strategy.md— broader distribution + monetization strategykeystores/production-release.jks— signing key (gitignored; backup in Bitwarden)android/— Expo prebuild output (regenerated each CI run)
Acquisition metrics — trusted source
There is currently no verified, least-privilege source wired up for Play
Store acquisition/uninstall metrics (installs, uninstalls, store listing
conversion). scripts/product-intelligence.mjs explicitly lists this as a
deferred metric until a proper reporting contract exists — do not treat
ad-hoc Play Console screenshots or manual exports as a trusted feed for
automated reporting.
Until that's implemented, the Play Console UI
(https://play.google.com/console/u/2/developers/8842655543970815326) is the
only source of truth for acquisition numbers, checked manually. Review
volume/rating triage (a related but separate signal) is automated via
.github/workflows/triage-reviews.yml + scripts/triage-reviews.py, which
reads reviews through the Android Publisher API using the
PLAY_STORE_SERVICE_ACCOUNT_JSON GitHub secret (see "Linked GCP resources"
above) — this is the trusted source for review-based signals, not any
scraped or manually copied review text.
Sibling channels: F-Droid + IzzyOnDroid
OpenCode Mobile is also distributed via F-Droid (mainline) and IzzyOnDroid — the two primary OSS Android app stores for privacy-conscious users.
All three channels use the same signing key and same package id (ai.opencode.mobile),
so users can update in-place across stores.
Submission packets (ready to file after the first Play release is live):
distribution/fdroid-submission/— F-Droid mainline MR packetmetadata.yml— ready-to-PR fdroiddata metadataSUBMISSION-CHECKLIST.md— step-by-step MR filing guideREPRODUCIBLE-BUILD-NOTES.md— reproducibility audit + fixes neededSIZE-OPTIMIZATION.md— APK ABI splits + FCM flavor documentation
distribution/izzyondroid-submission/— IzzyOnDroid inclusion request packetINCLUSION-REQUEST.md— ready-to-paste Codeberg issue bodySUBMISSION-CHECKLIST.md— step-by-step filing guide
distribution/SIGNING-KEY-FINGERPRINTS.md— signing key SHA-256 fingerprintsdocs/fdroid.md— operational doc for F-Droid / IzzyOnDroid (mirrors this doc)
Timeline: IzzyOnDroid 1–3 days after first APK on GitHub releases. F-Droid mainline 4–12 weeks after MR filed.
Reference
- Console: https://play.google.com/console/u/2/developers/8842655543970815326
- Account details: https://play.google.com/console/u/2/developers/8842655543970815326/account/developer-details
- Identity verification: https://play.google.com/console/u/2/developers/8842655543970815326/app-list (Home → Verify your identity)
- Original handoff doc:
opencode-mobile.playstore.md(root, mostly historical) - Setup notes:
distribution/PLAY_CONSOLE_SETUP.md(historical)