Skip to content

[codex] Add native build usage chart#2050

Merged
riderx merged 7 commits into
mainfrom
codex/native-version-usage-chart
May 7, 2026
Merged

[codex] Add native build usage chart#2050
riderx merged 7 commits into
mainfrom
codex/native-version-usage-chart

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 6, 2026

Summary (AI generated)

  • Added native build/version usage tracking to device usage telemetry, split by platform.
  • Added a secured native usage statistics endpoint and chart data path.
  • Added a new Native build by platform chart on the app dashboard second chart row.
  • Added desktop and mobile screenshots for review.

Motivation (AI generated)

Users need to see whether native app builds are still being used per platform, since iOS, Android, and Electron can each ship different native build versions.

Business Impact (AI generated)

This improves release observability for teams using Capgo, helping them reduce support risk and make native app rollout decisions with clearer usage evidence.

Screenshots (AI generated)

Desktop:

Native build by platform chart desktop

Mobile:

Native build by platform chart mobile

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • bun typecheck
  • bun run supabase:db:reset
  • bun scripts/supabase-worktree.ts test db supabase/tests/26_test_rls_policies.sql
  • bun run supabase:with-env -- bunx vitest run tests/statistics.test.ts
  • GitHub CI checks

Generated with AI

Summary by CodeRabbit

  • New Features
    • Native build usage tracking end-to-end with per-build daily charts, latest-version summary, and a Devices Stats dashboard card supporting "native" or "bundle" views with dynamic titles.
  • Translations
    • Added English title key for native build chart.
  • Database
    • Migration to store native build identifiers and add indexes + a native-version usage aggregate function.
  • Tests
    • Added tests covering native version usage endpoint (regular and limited-key).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds native-version (version_build) tracking end-to-end: DB migration and RPC, typed schema updates, collection/read in Supabase & Cloudflare, public API and auth, frontend chart service and DevicesStats card, translation, and tests.

Changes

Native Version Usage

Layer / File(s) Summary
Database Schema & Migration
supabase/migrations/20260506152006_native_version_usage_chart.sql
Adds version_build and platform to public.device_usage, creates indexes, updates RLS, and adds read_native_version_usage RPC returning date/platform/version_build/device counts.
DB Types
src/types/supabase.types.ts, supabase/functions/_backend/utils/supabase.types.ts
Adds version_build to device_usage Row/Insert/Update shapes and declares read_native_version_usage RPC signature.
Backend Types
supabase/functions/_backend/utils/types.ts
Adds NativeVersionUsage interface (date, platform, version_build, devices).
Stats Collection Core
supabase/functions/_backend/utils/stats.ts, supabase/functions/_backend/plugins/stats.ts, supabase/functions/_backend/utils/update.ts
createStatsMau extended to accept/forward optional version_build; call sites updated to pass version_build; exposes readNativeVersionUsage dispatcher.
Supabase Backend Implementation
supabase/functions/_backend/utils/supabase.ts
trackDeviceUsageSB accepts optional versionBuild and inserts platform and version_build (fallback 'unknown'); adds readNativeVersionUsageSB RPC wrapper.
Cloudflare Backend Implementation
supabase/functions/_backend/utils/cloudflare.ts
trackDeviceUsageCF accepts optional version_build, normalizes platform/version, writes analytics blobs keyed by platform/version_build, and adds readNativeVersionUsageCF to aggregate per-day/per-build counts.
Public API & Authorization
supabase/functions/_backend/public/statistics/index.ts
Adds getAuthorizedStatsAppClient, buildNativeVersionCounts, getNativeVersionUsage; refactors /app/:app_id/bundle_usage to use authorized client; replaces /app/:app_id/native_usage to use native reader and return labels/datasets + latestVersion.
Frontend Data Service
src/services/chartDataService.ts
useChartData gains kind: VersionUsageKind = 'bundle'; cache keys include kind; RPC path chosen between native_usage and bundle_usage.
UI Component
src/components/dashboard/DevicesStats.vue
Adds props appId and usageKind; demo generator accepts usageKind; computes activeAppId, isNativeUsage, and titleKey; data loading uses activeAppId and passes usageKind to useChartData; watchers updated; Card title uses new translation key when native.
Page Integration & Layout
src/pages/app/[app].vue
Imports and inserts DevicesStats card with usage-kind="native", adjusts grid from xl:grid-cols-12 to xl:grid-cols-16.
Translations
messages/en.json
Adds active_users_by_native_version: "Native build by platform".
Tests / RLS expectations
tests/statistics.test.ts, supabase/tests/26_test_rls_policies.sql
Adds endpoint tests for native usage (with and without subkey): seed device_usage rows (platform/version_build), call /statistics/app/:app/native_usage, assert labels and datasets, validate metaCounts when applicable, and update RLS policy expectations test.

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant API as Statistics_API
  participant Auth as Auth_Checker
  participant Backend as Stats_Backend
  participant DB as Database_Analytics

  Frontend->>API: GET /statistics/app/:app/native_usage (app_id, date range)
  API->>Auth: validate API key / subkey & RBAC
  Auth-->>API: authorized
  API->>Backend: readNativeVersionUsage(app_id, start, end)
  Backend->>DB: query device_usage (group by date, platform, version_build) / or AE read
  DB-->>Backend: rows (date, platform, version_build, devices)
  Backend-->>API: aggregated labels, datasets, latestVersion
  API-->>Frontend: { labels, datasets, latestVersion }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Cap-go/capgo#1459: Related changes in the stats subsystem touching version tracking and backend stats utilities.

"I hopped through rows and indexed trees,
I counted builds on busy breeze,
From DB to charts I danced and spun,
Native versions all in one—
A carrot-coded victory, whee!" 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main feature: adding a native build usage chart to the dashboard.
Description check ✅ Passed The PR description includes all required sections: summary, test plan with specific commands executed, and screenshots for both desktop and mobile views.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/native-version-usage-chart

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 6, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/native-version-usage-chart (e67d3c5) with main (910dad1)

Open in CodSpeed

@riderx riderx force-pushed the codex/native-version-usage-chart branch from 8fdf79c to b0282c1 Compare May 6, 2026 16:05
@riderx riderx marked this pull request as ready for review May 6, 2026 16:13
@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

return `${kind}|${appId}|${formatDateParam(from)}|${formatDateParam(to)}`

P2 Badge Keep app-level cache invalidation key-compatible

Update the cache-key format and the app-scoped invalidation logic together. This key now starts with kind, but clearChartDataCache(appId) still filters with key.startsWith(${appId}|), so any caller that tries to invalidate one app’s chart data will leave stale entries behind (both bundle/native variants), and subsequent fetches can keep serving cached data instead of refreshed statistics.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@riderx riderx force-pushed the codex/native-version-usage-chart branch from b0282c1 to de6c7ce Compare May 6, 2026 16:30
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

if (error) {
cloudlogErr({ requestId: c.get('requestId'), message: 'Error reading native version usage', error })
return []

P2 Badge Propagate native usage RPC failures instead of empty data

When read_native_version_usage fails (for example, migration not applied yet, permission drift, or transient DB errors), this path logs the error and returns [], so /statistics/app/:app_id/native_usage responds 200 with an empty dataset instead of surfacing a failure. That silently masks backend issues and makes the new chart look like genuine zero usage, unlike bundle_usage which reports a 500 on query failure.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@riderx riderx force-pushed the codex/native-version-usage-chart branch from de6c7ce to 31d0d59 Compare May 6, 2026 16:46
@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

Addressed the Codex review feedback in 31d0d599f: app-scoped chart cache invalidation is key-compatible again, native usage RPC errors now propagate as endpoint failures, and the SonarCloud regex hotspot was removed.

@riderx riderx force-pushed the codex/native-version-usage-chart branch from 31d0d59 to f3c55c2 Compare May 6, 2026 22:15
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/statistics.test.ts`:
- Around line 148-170: The test is brittle because it relies on common
version_build labels ("1.0.0", "1.1.0") that other parallel tests may also seed;
update the seeded events (the array of objects you push before calling
.throwOnError()) to use per-test unique version_build values (e.g., incorporate
the test's prefix or a random/suffix token like `${prefix}-1.0.0` and
`${prefix}-1.1.0`) and then update the assertions that look up datasets
(variables version100 and version110) to search for those unique labels; this
ensures getNativeUsage / nativeUsageData.datasets are matched to the
test-specific version_build values and prevents cross-test collisions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6281fc1a-d819-4a47-81a7-1a67ebcda115

📥 Commits

Reviewing files that changed from the base of the PR and between 0396172 and f3c55c2.

⛔ Files ignored due to path filters (2)
  • docs/pr-screenshots/native-version-usage-desktop.png is excluded by !**/*.png
  • docs/pr-screenshots/native-version-usage-mobile.png is excluded by !**/*.png
📒 Files selected for processing (15)
  • messages/en.json
  • src/components/dashboard/DevicesStats.vue
  • src/pages/app/[app].vue
  • src/services/chartDataService.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/plugins/stats.ts
  • supabase/functions/_backend/public/statistics/index.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/stats.ts
  • supabase/functions/_backend/utils/supabase.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/types.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260506152006_native_version_usage_chart.sql
  • tests/statistics.test.ts

Comment thread tests/statistics.test.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
supabase/functions/_backend/public/statistics/index.ts (1)

711-720: ⚡ Quick win

Use the existing stats retry wrapper for the native usage read.

This is the only new stats path here that goes straight from the backend read to a 500. A transient PostgREST/schema-cache failure will fail the native chart even though the other statistics handlers in this module already recover via executeStatsQueryWithRetry(...).

Suggested shape
 async function getNativeVersionUsage(c: Context, appId: string, from: Date, to: Date) {
   const dates = generateDateLabels(from, to)
   const startDate = dayjs(from).utc().startOf('day').format('YYYY-MM-DD')
   const endDate = dayjs(to).utc().startOf('day').add(1, 'day').format('YYYY-MM-DD')
-  let nativeVersionUsage: NativeVersionUsageRow[]
-  try {
-    nativeVersionUsage = await readNativeVersionUsage(c, appId, startDate, endDate) as NativeVersionUsageRow[]
-  }
-  catch (error) {
+  const { data: nativeVersionUsage, error } = await executeStatsQueryWithRetry<NativeVersionUsageRow[]>(
+    c,
+    'read_native_version_usage',
+    async () => {
+      try {
+        return {
+          data: await readNativeVersionUsage(c, appId, startDate, endDate) as NativeVersionUsageRow[],
+          error: null,
+        }
+      }
+      catch (error) {
+        return { data: null, error }
+      }
+    },
+  )
+
+  if (error) {
     return { data: null, error }
   }
+
   const seriesNames = [...new Set(nativeVersionUsage.map(getNativeVersionSeriesName))]
   const dailyCounts = buildNativeVersionCounts(nativeVersionUsage, dates, seriesNames)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/statistics/index.ts` around lines 711 -
720, In getNativeVersionUsage, don't call readNativeVersionUsage directly;
instead wrap it with the existing retry helper executeStatsQueryWithRetry so
transient PostgREST/schema-cache failures are retried. Replace the direct await
readNativeVersionUsage(c, appId, startDate, endDate) with a call to
executeStatsQueryWithRetry(() => readNativeVersionUsage(c, appId, startDate,
endDate), c) (or the module's executeStatsQueryWithRetry signature) and
assign/return the resulting NativeVersionUsageRow[] so the rest of
getNativeVersionUsage continues to use nativeVersionUsage as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/utils/supabase.ts`:
- Around line 1165-1174: The helper readNativeVersionUsageSB currently uses the
service-role client supabaseAdmin(c) which bypasses RLS; change it to use the
authenticated Supabase client used by public endpoints (the same pattern as
other public stats handlers) by either adding a Supabase client parameter to
readNativeVersionUsageSB or by calling the context-bound user client (instead of
supabaseAdmin(c)), then call its rpc('read_native_version_usage', ...) and keep
the existing error logging/throw behavior; ensure callers of
readNativeVersionUsageSB (the /statistics/app/:app_id/native_usage path) are
updated to pass the authenticated client rather than relying on the service key.

---

Nitpick comments:
In `@supabase/functions/_backend/public/statistics/index.ts`:
- Around line 711-720: In getNativeVersionUsage, don't call
readNativeVersionUsage directly; instead wrap it with the existing retry helper
executeStatsQueryWithRetry so transient PostgREST/schema-cache failures are
retried. Replace the direct await readNativeVersionUsage(c, appId, startDate,
endDate) with a call to executeStatsQueryWithRetry(() =>
readNativeVersionUsage(c, appId, startDate, endDate), c) (or the module's
executeStatsQueryWithRetry signature) and assign/return the resulting
NativeVersionUsageRow[] so the rest of getNativeVersionUsage continues to use
nativeVersionUsage as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6451f53a-0cb1-4ce4-b917-622ccb1a1e66

📥 Commits

Reviewing files that changed from the base of the PR and between d1cf325 and 52c78a2.

📒 Files selected for processing (10)
  • messages/en.json
  • src/types/supabase.types.ts
  • supabase/functions/_backend/public/statistics/index.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/stats.ts
  • supabase/functions/_backend/utils/supabase.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/types.ts
  • supabase/migrations/20260506152006_native_version_usage_chart.sql
  • tests/statistics.test.ts
✅ Files skipped from review due to trivial changes (1)
  • messages/en.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • supabase/functions/_backend/utils/types.ts
  • tests/statistics.test.ts
  • supabase/migrations/20260506152006_native_version_usage_chart.sql
  • supabase/functions/_backend/utils/supabase.types.ts

Comment thread supabase/functions/_backend/utils/supabase.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
supabase/migrations/20260506152006_native_version_usage_chart.sql (1)

149-153: 💤 Low value

Minor: Function comment mentions "Authenticated" but function grants to anon as well.

The comment says "Authenticated aggregate" but the function is also granted to anon. Consider updating the comment to reflect that both authenticated users and API keys (via anon role) can execute this function.

 COMMENT ON FUNCTION public.read_native_version_usage(
     character varying,
     timestamp without time zone,
     timestamp without time zone
-) IS 'Authenticated aggregate for native version usage by platform.';
+) IS 'Aggregate for native version usage by platform (authenticated and API key access).';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260506152006_native_version_usage_chart.sql` around
lines 149 - 153, The function comment for read_native_version_usage inaccurately
calls it an "Authenticated aggregate" while the function is also granted to the
anon role; update the COMMENT ON FUNCTION text to reflect that execution is
allowed for both authenticated users and anon (API key) callers (or reword to
"Accessible to authenticated users and anon/API key callers") so the comment
matches the GRANT behavior for read_native_version_usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@supabase/migrations/20260506152006_native_version_usage_chart.sql`:
- Around line 149-153: The function comment for read_native_version_usage
inaccurately calls it an "Authenticated aggregate" while the function is also
granted to the anon role; update the COMMENT ON FUNCTION text to reflect that
execution is allowed for both authenticated users and anon (API key) callers (or
reword to "Accessible to authenticated users and anon/API key callers") so the
comment matches the GRANT behavior for read_native_version_usage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 05379371-2594-41bf-a823-5c61ed537e17

📥 Commits

Reviewing files that changed from the base of the PR and between 52c78a2 and 16251a1.

📒 Files selected for processing (5)
  • supabase/functions/_backend/public/statistics/index.ts
  • supabase/functions/_backend/utils/stats.ts
  • supabase/functions/_backend/utils/supabase.ts
  • supabase/migrations/20260506152006_native_version_usage_chart.sql
  • supabase/tests/26_test_rls_policies.sql
🚧 Files skipped from review as they are similar to previous changes (1)
  • supabase/functions/_backend/utils/supabase.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/dashboard/DevicesStats.vue`:
- Around line 707-726: The early return in the watch callback prevents reacting
to usageKind changes when props.appId is empty; move extraction of old values
(oldPackageId and oldUsageKind) above the early return and change the guard to
only return when there is no packageId and the usageKind did not change (e.g. if
(!packageId && usageKind === oldUsageKind) return), so that usageKind changes
still trigger cache reset (cachedBillingData, cached30DayData), assignment to
appId, and loadData(true) as currently orchestrated by the existing
packageChanged check and loadData call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: da706adf-648f-4a9b-8dfc-c437eb2ed01c

📥 Commits

Reviewing files that changed from the base of the PR and between 16251a1 and 99e9d04.

⛔ Files ignored due to path filters (2)
  • docs/pr-screenshots/native-version-usage-desktop.png is excluded by !**/*.png
  • docs/pr-screenshots/native-version-usage-mobile.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • src/components/dashboard/DevicesStats.vue

Comment thread src/components/dashboard/DevicesStats.vue
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99e9d041ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/migrations/20260506152006_native_version_usage_chart.sql Outdated
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

@riderx riderx merged commit 161a070 into main May 7, 2026
49 of 50 checks passed
@riderx riderx deleted the codex/native-version-usage-chart branch May 7, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant