Skip to content

Conversation

@riderx
Copy link
Member

@riderx riderx commented Jan 8, 2026

Summary

Added full support for the Electron platform across the codebase. Electron devices can now use the Capgo update system alongside iOS and Android devices. This includes database schema updates, backend API support, frontend UI, platform-specific logic, comprehensive tests, and translations in all 15 languages.

Test plan

  • Run bun test:backend to verify electron platform validation in channel_self and updates endpoints
  • Check app settings to ensure electron channels can be configured
  • Verify deployment banner displays electron platform alongside iOS and Android
  • Test that channels can be marked as electron-only or combined with other platforms

Checklist

  • Code follows project style and passes linting
  • Database migration created for electron platform enum
  • Backend validation updated for electron platform
  • Frontend components updated with electron support
  • Comprehensive tests added for electron functionality
  • Translations added for all 15 languages

Summary by CodeRabbit

  • New Features
    • Electron added as a supported deployment platform; channels and compatibility now include Electron.
  • UI / Translations
    • UI labels and translations added for Electron across all supported locales.
  • Behavior
    • Update attempts for channels without Electron enabled are blocked with a clear response and telemetry event.
  • Admin / Analytics
    • Admin dashboards and device counts now include Electron metrics.
  • Tests
    • Added tests covering Electron platform flows and validations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 8, 2026

Warning

Rate limit exceeded

@riderx has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 40 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 03b4159 and 5840bb9.

📒 Files selected for processing (29)
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/hi.json
  • messages/id.json
  • messages/it.json
  • messages/ja.json
  • messages/ko.json
  • messages/pl.json
  • messages/pt-br.json
  • messages/ru.json
  • messages/tr.json
  • messages/vi.json
  • messages/zh-cn.json
  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
  • tests/channel_self.test.ts
  • tests/updates.test.ts
📝 Walkthrough

Walkthrough

Adds first-class Electron platform support across locales, DB schema/migration/seed, TypeScript DB types, backend validation/channel selection, analytics/cloudflare mappings, frontend channel/platform handling, and tests.

Changes

Cohort / File(s) Summary
Translations
messages/de.json, messages/en.json, messages/es.json, messages/fr.json, messages/hi.json, messages/id.json, messages/it.json, messages/ja.json, messages/ko.json, messages/pl.json, messages/pt-br.json, messages/ru.json, messages/tr.json, messages/vi.json, messages/zh-cn.json
Added action-disable-platform-electron, channel-platform-electron, and platform-electron keys in each locale.
DB Migration & Seed
supabase/migrations/20260108000000_add_electron_platform.sql, supabase/seed.sql
Migration adds electron value to platform_os, adds disablePlatformElectron to stats_action, and adds channels.electron BOOLEAN NOT NULL DEFAULT TRUE; seed inserts an electron_only channel row and test device, updates INSERTs/IDs.
Type Definitions
src/types/supabase.types.ts, supabase/functions/_backend/utils/supabase.types.ts
Add graphql_public namespace; extend platform_os enum with electron; add electron: boolean to channels Row/Insert/Update; add disablePlatformElectron to stats_action; other enum/type adjustments.
Frontend Components
src/components/dashboard/AppSetting.vue, src/components/dashboard/DeploymentBanner.vue
Channel shapes and queries include electron; PlatformKey, deploy-target computation, default-channel filtering, and platform label generation extended to include Electron.
Backend: Channel & Updates
supabase/functions/_backend/plugins/channel_self.ts, supabase/functions/_backend/plugins/updates.ts, supabase/functions/_backend/utils/update.ts
Validation and channel-selection logic accept 'electron'; added runtime guard that blocks electron updates when channel.electron is false and emits disablePlatformElectron stat.
Backend: Postgres Utilities
supabase/functions/_backend/utils/pg.ts, supabase/functions/_backend/utils/postgres_schema.ts
PG helpers/selects now include channels.electron; getCompatibleChannelsPg accepts 'electron' and returns electron: boolean; schema declaration adds channels.electron.
Backend: Analytics / Cloudflare
supabase/functions/_backend/utils/cloudflare.ts
Map Electron to platform value 2 for tracking/reading; add electron_devices to admin overview queries, types, and responses.
Tests
tests/channel_self.test.ts, tests/updates.test.ts
Added tests covering electron platform for channel listing/compatibility and update validation.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant UpdatesFn as Updates Function
  participant PG as Database
  participant Stats as Stats Logger

  Client->>UpdatesFn: POST /updates { platform: "electron", version_name, ... }
  UpdatesFn->>PG: SELECT channel WHERE id=? (include electron column)
  PG-->>UpdatesFn: channelData (electron: false | true)
  alt channel.electron == false
    UpdatesFn->>Stats: record "disablePlatformElectron"
    UpdatesFn->>Client: 200 { error: "Electron updates disabled", version, previous_version_name }
  else
    UpdatesFn->>PG: insert build/update row / proceed normal flow
    UpdatesFn->>Client: 200 { success }
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hopped through schemas, keys in tow,

Planted Electron names in every locale row,
Channels, seeds, and tests now dance in tune,
Metrics hum a new, bright moon,
A little bunny cheer — hop, code, go!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add electron platform support' clearly and concisely describes the main change in the PR, which is adding full Electron platform support across the codebase.
Description check ✅ Passed The PR description includes a comprehensive summary of the changes, a detailed test plan with specific testing steps, and a checklist confirming that all required tasks are completed.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@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: 0c81b9f8ae

ℹ️ 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 on lines +229 to +239
if (!channelData.channels.electron && platform === 'electron') {
cloudlog({ requestId: c.get('requestId'), message: 'Cannot update, electron is disabled', id: device_id, date: new Date().toISOString() })
await sendStatsAndDevice(c, device, [{ action: 'disablePlatformElectron', versionName: version.name }])
return simpleError200(c, 'disabled_platform_electron', 'Cannot update, electron is disabled', {
version: version.name,

Choose a reason for hiding this comment

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

P1 Badge Ensure electron flag is loaded before blocking updates

The new check !channelData.channels.electron will always evaluate to true because channelData comes from requestInfosPostgres/getSchemaUpdatesAlias in pg.ts, which only selects ios and android flags (no electron). As a result, every /updates request with platform=electron returns disabled_platform_electron even when the channel allows Electron. Populate electron in the channel select (and schema) or derive the platform flag directly so Electron devices can actually update.

Useful? React with 👍 / 👎.

Copy link
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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
supabase/functions/_backend/plugins/channel_self.ts (1)

571-573: Invert condition to properly close PG clients in PUT and GET handlers

The finally blocks in PUT (lines 572–573) and GET (lines 616–617) handlers only call closeClient when pgClient is falsy:

if (!pgClient)
  await closeClient(c, pgClient)

This prevents closure of actual clients, causing resource leaks. The POST and DELETE handlers demonstrate the correct pattern with unconditional await closeClient(c, pgClient). Fix by inverting the condition:

🔧 Proposed fix
PUT handler:
   finally {
-    if (!pgClient)
-      await closeClient(c, pgClient)
+    if (pgClient)
+      await closeClient(c, pgClient)

GET handler:
   finally {
-    if (!pgClient)
-      await closeClient(c, pgClient)
+    if (pgClient)
+      await closeClient(c, pgClient)
supabase/functions/_backend/utils/pg.ts (1)

698-731: Add electron column definition to channels table schema in postgres_schema.ts.

The Drizzle ORM schema definition in postgres_schema.ts is missing the electron boolean column on the channels table. The database migration (20260108000000_add_electron_platform.sql) adds the column to the database, but TypeScript type definitions are not updated. This causes the code in pg.ts to reference schema.channels.electron which doesn't exist, resulting in compilation failures.

Additionally, the channelSelect object in getSchemaUpdatesAlias() is missing the electron field, which should be added for consistency with the other platform columns.

Required changes

In postgres_schema.ts, add to the channels table definition (alongside ios and android):

electron: boolean('electron').notNull().default(true),

In the getSchemaUpdatesAlias() function in pg.ts, add to the channelSelect object:

electron: channelAlias.electron,
🤖 Fix all issues with AI agents
In @supabase/functions/_backend/plugins/channel_self.ts:
- Line 25: The devicePlatformScheme is wrong: replace
z.literal(['ios','android','electron']) with
z.enum(['ios','android','electron']) so individual platform strings validate
correctly; update the inline channel typing objects (the channel shape declared
inline where channels are indexed by platform) to include electron: boolean
alongside ios and android so indexing with 'electron' is typed; and fix the PG
client close logic in the PUT and GET handlers by changing the guard from if
(!pgClient) to if (pgClient) so pgClient.end() runs only when the client exists.

In @supabase/seed.sql:
- Around line 537-542: The seed data is inconsistent: the "no_access" channel
(id 2 / name 'no_access') is inserted with electron='t' in reset_and_seed_data
but electron=false in reset_and_seed_app_data, which breaks tests expecting it
to be excluded on Electron; update the INSERT tuple for the 'no_access' row in
reset_and_seed_data (the row with id 2 / name 'no_access') to set electron to
false (align with reset_and_seed_app_data) so tests like the Expect
not.toContain('no_access') for Electron pass consistently.
🧹 Nitpick comments (2)
messages/vi.json (1)

77-77: Consider reordering Electron keys for consistency.

The new Electron platform translation keys are currently placed after the iOS keys, but alphabetically "electron" comes before "ios". For consistency with the other locale files (ja.json, pt-br.json) and to maintain alphabetical ordering, consider moving these entries before their corresponding iOS entries:

  • Line 77 action-disable-platform-electron should be placed before line 76 (ios)
  • Line 416 channel-platform-electron should be placed before line 415 (ios)
  • Line 1119 platform-electron should be placed before line 1118 (ios)

The translation content itself is correct and follows the established Vietnamese language patterns.

Also applies to: 416-416, 1119-1119

tests/updates.test.ts (1)

333-341: Electron platform validity test is correct, consider a slightly stronger assertion

This test does its job of guarding against 400 invalid_json_body when platform = 'electron'. If you want a bit more confidence, you could also assert on the response body (e.g. json.error !== 'invalid_json_body' or an explicit 200), but that’s optional.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bf74d8 and 0c81b9f.

📒 Files selected for processing (28)
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/hi.json
  • messages/id.json
  • messages/it.json
  • messages/ja.json
  • messages/ko.json
  • messages/pl.json
  • messages/pt-br.json
  • messages/ru.json
  • messages/tr.json
  • messages/vi.json
  • messages/zh-cn.json
  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
  • tests/channel_self.test.ts
  • tests/updates.test.ts
🧰 Additional context used
📓 Path-based instructions (20)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use single quotes and no semicolons per @antfu/eslint-config

Files:

  • tests/updates.test.ts
  • src/components/dashboard/AppSetting.vue
  • tests/channel_self.test.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • src/components/dashboard/DeploymentBanner.vue
  • supabase/functions/_backend/utils/cloudflare.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
tests/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Backend tests should be located in the tests/ directory and use Vitest test runner

Files:

  • tests/updates.test.ts
  • tests/channel_self.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode with path aliases mapping ~/ to src/

Files:

  • tests/updates.test.ts
  • tests/channel_self.test.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
tests/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend tests must use helpers from tests/test-utils.ts including getEndpointUrl(path) for correct worker routing and USE_CLOUDFLARE_WORKERS=true for CF Workers testing

Files:

  • tests/updates.test.ts
  • tests/channel_self.test.ts
**/{tests,__tests__,test,spec}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows.

Files:

  • tests/updates.test.ts
  • tests/channel_self.test.ts
supabase/migrations/**/*.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Database migrations must be created with supabase migration new <feature_slug> and never modify previously committed migrations

supabase/migrations/**/*.sql: When a feature requires schema changes, create a single migration file with the Supabase CLI (supabase migration new <feature_slug>) and keep editing that file until the feature ships; never edit previously committed migrations.
A migration that introduces a new table may include seed inserts for that table, but treat that seeding as part of the current feature and do not modify previously committed migrations.
Do not create new cron jobs; instead update the process_all_cron_tasks function in a new migration file to add your job if needed.

Files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
src/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.vue: Use Vue 3 with Composition API and <script setup> syntax for frontend components
Style components using TailwindCSS with DaisyUI components

src/**/*.vue: Use Vue 3 <script setup> syntax exclusively for all Vue component scripts
Use Tailwind utility classes for layout and spacing in Vue components
Use DaisyUI components (d-btn, d-input, d-card) for interactive elements in Vue components
Use Konsta components ONLY for safe area helpers (top/bottom insets) in Vue components; avoid other uses
Use useRoute() from vue-router to access route parameters and useRouter() for programmatic navigation in Vue components

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

Reusable Vue components should be organized in src/components/ directory

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
{capacitor.config.{ts,js},src/**/*.{ts,tsx,vue}}

📄 CodeRabbit inference engine (CLAUDE.md)

Mobile apps should use Capacitor with app ID ee.forgr.capacitor_go for native mobile functionality

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
src/**/*.{ts,tsx,vue,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ~/ alias for imports from src/ directory in frontend TypeScript and Vue components

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
src/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Frontend ESLint must pass before commit; run bun lint:fix to auto-fix issues in frontend files

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
**/{src,app}/{components,views,pages}/**/*.{vue,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

The web client is built with Vue.js and Tailwind CSS; lean on utility classes and composition-friendly patterns rather than bespoke CSS.

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
**/{src,app}/{components,views,pages}/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Use DaisyUI (d- prefixed classes) for buttons, inputs, and other interactive primitives to keep behavior and spacing consistent.

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
**/{src,app}/**/*.{vue,ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Konsta components are reserved for the safe area helpers. Avoid importing konsta anywhere else in the app.

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
**/{src,app}/**/*.{css,scss,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Capgo's design uses deep slate bases with the 'Extract' azure highlight (--color-azure-500: #119eff) and soft radii; mirror the palette from src/styles/style.css (e.g., --color-primary-500: #515271) when introducing new UI.

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
supabase/functions/_backend/**

📄 CodeRabbit inference engine (CLAUDE.md)

Backend logic should be organized in supabase/functions/_backend/ with subdirectories for plugins, private endpoints, public endpoints, triggers, and utilities

Files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Supabase Edge Functions use Deno runtime

Files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/seed.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Seed database with supabase db reset to apply all migrations and test data from supabase/seed.sql

Updating supabase/seed.sql to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Files:

  • supabase/seed.sql
🧠 Learnings (22)
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to **/{tests,__tests__,test,spec}/**/*.{ts,tsx,js} : Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows.

Applied to files:

  • tests/updates.test.ts
  • src/types/supabase.types.ts
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/migrations/**/*.sql : A migration that introduces a new table may include seed inserts for that table, but treat that seeding as part of the current feature and do not modify previously committed migrations.

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/seed.sql : Updating `supabase/seed.sql` to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/migrations/**/*.sql : Do not create new cron jobs; instead update the `process_all_cron_tasks` function in a new migration file to add your job if needed.

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/migrations/**/*.sql : When a feature requires schema changes, create a single migration file with the Supabase CLI (`supabase migration new <feature_slug>`) and keep editing that file until the feature ships; never edit previously committed migrations.

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/migrations/**/*.sql : Database migrations must be created with `supabase migration new <feature_slug>` and never modify previously committed migrations

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
📚 Learning: 2025-12-25T11:22:13.039Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:13.039Z
Learning: In SQL migrations under the repository (e.g., supabase/migrations), enforce that when an org has enforcing_2fa=true, all users (including super_admins) must have 2FA enabled before accessing any org functions, including check_org_members_2fa_enabled. Do not grant admin exceptions to 2FA requirements. This ensures consistent security enforcement across all org-related operations; implement this rule within relevant migrations and associated stored procedures/tests.

Applied to files:

  • supabase/migrations/20260108000000_add_electron_platform.sql
📚 Learning: 2025-05-29T18:21:17.703Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1107
File: src/components/dashboard/AppSetting.vue:85-182
Timestamp: 2025-05-29T18:21:17.703Z
Learning: In setUpdateChannelSync function in src/components/dashboard/AppSetting.vue, the database update code at the end is intentionally outside the conflict-resolution if block and should run for cases where sync is being toggled without conflicts or after conflicts are resolved. The return statements inside the dialog handling correctly prevent database updates when the user cancels.

Applied to files:

  • src/components/dashboard/AppSetting.vue
📚 Learning: 2025-12-23T01:19:04.593Z
Learnt from: riderx
Repo: Cap-go/capgo PR: 1297
File: src/components/dashboard/DeploymentBanner.vue:77-79
Timestamp: 2025-12-23T01:19:04.593Z
Learning: In the Cap-go codebase, ensure that app permission checks never include the role 'owner'. App-level permissions should be based on the user_min_right enum with values: read, upload, write, admin, super_admin (and NOT owner). This pattern applies across Vue components that perform permission checks; if you find a check referencing 'owner' for app-level access, replace it with the appropriate user_min_right value and keep organization-level owner handling in organization.ts.

Applied to files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to playwright/e2e/**/*.{ts,js} : Cover customer-facing flows with the Playwright MCP suite. Add scenarios under `playwright/e2e` and run them locally with `bun run test:front` before shipping UI changes.

Applied to files:

  • tests/channel_self.test.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/functions/_backend/plugins/updates.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Use shared backend code from `supabase/functions/_backend/` across all deployment platforms; never create platform-specific implementations outside this directory

Applied to files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/**/*.{ts,js} : Backend ESLint must pass before commit; run `bun lint:backend` for backend files

Applied to files:

  • supabase/functions/_backend/utils/update.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to cloudflare_workers/plugin/index.ts : Plugin Worker (port 8788) routes: `/updates`, `/channel_self`, `/stats`

Applied to files:

  • supabase/functions/_backend/plugins/channel_self.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to cloudflare_workers/api/index.ts : API Worker (port 8787) routes: `/bundle`, `/app`, `/device`, `/channel`, `/private/*`, `/triggers`

Applied to files:

  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use structured logging with `cloudlog({ requestId: c.get('requestId'), message: '...' })` for all backend logging

Applied to files:

  • supabase/functions/_backend/utils/cloudflare.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/seed.sql : Seed database with `supabase db reset` to apply all migrations and test data from `supabase/seed.sql`

Applied to files:

  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Run `bun types` after schema changes to regenerate TypeScript types from Supabase

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-05T17:34:25.556Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T17:34:25.556Z
Learning: Applies to supabase/functions/**/*.ts : Supabase Edge Functions use Deno runtime

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
🧬 Code graph analysis (5)
tests/updates.test.ts (1)
tests/test-utils.ts (2)
  • getBaseData (210-212)
  • postUpdate (469-476)
tests/channel_self.test.ts (1)
tests/test-utils.ts (2)
  • resetAndSeedAppData (225-287)
  • getBaseData (210-212)
supabase/functions/_backend/utils/update.ts (3)
supabase/functions/_backend/utils/logging.ts (1)
  • cloudlog (3-15)
supabase/functions/_backend/utils/stats.ts (1)
  • sendStatsAndDevice (86-96)
supabase/functions/_backend/utils/hono.ts (1)
  • simpleError200 (213-222)
supabase/functions/_backend/plugins/channel_self.ts (2)
supabase/functions/_backend/utils/postgres_schema.ts (1)
  • channels (63-82)
supabase/functions/_backend/utils/pg.ts (1)
  • getCompatibleChannelsPg (695-739)
src/types/supabase.types.ts (1)
supabase/functions/_backend/utils/supabase.types.ts (1)
  • Json (1-7)
🪛 GitHub Actions: Run tests
supabase/functions/_backend/utils/update.ts

[error] 229-229: TS2339: Property 'electron' does not exist on type '{ id: number; name: string; app_id: string; allow_dev: boolean; allow_prod: boolean; allow_emulator: boolean; allow_device: boolean; disable_auto_update_under_native: boolean; disable_auto_update: "none" | ... 3 more ... | "version_number"; ios: boolean; android: boolean; allow_device_self_set: boolean; public: bool...'.

supabase/functions/_backend/plugins/channel_self.ts

[error] 208-208: TS7053: Element implicitly has an 'any' type because expression of type '"ios" | "android" | "electron"' can't be used to index type '{ name: string; ios: boolean; android: boolean; }'. Property 'electron' does not exist on type '{ name: string; ios: boolean; android: boolean; }'.


[error] 366-366: TS7053: Element implicitly has an 'any' type because expression of type '"ios" | "android" | "electron"' can't be used to index type '{ ios: boolean; android: boolean; }'. Property 'electron' does not exist on type '{ ios: boolean; android: boolean; }'.

supabase/functions/_backend/utils/pg.ts

[error] 319-319: TS2339: Property 'electron' does not exist on type 'PgTableWithColumns<Required<Update<{ name: "channels"; schema: undefined; columns: { id: PgColumn<{ name: "id"; tableName: "channels"; dataType: "number"; columnType: "PgBigInt53"; data: number; driverParam: string | number; notNull: true; ... 7 more ...; generated: undefined; }, {}, {}>; ... 16 more ...; allow_prod...'.


[error] 710-710: TS2339: Property 'electron' does not exist on type 'PgTableWithColumns<{ name: "channels"; schema: undefined; columns: { id: PgColumn<{ name: "id"; tableName: "channels"; dataType: "number"; columnType: "PgBigInt53"; data: number; driverParam: string | number; notNull: true; ... 7 more ...; generated: undefined; }, {}, {}>; ... 16 more ...; allow_prod: PgColumn<...>;...'.


[error] 722-722: TS2339: Property 'electron' does not exist on type 'PgTableWithColumns<{ name: "channels"; schema: undefined; columns: { id: PgColumn<{ name: "id"; tableName: "channels"; dataType: "number"; columnType: "PgBigInt53"; data: number; driverParam: string | number; notNull: true; ... 7 more ...; generated: undefined; }, {}, {}>; ... 16 more ...; allow_prod: PgColumn<...>;...'.

🔇 Additional comments (37)
messages/it.json (1)

76-76: LGTM! Electron platform translations are consistent and correct.

The three new Italian translation keys for Electron platform support mirror the existing Android and iOS patterns perfectly:

  • Line 76: Action message follows the "Bloccato - Piattaforma X disabilitata" structure with correct feminine agreement
  • Line 415: Channel platform label follows the "Solo X" pattern
  • Line 1118: Simple platform name (proper noun, correctly untranslated)

The translations are grammatically correct and maintain consistency with the existing codebase.

Also applies to: 415-415, 1118-1118

supabase/functions/_backend/plugins/updates.ts (1)

31-56: Electron platform added correctly to request validation

Extending platform to accept 'electron' matches the existing pattern and keeps error handling intact. No additional issues spotted in this schema block.

messages/ru.json (1)

75-78: Electron RU translations consistent with existing platform strings

The new Russian entries for disabling Electron, Electron-only channels, and the Electron platform label are grammatically correct and align with the existing Android/iOS counterparts. JSON structure and commas are also valid.

Also applies to: 413-417, 1117-1120

messages/zh-cn.json (1)

75-78: Electron zh-CN translations align with Android/iOS phrasing

The added zh-CN strings for Electron platform disabling, Electron-only channels, and the platform label follow the same structure and tone as the Android/iOS entries, with correct JSON formatting.

Also applies to: 413-417, 1117-1120

messages/es.json (1)

75-78: Electron ES translations are consistent and correctly wired

The Spanish messages for blocking the Electron platform, Electron-only channels, and the Electron platform label are consistent with the Android/iOS variants and fit the existing wording style. JSON syntax is correct.

Also applies to: 413-417, 1117-1119

messages/de.json (3)

76-76: Electron disable-action translation matches existing platform variants

Text and structure align with the Android/iOS equivalents; JSON remains valid.


414-414: Electron channel label consistent with Android/iOS channel labels

“Nur Electron” mirrors “Nur Android” / “Nur iOS” and fits the UI usage.


1118-1118: Platform label for Electron is coherent with other platforms

Uses the same pattern as platform-android / platform-ios and is appropriate as a product name.

messages/pl.json (3)

77-77: Polish disable-action string for Electron is consistent

Matches the pattern and tone of Android/iOS disable-platform messages.


416-416: Electron-only channel label is aligned with existing Polish labels

“Tylko Electron” is parallel to “Tylko Android” / “Tylko dla iOS” and reads naturally.


1119-1119: Platform name entry for Electron is correct and consistent

Reuses the product name as done for Android/iOS; no issues.

messages/fr.json (3)

76-76: French disable-action text for Electron matches Android/iOS patterns

Sentence structure and terminology are consistent with the other platforms.


415-415: Electron-only channel label is well aligned with French UI copy

“Uniquement Electron” mirrors “Uniquement Android” / “Uniquement sur iOS” appropriately.


1118-1118: Electron platform label integrates cleanly with existing platform list

Uses the same style as platform-android / platform-ios; no localization or syntax issues.

messages/ja.json (1)

76-76: LGTM! Electron platform translations added correctly.

The three new Electron platform translation keys have been added with proper alphabetical ordering and consistent formatting that matches the existing Android and iOS platform translations. The Japanese translations follow the established pattern and terminology.

Also applies to: 415-415, 1118-1118

messages/pt-br.json (1)

76-76: LGTM! Electron platform translations added correctly.

The three new Electron platform translation keys have been added with proper alphabetical ordering and consistent formatting that matches the existing Android and iOS platform translations. The Portuguese (Brazilian) translations follow the established pattern and terminology.

Also applies to: 415-415, 1118-1118

messages/vi.json (1)

77-77: Translations are accurate and consistent.

The Vietnamese translations for the Electron platform follow the same pattern and terminology as the existing Android and iOS platform translations, maintaining consistency across the file.

Also applies to: 416-416, 1119-1119

messages/hi.json (1)

75-77: Electron Hindi translations are consistent and correctly keyed

The new Electron-related keys mirror the existing Android/iOS patterns and use appropriate Hindi phrasing; no issues from a code/structure perspective.

Also applies to: 413-416, 1117-1119

src/components/dashboard/AppSetting.vue (1)

34-34: Channel model and query correctly extended with electron

Extending the local channels type and SELECT to include the electron flag keeps this component in sync with the updated schema and other platform flags without affecting existing iOS/Android logic.

Also applies to: 235-248

messages/ko.json (1)

75-77: Electron Korean translations are consistent with existing platform keys

The new Electron-related keys are correctly named, localized, and aligned with the Android/iOS counterparts; no issues from a code perspective.

Also applies to: 413-416, 1117-1119

messages/id.json (1)

76-78: Electron translations are consistent with existing platform keys

The new Indonesian strings for action-disable-platform-electron, channel-platform-electron, and platform-electron follow the same naming, tone, and placement as the Android/iOS entries. No issues from a structure or keying perspective.

Also applies to: 413-417, 1117-1119

messages/en.json (1)

79-81: Electron strings align with existing platform wording

The added English entries for action-disable-platform-electron, channel-platform-electron, and platform-electron are consistent with the Android/iOS variants and the backend action/error naming. No structural or phrasing issues.

Also applies to: 446-450, 1044-1048

messages/tr.json (1)

75-79: Turkish Electron translations look correct and consistent

The Turkish strings for action-disable-platform-electron, channel-platform-electron, and platform-electron follow the same pattern as the Android/iOS entries and read naturally. No key, placement, or consistency problems.

Also applies to: 413-417, 1117-1120

supabase/functions/_backend/utils/update.ts (1)

229-236: I don't have a review comment to rewrite. Please provide:

  1. The original review comment (within <review_comment> tags)
  2. Any relevant code context
  3. Any capability results if verification has already been performed

Once you provide these, I will output the rewritten comment in the required format.

tests/channel_self.test.ts (2)

416-438: LGTM! Good extension of existing platform compatibility test.

The Electron test block follows the established pattern for iOS and Android, with clear comments documenting the expected channel configurations. The assertions correctly verify that electron_only, beta, and production channels are returned while development and no_access are excluded based on their electron flag.


440-465: LGTM! Dedicated Electron channel compatibility test.

This test provides focused coverage for Electron platform behavior, complementing the multi-platform test above. The expected channel configuration is well-documented in the comments.

supabase/migrations/20260108000000_add_electron_platform.sql (1)

9-10: Verify that DEFAULT true is the intended behavior for existing channels.

Setting DEFAULT true means all existing channels will automatically support Electron platform. This could be intentional (Electron apps get updates from existing channels by default) or unintentional (existing channels weren't designed for Electron and should opt-in).

Confirm this aligns with the product requirements. If existing channels should not automatically support Electron, consider using DEFAULT false instead.

supabase/seed.sql (1)

856-866: LGTM! Channel configurations in reset_and_seed_app_data are correct.

The electron flags align with test expectations:

  • production: electron=true (included for Electron)
  • beta: electron=true (included for Electron)
  • development: electron=false (excluded for Electron)
  • no_access: electron=false (excluded for Electron)
  • electron_only: electron=true, ios=false, android=false (Electron-exclusive)
src/components/dashboard/DeploymentBanner.vue (3)

69-72: LGTM! Type definition correctly extended for Electron.

The DefaultChannel type now includes electron in the Pick selection, ensuring type safety for the new platform field.


104-116: LGTM! Platform filtering and target generation correctly includes Electron.

The channel filter and platform mapping logic correctly handle Electron alongside iOS and Android.


308-317: LGTM! Platform label generation updated for Electron.

The getPlatformLabel function now handles the electron platform with proper i18n support.

supabase/functions/_backend/utils/cloudflare.ts (4)

191-193: LGTM! Platform encoding extended for Electron.

The platform value mapping is clear and consistent:

  • 0 = Android (default)
  • 1 = iOS
  • 2 = Electron

This is documented in the comment and correctly applied in both write and read operations.


586-586: LGTM! Platform decoding correctly handles Electron.

The mapping is consistent with the encoding in trackDevicesCF, ensuring data integrity when reading device information from Analytics Engine.


1146-1158: LGTM! Admin platform overview interface extended for Electron.

The AdminPlatformOverview interface now includes electron_devices alongside the existing android_devices and ios_devices fields.


1376-1406: LGTM! Platform overview query and aggregation includes Electron devices.

The query correctly counts devices with double1 = 2 as Electron devices, and the result is properly propagated through the function.

src/types/supabase.types.ts (1)

10-34: Auto-generated types correctly reflect Electron platform support.

The type definitions are properly regenerated to include:

  • electron: boolean field in channels table (Row/Insert/Update)
  • "electron" value in platform_os enum
  • "disablePlatformElectron" in stats_action enum
  • Updated Constants to match

Based on learnings, ensure bun types was run after the schema migration to generate these types.

Also applies to: 631-631, 652-652, 673-673, 3066-3066, 3130-3130, 3323-3323, 3387-3387

supabase/functions/_backend/utils/supabase.types.ts (1)

10-34: Backend types are in sync with frontend types.

The backend type definitions mirror the frontend types exactly, which is correct for auto-generated Supabase types. The Electron platform support is properly reflected in:

  • Channels table with electron boolean field
  • platform_os enum including "electron"
  • stats_action enum with "disablePlatformElectron"

This ensures type safety across both frontend and backend code when working with Electron channels.

Also applies to: 631-631, 652-652, 673-673, 3066-3066, 3130-3130, 3323-3323, 3387-3387

Copy link
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: 0

🧹 Nitpick comments (3)
supabase/functions/_backend/utils/pg.ts (2)

320-320: Consider refactoring the platform mapping for maintainability.

The nested ternary correctly handles all three platforms but could be more readable as an object lookup or switch statement, especially if more platforms are added in the future.

♻️ Optional refactor for improved readability
- const platformQuery = platform === 'android' ? channelAlias.android : platform === 'electron' ? channelAlias.electron : channelAlias.ios
+ const platformMap = {
+   android: channelAlias.android,
+   electron: channelAlias.electron,
+   ios: channelAlias.ios,
+ } as const
+ const platformQuery = platformMap[platform as keyof typeof platformMap] ?? channelAlias.ios

711-711: Platform column mapping works correctly but could be more maintainable.

Similar to Line 320, this nested ternary correctly handles platform mapping but checks platforms in a different order (ios→electron→android vs android→electron→ios). While functionally correct due to the typed union parameter, consistent ordering and a refactored approach would improve maintainability.

♻️ Optional refactor for consistency
- const platformColumn = platform === 'ios' ? schema.channels.ios : platform === 'electron' ? schema.channels.electron : schema.channels.android
+ const platformColumnMap = {
+   ios: schema.channels.ios,
+   android: schema.channels.android,
+   electron: schema.channels.electron,
+ } as const
+ const platformColumn = platformColumnMap[platform]

Note: Since platform is strongly typed as the union 'ios' | 'android' | 'electron', no fallback is needed.

supabase/functions/_backend/utils/postgres_schema.ts (1)

75-77: Consider standardizing the method call order for consistency.

The ios column uses .default(true).notNull() while android and electron use .notNull().default(true). While both orderings work correctly in Drizzle ORM, standardizing the order improves code consistency and maintainability.

♻️ Proposed fix to standardize the ordering
-  ios: boolean('ios').default(true).notNull(),
-  android: boolean('android').notNull().default(true),
-  electron: boolean('electron').notNull().default(true),
+  ios: boolean('ios').notNull().default(true),
+  android: boolean('android').notNull().default(true),
+  electron: boolean('electron').notNull().default(true),
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c81b9f and 430c990.

📒 Files selected for processing (4)
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/seed.sql
🚧 Files skipped from review as they are similar to previous changes (1)
  • supabase/functions/_backend/plugins/channel_self.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use single quotes and no semicolons per @antfu/eslint-config

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
supabase/functions/_backend/**

📄 CodeRabbit inference engine (CLAUDE.md)

Backend logic should be organized in supabase/functions/_backend/ with subdirectories for plugins, private endpoints, public endpoints, triggers, and utilities

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode with path aliases mapping ~/ to src/

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Supabase Edge Functions use Deno runtime

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
supabase/seed.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Seed database with supabase db reset to apply all migrations and test data from supabase/seed.sql

Updating supabase/seed.sql to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Files:

  • supabase/seed.sql
🧠 Learnings (8)
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/migrations/**/*.sql : A migration that introduces a new table may include seed inserts for that table, but treat that seeding as part of the current feature and do not modify previously committed migrations.

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/seed.sql
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/seed.sql : Updating `supabase/seed.sql` to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Use shared backend code from `supabase/functions/_backend/` across all deployment platforms; never create platform-specific implementations outside this directory

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/seed.sql : Seed database with `supabase db reset` to apply all migrations and test data from `supabase/seed.sql`

Applied to files:

  • supabase/seed.sql
🔇 Additional comments (8)
supabase/seed.sql (4)

537-542: LGTM! Comprehensive electron platform seeding.

The channel inserts properly seed the electron column across diverse platform combinations, including an electron-only channel for isolated testing. The seed data aligns well with the test plan objectives.


556-557: Verify the electron plugin_version selection.

The electron test device uses plugin_version='7.0.0' while other test devices use '4.15.3'. Please confirm this version jump is intentional and aligns with Electron plugin requirements.


563-563: Sequence correctly updated for new channel.

The channel_id_seq increment appropriately accounts for the new electron_only channel.


755-866: LGTM! Function properly extended for electron support.

The reset_and_seed_app_data function correctly adds electron column handling while maintaining backward compatibility. The channel platform combinations align with the main seed data.

supabase/functions/_backend/utils/pg.ts (3)

260-260: LGTM! Electron field properly added to channel selection.

The electron column is correctly integrated into the channelSelect object, maintaining consistency with the existing ios/android pattern.


699-703: Excellent type safety for electron platform support.

The function signature correctly constrains the platform parameter to the union type and extends the return type to include the electron boolean. This provides strong compile-time guarantees.


723-732: Query correctly includes electron column in SELECT and WHERE clauses.

The electron field is properly selected and the WHERE clause correctly uses the platformColumn variable to filter by the appropriate platform boolean.

supabase/functions/_backend/utils/postgres_schema.ts (1)

77-77: The GET and POST endpoints must be updated to handle the new electron column.

The schema change is correct, but the channel endpoints have gaps:

  1. GET endpoint (public/channel/get.ts): The getAll() and getOne() functions are missing ios, android, and electron in their SELECT column lists. These fields should be included in the queries on lines 25–35 and 50–60.

  2. POST endpoint (public/channel/post.ts): The ChannelSet interface (line 11–23) is missing electron?: boolean, and the channel object construction (line 67–71) doesn't include the electron field spread like it does for ios and android. Add electron as an optional field and include ...(body.electron == null ? {} : { electron: body.electron }) in the object.

  3. Trigger (triggers/on_channel_update.ts): Review whether the electron field should be included in the public channel uniqueness logic (lines 22–64). Currently, the logic only considers ios and android combinations.

⛔ Skipped due to learnings
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to **/{tests,__tests__,test,spec}/**/*.{ts,tsx,js} : Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows.
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/seed.sql : Updating `supabase/seed.sql` to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Copy link
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/functions/_backend/utils/pg.ts (1)

701-734: Implementation correct; however, add Postgres-level unit tests.

The electron platform support is properly implemented with type-safe parameters, complete field mappings, and comprehensive end-to-end tests in channel_self.test.ts (lines 417-437, 440-465). All callers correctly pass the platform parameter, and the schema includes the electron field.

However, per project guidelines, database changes must be covered with both Postgres-level unit tests and end-to-end tests. Currently only E2E tests exist. Add a dedicated test file (e.g., tests/pg.test.ts) with direct unit tests for getCompatibleChannelsPg covering the electron platform branch logic.

🧹 Nitpick comments (1)
supabase/functions/_backend/utils/pg.ts (1)

320-320: Consider refactoring for consistency with getCompatibleChannelsPg pattern.

The nested ternary logic is correct but could be refactored to use an extracted variable pattern like line 713 for improved readability and consistency:

+  const platformColumn = platform === 'android' ? channelAlias.android : platform === 'electron' ? channelAlias.electron : channelAlias.ios
-  const platformQuery = platform === 'android' ? channelAlias.android : platform === 'electron' ? channelAlias.electron : channelAlias.ios

Additionally, consider typing the platform parameter (line 312) as 'ios' | 'android' | 'electron' instead of string for better type safety, similar to getCompatibleChannelsPg.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 430c990 and b32930b.

📒 Files selected for processing (1)
  • supabase/functions/_backend/utils/pg.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use single quotes and no semicolons per @antfu/eslint-config

Files:

  • supabase/functions/_backend/utils/pg.ts
supabase/functions/_backend/**

📄 CodeRabbit inference engine (CLAUDE.md)

Backend logic should be organized in supabase/functions/_backend/ with subdirectories for plugins, private endpoints, public endpoints, triggers, and utilities

Files:

  • supabase/functions/_backend/utils/pg.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode with path aliases mapping ~/ to src/

Files:

  • supabase/functions/_backend/utils/pg.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Supabase Edge Functions use Deno runtime

Files:

  • supabase/functions/_backend/utils/pg.ts
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/utils/pg.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/utils/pg.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to **/{tests,__tests__,test,spec}/**/*.{ts,tsx,js} : Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows.
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to playwright/e2e/**/*.{ts,js} : Cover customer-facing flows with the Playwright MCP suite. Add scenarios under `playwright/e2e` and run them locally with `bun run test:front` before shipping UI changes.
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
🧬 Code graph analysis (1)
supabase/functions/_backend/utils/pg.ts (1)
supabase/functions/_backend/utils/postgres_schema.ts (1)
  • channels (63-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (3)
supabase/functions/_backend/utils/pg.ts (3)

260-260: LGTM! Electron field added to channel selection.

The addition of the electron field to channelSelect is consistent with the ios and android fields and aligns with the database schema.


564-571: LGTM! getMainChannelsPg properly extended for Electron support.

Both the return type signature and the query selection have been correctly updated to include the electron field.


641-658: LGTM! getChannelsPg properly extended for Electron support.

The function signature and query have been correctly updated to include the electron field in both the return type and the select statement.

@riderx riderx force-pushed the riderx/add-electron-platform branch 2 times, most recently from 14c9040 to 8b4e954 Compare January 9, 2026 17:42
Copy link
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/components/dashboard/DeploymentBanner.vue (2)

95-97: Keep docs consistent with the actual permission check (no app-level “owner”).
hasAdminPermission correctly uses admin/super_admin only; please update the header comment that claims “owner” visibility to avoid reintroducing that pattern later. (Based on learnings, app-level checks should not use owner.)


467-542: Add e2e test for Electron platform in deployment banner and deploy dialog flow.

The DeploymentBanner component supports the Electron platform and provides a customer-facing deployment workflow for admins. Per the Playwright MCP guidelines, this flow requires e2e coverage. Add a scenario under playwright/e2e/ that covers the banner appearance with Electron-enabled channels and the deploy dialog interaction, then run bun run test:front before shipping.

supabase/functions/_backend/utils/cloudflare.ts (1)

1190-1202: Verify and fix platform aggregation inconsistency: readLastMonthDevicesByPlatformCF silently drops electron devices.

While AdminPlatformOverview correctly includes electron in its platform breakdown, readLastMonthDevicesByPlatformCF (used in logsnag_insights.ts) only counts android and ios—the query omits WHEN double1 = 2 for electron, and the DevicesByPlatform interface lacks an electron field. The total count includes electron devices, but the platform-specific breakdown loses track of them.

Update:

  1. Add electron: number to DevicesByPlatform interface
  2. Add electron case to the query: COUNT(DISTINCT CASE WHEN double1 = 2 THEN blob1 END) AS electron
  3. Include electron in the return object
  4. Update the comment to reflect: "Platform: double1 = 0 for android, 1 for ios, 2 for electron"
🧹 Nitpick comments (3)
src/components/dashboard/DeploymentBanner.vue (2)

172-180: Supabase channel query updated for Electron—consider handling query errors explicitly.
Right now publicChannels errors will silently hide the banner; at least log/toast on error (even if you keep the “banner disappears on failure” behavior).


308-317: Avoid hard-coded ' & ' joining; make platform labels locale-aware.
For 3+ platforms this also becomes awkward. Prefer Intl.ListFormat (with the current locale) or an i18n-driven separator/list pattern.

supabase/functions/_backend/utils/pg.ts (1)

432-474: Add platform filter to defaultChannel branch for fail-fast validation.

The concern is valid: when defaultChannel is specified, the query omits the platform filter, allowing a channel with electron = false (for example) to be returned for an electron client. While downstream validation at lines 218–235 of update.ts catches platform mismatches and returns explicit errors (e.g., disabled_platform_electron), filtering at query time is more defensive and efficient.

Proposed change (enforce platform match for defaultChannel lookups)
   const channelQuery = (includeManifest
     ? baseQuery.leftJoin(schema.manifest, eq(schema.manifest.app_version_id, versionAlias.id))
     : baseQuery)
     .where(!defaultChannel
       ? and(
           eq(channelAlias.public, true),
           eq(channelAlias.app_id, app_id),
           eq(platformQuery, true),
         )
       : and(
           eq(channelAlias.app_id, app_id),
           eq(channelAlias.name, defaultChannel),
+          eq(platformQuery, true),
         ),
     )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b32930b and 8b4e954.

📒 Files selected for processing (29)
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/hi.json
  • messages/id.json
  • messages/it.json
  • messages/ja.json
  • messages/ko.json
  • messages/pl.json
  • messages/pt-br.json
  • messages/ru.json
  • messages/tr.json
  • messages/vi.json
  • messages/zh-cn.json
  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
  • tests/channel_self.test.ts
  • tests/updates.test.ts
🚧 Files skipped from review as they are similar to previous changes (19)
  • src/components/dashboard/AppSetting.vue
  • messages/tr.json
  • messages/it.json
  • messages/vi.json
  • messages/pt-br.json
  • messages/de.json
  • messages/ja.json
  • messages/zh-cn.json
  • supabase/functions/_backend/plugins/updates.ts
  • tests/channel_self.test.ts
  • messages/id.json
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • messages/en.json
  • messages/fr.json
  • messages/hi.json
  • tests/updates.test.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • messages/ru.json
🧰 Additional context used
📓 Path-based instructions (16)
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use Vue 3 <script setup> syntax exclusively for all Vue component scripts
Use Tailwind utility classes for layout and spacing in Vue components
Use DaisyUI components (d-btn, d-input, d-card) for interactive elements in Vue components
Use Konsta components ONLY for safe area helpers (top/bottom insets) in Vue components; avoid other uses
Use useRoute() from vue-router to access route parameters and useRouter() for programmatic navigation in Vue components

src/**/*.vue: Use Vue 3 with Composition API and <script setup> syntax for frontend development
Use TailwindCSS with DaisyUI components for styling

Files:

  • src/components/dashboard/DeploymentBanner.vue
src/**/*.{ts,tsx,vue,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ~/ alias for imports from src/ directory in frontend TypeScript and Vue components

Files:

  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
src/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Frontend ESLint must pass before commit; run bun lint:fix to auto-fix issues in frontend files

Files:

  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
**/{src,app}/{components,views,pages}/**/*.{vue,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

The web client is built with Vue.js and Tailwind CSS; lean on utility classes and composition-friendly patterns rather than bespoke CSS.

Files:

  • src/components/dashboard/DeploymentBanner.vue
**/{src,app}/{components,views,pages}/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Use DaisyUI (d- prefixed classes) for buttons, inputs, and other interactive primitives to keep behavior and spacing consistent.

Files:

  • src/components/dashboard/DeploymentBanner.vue
**/{src,app}/**/*.{vue,ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Konsta components are reserved for the safe area helpers. Avoid importing konsta anywhere else in the app.

Files:

  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
**/{src,app}/**/*.{css,scss,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Capgo's design uses deep slate bases with the 'Extract' azure highlight (--color-azure-500: #119eff) and soft radii; mirror the palette from src/styles/style.css (e.g., --color-primary-500: #515271) when introducing new UI.

Files:

  • src/components/dashboard/DeploymentBanner.vue
**/*.{js,ts,vue,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ESLint with @antfu/eslint-config with single quotes, no semicolons, and Vue 3 Composition API preferred

Files:

  • src/components/dashboard/DeploymentBanner.vue
  • supabase/functions/_backend/utils/postgres_schema.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use path alias ~/ to map to src/ directory for imports in TypeScript/Vue files

Files:

  • src/components/dashboard/DeploymentBanner.vue
  • supabase/functions/_backend/utils/postgres_schema.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
src/components/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

Organize frontend components in src/components/ directory for reusable Vue components

Files:

  • src/components/dashboard/DeploymentBanner.vue
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/_backend/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Core backend logic should be organized in supabase/functions/_backend/ with subdirectories for plugins, private, public, triggers, and utils

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Backend API endpoints use TypeScript in Supabase Edge Functions with Deno runtime

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable TypeScript strict mode

Files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
supabase/seed.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Seed database with supabase db reset to apply all migrations and test data from supabase/seed.sql

Updating supabase/seed.sql to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Files:

  • supabase/seed.sql
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to playwright/e2e/**/*.{ts,js} : Cover customer-facing flows with the Playwright MCP suite. Add scenarios under `playwright/e2e` and run them locally with `bun run test:front` before shipping UI changes.
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to cloudflare_workers/api/index.ts : API Worker (port 8787) routes: `/bundle`, `/app`, `/device`, `/channel`, `/private/*`, `/triggers`

Applied to files:

  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2025-12-23T01:19:04.593Z
Learnt from: riderx
Repo: Cap-go/capgo PR: 1297
File: src/components/dashboard/DeploymentBanner.vue:77-79
Timestamp: 2025-12-23T01:19:04.593Z
Learning: In the Cap-go codebase, ensure that app permission checks never include the role 'owner'. App-level permissions should be based on the user_min_right enum with values: read, upload, write, admin, super_admin (and NOT owner). This pattern applies across Vue components that perform permission checks; if you find a check referencing 'owner' for app-level access, replace it with the appropriate user_min_right value and keep organization-level owner handling in organization.ts.

Applied to files:

  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/migrations/**/*.sql : A migration that introduces a new table may include seed inserts for that table, but treat that seeding as part of the current feature and do not modify previously committed migrations.

Applied to files:

  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-09T16:10:23.878Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T16:10:23.878Z
Learning: Applies to supabase/functions/**/*.ts : Backend API endpoints use TypeScript in Supabase Edge Functions with Deno runtime

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to **/{tests,__tests__,test,spec}/**/*.{ts,tsx,js} : Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows.

Applied to files:

  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-09T16:10:23.878Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T16:10:23.878Z
Learning: Applies to supabase/functions/_backend/**/*.ts : Core backend logic should be organized in `supabase/functions/_backend/` with subdirectories for plugins, private, public, triggers, and utils

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Run `bun types` after schema changes to regenerate TypeScript types from Supabase

Applied to files:

  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use structured logging with `cloudlog({ requestId: c.get('requestId'), message: '...' })` for all backend logging

Applied to files:

  • supabase/functions/_backend/utils/cloudflare.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Use shared backend code from `supabase/functions/_backend/` across all deployment platforms; never create platform-specific implementations outside this directory

Applied to files:

  • supabase/functions/_backend/utils/cloudflare.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-08T00:40:00.524Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-08T00:40:00.524Z
Learning: Applies to supabase/seed.sql : Updating `supabase/seed.sql` to back new or evolved tests is expected; keep fixtures focused on current behavior while leaving committed migrations unchanged.

Applied to files:

  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/seed.sql : Seed database with `supabase db reset` to apply all migrations and test data from `supabase/seed.sql`

Applied to files:

  • supabase/seed.sql
📚 Learning: 2026-01-09T16:10:23.878Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T16:10:23.878Z
Learning: Applies to supabase/migrations/**/*.sql : Use `get_identity_org_appid()` in RLS policies with both app_id references in `get_identity_org_appid()` and `check_min_rights()` parameters

Applied to files:

  • supabase/seed.sql
📚 Learning: 2026-01-09T16:10:23.878Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T16:10:23.878Z
Learning: Applies to supabase/migrations/**/*.sql : `get_identity_org_allowed()` is an absolute last resort RLS function only when table has NO app_id column and NO way to join to get an app_id

Applied to files:

  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/**/*.{ts,js} : Backend ESLint must pass before commit; run `bun lint:backend` for backend files

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
🧬 Code graph analysis (3)
src/types/supabase.types.ts (1)
supabase/functions/_backend/utils/supabase.types.ts (1)
  • Json (1-7)
supabase/functions/_backend/utils/pg.ts (1)
supabase/functions/_backend/utils/postgres_schema.ts (1)
  • channels (63-83)
supabase/functions/_backend/utils/supabase.types.ts (1)
src/types/supabase.types.ts (1)
  • Json (1-7)
🔇 Additional comments (25)
messages/ko.json (1)

76-77: Electron translation keys look consistent and correctly wired.
New action-disable-platform-electron, channel-platform-electron, and platform-electron entries follow existing key conventions and keep wording aligned with other platform labels.

Also applies to: 415-416, 1131-1134

messages/pl.json (1)

76-78: Electron translation keys are correct and consistent.
The added Polish entries mirror the existing platform/action/channel patterns and appear correctly integrated.

Also applies to: 415-417, 1130-1134

messages/es.json (1)

75-78: Spanish Electron strings match existing platform phrasing.
New Electron keys follow the same structure as Android/iOS and should render correctly in UI.

Also applies to: 413-417, 1130-1134

src/components/dashboard/DeploymentBanner.vue (2)

69-73: Types updated cleanly to carry electron through the component.
DefaultChannel + PlatformKey changes are minimal and keep the rest of the code strongly typed.

Also applies to: 81-87


99-116: Deploy target computation correctly includes Electron channels.
Filtering + platform array composition looks correct and keeps ordering stable across platforms.

supabase/functions/_backend/utils/postgres_schema.ts (1)

63-83: Schema addition for channels.electron is consistent with ios/android.
notNull().default(true) keeps existing rows compatible while enabling Electron-specific filtering. Migration, schema definition, and seed fixtures are all properly synchronized.

supabase/seed.sql (4)

537-542: Seed channels: electron column + electron_only channel look consistent.

Good update to explicitly seed channels.electron and provide an electron_only fixture for test coverage. Based on learnings, keep fixtures minimal and aligned with current tests.


755-756: reset_and_seed_app_data: electron propagation is good; ensure channel naming/flags match backend expectations.

The electron_only channel is seeded and its id captured—nice for deterministic tests that need platform-specific selection.

Also applies to: 856-867


556-557: Electron device seed fixture is acceptable as-is. os_version: 'Linux 5.15' is valid; the field accepts any string value regardless of platform, with no numeric-only requirement in the backend parsing logic.


563-563: Sequence bump verified: channel_id_seq nextval is safe.

Max seeded channel id = 5, and setval(..., 6, false) correctly makes the next nextval() return 6. No other INSERT paths in seed data or migrations set higher channel ids.

supabase/functions/_backend/utils/pg.ts (4)

370-385: Channel select shape: electron is correctly propagated.

This keeps the “channelData.channels.electron” surface consistent across the DB layer.


682-706: getMainChannelsPg: return type update is aligned and low-risk.


758-791: getChannelsPg: return type update is aligned and low-risk.


820-864: platformColumn approach is clearer; callsite at line 535 of channel_self.ts properly handles the union type.

The single callsite in the codebase correctly casts the platform parameter to the required union type ('ios' | 'android' | 'electron') before passing it to getCompatibleChannelsPg, ensuring type safety and compilation.

supabase/functions/_backend/utils/cloudflare.ts (2)

199-202: trackDevicesCF: platform mapping updated cleanly for Electron.


589-606: readDevicesCF: mapping back to 'electron' is correct; ensure any UI filters accept it.

supabase/functions/_backend/utils/supabase.types.ts (3)

618-705: channels typing: electron field is correctly represented in Row/Insert/Update.


3068-3074: Enums/constants: platform_os + disablePlatformElectron updates look consistent.

Also applies to: 3310-3331, 3392-3394


9-34: Type surface: graphql_public addition is fine; no downstream code assumes only public. The type system was designed to support multiple schemas through generic helpers that accept optional schema: keyof DatabaseWithoutInternals parameters. All runtime code explicitly accesses Database['public'], so the addition is additive with no breaking changes.

src/types/supabase.types.ts (6)

10-34: Verify graphql_public namespace addition.

The new graphql_public namespace appears to be unrelated to Electron platform support. This might be a side effect of updating Supabase types or running bun types with a newer Supabase version. Confirm whether this change is intentional and related to this PR.


631-631: LGTM: Electron field properly added to channels table.

The electron boolean field is consistently added across Row, Insert, and Update types for the channels table, matching the pattern of existing ios and android fields. The optional modifier on Insert/Update types is appropriate.

Also applies to: 652-652, 673-673


3113-3115: LGTM: Stats action enum values added for Electron support.

The new stats_action enum values follow the existing pattern:

  • disablePlatformElectron aligns with disablePlatformIos and disablePlatformAndroid
  • disableProdBuild and disableDevice appear to be general additions that complement existing disable actions

These additions support proper analytics tracking for Electron platform configurations.

Also applies to: 3136-3136


3311-3313: LGTM: Constants properly updated to mirror type changes.

The Constants object correctly reflects all enum changes:

  • graphql_public.Enums added (empty, matching the type definition)
  • "electron" added to platform_os array
  • New stats_action values included

These runtime constants enable type-safe enum validation throughout the application.

Also applies to: 3329-3329, 3370-3372, 3393-3393


448-448: The Relationships: [] array in the build_logs type definition is correct. The build_logs table in the schema has no foreign key constraints—only CHECK constraints on billable_seconds, build_time_unit, and platform. This is the original schema design from the migration that created the table, not a removal. The types file accurately reflects the current database structure.

Likely an incorrect or invalid review comment.


3072-3072: Electron platform integration is already complete.

The addition of "electron" to the platform_os enum is properly integrated throughout the backend. Device registration, channel queries, and update endpoints all correctly handle the new platform—including dedicated disable checks (update.ts:235), platform column selection (pg.ts:835), and channel filtering (pg.ts:442).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds comprehensive support for the Electron platform across the Capgo update system. Electron devices can now receive over-the-air updates alongside iOS and Android devices.

Key Changes:

  • Database migration adds electron enum value to platform_os, adds disablePlatformElectron stats action, and adds electron boolean column to channels table
  • Backend API endpoints updated to validate and handle electron platform requests
  • Analytics tracking extended to track electron devices (platform value = 2)
  • Frontend components updated to display electron platform information
  • Comprehensive test coverage added for electron platform flows
  • Translations added across all 15 supported languages

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
supabase/migrations/20260108000000_add_electron_platform.sql Migration adding electron to platform_os enum, disablePlatformElectron action, and electron column to channels
supabase/seed.sql Seed data updated with electron column values and electron_only test channel
supabase/functions/_backend/utils/postgres_schema.ts Drizzle schema updated with electron boolean column
supabase/functions/_backend/utils/pg.ts Database queries updated to include electron platform filtering and selection
supabase/functions/_backend/utils/update.ts Update logic extended to block updates when electron is disabled on channel
supabase/functions/_backend/utils/cloudflare.ts Analytics tracking updated to track electron devices (platform=2)
supabase/functions/_backend/plugins/updates.ts Validation schema updated to accept electron platform (contains bug with z.literal)
supabase/functions/_backend/plugins/channel_self.ts Platform handling updated for electron; fixes critical connection cleanup bugs
supabase/functions/_backend/utils/supabase.types.ts TypeScript types regenerated with electron platform support
src/types/supabase.types.ts Frontend TypeScript types updated with electron platform support
src/components/dashboard/DeploymentBanner.vue UI updated to display and handle electron deployment targets
src/components/dashboard/AppSetting.vue Channel queries updated to include electron field
messages/*.json (15 files) Translations added for electron platform across all languages
tests/updates.test.ts Test added to verify electron platform is accepted
tests/channel_self.test.ts Comprehensive tests added for electron channel compatibility filtering

defaultChannel: z.optional(z.string()),
is_prod: z.boolean(),
platform: z.literal(['android', 'ios'], {
platform: z.literal(['android', 'ios', 'electron'], {
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

Incorrect use of z.literal() with an array. For validating a string that must be one of several specific values, use z.enum() instead. This should be z.enum(['android', 'ios', 'electron'], { ... }) to properly validate platform values. The current code with z.literal() may not work as intended for enum validation.

Suggested change
platform: z.literal(['android', 'ios', 'electron'], {
platform: z.enum(['android', 'ios', 'electron'], {

Copilot uses AI. Check for mistakes.
Copy link
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

🤖 Fix all issues with AI agents
In @supabase/functions/_backend/utils/supabase.types.ts:
- Line 3075: The platform type and validation checks were extended to include
"electron" but several validators and type annotations still only allow
'ios'|'android' or explicitly reject electron; update the platform union and
validation arrays to include "electron" wherever platforms are checked
(specifically the validation schema used in the create_device handler, the
platform type and validation logic inside the build request handler, and the
type annotation in the build status handler), and update the user-facing error
message that currently says "platform must be ios or android" to include
"electron".
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b4e954 and 1484874.

📒 Files selected for processing (1)
  • supabase/functions/_backend/utils/supabase.types.ts
🧰 Additional context used
📓 Path-based instructions (5)
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/utils/supabase.types.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

supabase/functions/**/*.ts: Never use the Supabase admin SDK (with service key) for user-facing APIs; always use the client SDK with user authentication so RLS policies are enforced
The admin SDK should only be used for accessing data that is not user-accessible or for internal operations (triggers, CRON jobs, etc.)
When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Files:

  • supabase/functions/_backend/utils/supabase.types.ts
**/*.{js,ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use single quotes and no semicolons in JavaScript/TypeScript code

Files:

  • supabase/functions/_backend/utils/supabase.types.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use path aliases: ~/ maps to src/ for imports in TypeScript files

Files:

  • supabase/functions/_backend/utils/supabase.types.ts
🧠 Learnings (9)
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-09T18:24:11.070Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T18:24:11.070Z
Learning: Applies to supabase/functions/**/*.ts : Never use the Supabase admin SDK (with service key) for user-facing APIs; always use the client SDK with user authentication so RLS policies are enforced

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-09T18:24:11.070Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T18:24:11.070Z
Learning: Applies to supabase/functions/**/*.ts : The admin SDK should only be used for accessing data that is not user-accessible or for internal operations (triggers, CRON jobs, etc.)

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2026-01-09T18:24:11.070Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T18:24:11.070Z
Learning: Applies to supabase/seed.sql : Update `supabase/seed.sql` to back new or evolved tests, keeping fixtures focused on current behavior while leaving committed migrations unchanged

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Run `bun types` after schema changes to regenerate TypeScript types from Supabase

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Backend code must be placed in `supabase/functions/_backend/` as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms

Applied to files:

  • supabase/functions/_backend/utils/supabase.types.ts
🧬 Code graph analysis (1)
supabase/functions/_backend/utils/supabase.types.ts (1)
src/types/supabase.types.ts (1)
  • Json (1-7)
🔇 Additional comments (4)
supabase/functions/_backend/utils/supabase.types.ts (4)

631-631: LGTM! Electron field added correctly to channels table types.

The electron boolean field is properly added to the channels table Row, Insert, and Update types with correct optionality, consistent with the existing ios and android fields.

Also applies to: 652-652, 673-673


10-34: No action required. The graphql_public namespace is auto-generated by Supabase's type generation tool (bun types / supabase gen types typescript) from the built-in pg_graphql PostgreSQL extension. This is standard behavior and expected to appear in the generated types file. No SQL migrations are needed for this system-provided schema.


3116-3118: LGTM. The stats_action enum correctly adds "disablePlatformElectron" alongside the migration, type definitions, and backend implementation in update.ts (lines 235-237) that properly handles the new electron platform disable action.


448-448: No action needed. The Relationships: [] for build_logs is correct and intentional—the table has no foreign key constraints as defined in the migration 20251119001847_add_native_build_system.sql. This is an auto-generated types file, so the empty array accurately reflects the actual database schema.

disable_update: "major" | "minor" | "patch" | "version_number" | "none"
key_mode: "read" | "write" | "all" | "upload"
platform_os: "ios" | "android"
platform_os: "ios" | "android" | "electron"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and check the context around the specified lines
cat -n supabase/functions/_backend/utils/supabase.types.ts | sed -n '3070,3080p'

Repository: Cap-go/capgo

Length of output: 501


🏁 Script executed:

# Also check line 3332 for the constant array
cat -n supabase/functions/_backend/utils/supabase.types.ts | sed -n '3325,3335p'

Repository: Cap-go/capgo

Length of output: 498


🏁 Script executed:

# Search for all platform_os usage patterns
rg -n "platform_os" supabase/functions/_backend/ --type=ts -C 1

Repository: Cap-go/capgo

Length of output: 2576


🏁 Script executed:

# Search for switch statements on platform or platform checks
rg -n "switch.*platform|case\s+['\"]ios['\"]|case\s+['\"]android['\"]" supabase/functions/_backend/ --type=ts -C 2

Repository: Cap-go/capgo

Length of output: 38


🏁 Script executed:

# Search for explicit platform value checks (if statements, ternary operators, etc.)
rg -n '===\s*["\']ios["\']|===\s*["\']android["\']|==\s*["\']ios["\']|==\s*["\']android["\']|platform.*["\']ios["\']|platform.*["\']android["\']' supabase/functions/_backend/ --type=ts -C 2

Repository: Cap-go/capgo

Length of output: 124


🏁 Script executed:

# Search for filter or includes checks on platform arrays or values
rg -n 'includes.*platform|filter.*platform|\[.*ios.*android.*\]' supabase/functions/_backend/ --type=ts -C 2

Repository: Cap-go/capgo

Length of output: 1952


🏁 Script executed:

# Check if there are any hardcoded lists of platforms that don't include electron
rg -n '\["ios",\s*"android"\]|\[\'ios\',\s*\'android\'\]|ios.*android.*(?!electron)' supabase/functions/_backend/ --type=ts

Repository: Cap-go/capgo

Length of output: 275


🏁 Script executed:

# Find more instances of hardcoded platform checks
rg -n "ios.*android" supabase/functions/_backend/ --type=ts -A 1 -B 1

Repository: Cap-go/capgo

Length of output: 7646


🏁 Script executed:

# Check the create_device.ts file more completely
cat -n supabase/functions/_backend/private/create_device.ts | head -30

Repository: Cap-go/capgo

Length of output: 1106


🏁 Script executed:

# Check the build/request.ts file more completely around line 64
cat -n supabase/functions/_backend/public/build/request.ts | sed -n '55,75p'

Repository: Cap-go/capgo

Length of output: 1136


Update type definitions and validation in build and device endpoints to support electron.

The enum additions to platform_os at lines 3075 and 3332 are correct, but the changes are incomplete. Multiple endpoints still reject or don't support the 'electron' platform:

  • supabase/functions/_backend/private/create_device.ts line 13: Validation schema only accepts ['ios', 'android']
  • supabase/functions/_backend/public/build/request.ts lines 10 and 64-66: Type annotation and validation check hardcoded to only accept ['ios', 'android'], explicitly rejecting electron with error message "platform must be ios or android"
  • supabase/functions/_backend/public/build/status.ts line 11: Type annotation missing electron support

These locations must be updated to include 'electron' alongside the existing platforms, or the new enum value will cause API rejections.

🤖 Prompt for AI Agents
In @supabase/functions/_backend/utils/supabase.types.ts at line 3075, The
platform type and validation checks were extended to include "electron" but
several validators and type annotations still only allow 'ios'|'android' or
explicitly reject electron; update the platform union and validation arrays to
include "electron" wherever platforms are checked (specifically the validation
schema used in the create_device handler, the platform type and validation logic
inside the build request handler, and the type annotation in the build status
handler), and update the user-facing error message that currently says "platform
must be ios or android" to include "electron".

@riderx riderx force-pushed the riderx/add-electron-platform branch 2 times, most recently from 3b55e6b to d3df775 Compare January 10, 2026 02:38
Copy link
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/components/dashboard/DeploymentBanner.vue (1)

17-21: Fix misleading permission comment (“owner” role) to match actual checks + repo policy.
Docs say “admin, super_admin, or owner” (Line 18-20), but the code checks only ['admin', 'super_admin'] (Line 95-97). Also aligns with the project rule to avoid app-level owner checks.

Proposed fix
- * - Only visible to users with admin, super_admin, or owner roles
+ * - Only visible to users with admin or super_admin roles

Also applies to: 95-97

src/components/dashboard/AppSetting.vue (1)

534-584: Bug confirmed: Electron-only channels are incorrectly set to private.

The query at lines 566-571 updates all channels with ios=false AND android=false to public=false. Since Electron-only channels have ios=false, android=false, electron=true, they match this filter and will be unintentionally depublicized.

The proposed fix is correct:

Proposed fix
           const { error: hiddenError } = await supabase
             .from('channels')
             .update({ public: false })
             .eq('app_id', props.appId)
             .eq('ios', false)
             .eq('android', false)
+            .eq('electron', false)

This ensures only truly hidden channels (with no platform support) are set to private.

supabase/functions/_backend/plugins/channel_self.ts (1)

598-606: Inconsistent conditional check in PUT handler.

The PUT handler calls getPgClient(c) without the optional second parameter (line 592), same as POST and DELETE handlers. However, only PUT has the if (pgClient) conditional in its finally block.

  • POST (line 577-579): getPgClient(c) → no conditional
  • DELETE (line 628-630): getPgClient(c) → no conditional
  • PUT (line 603-604): getPgClient(c) → has conditional

Either remove the conditional to match POST/DELETE, or add conditionals to all handlers for consistency.

Suggested fix (remove unnecessary conditional)
   try {
     res = await put(c, getDrizzleClient(pgClient as any), bodyParsed)
   }
   finally {
-    if (pgClient)
-      await closeClient(c, pgClient)
+    await closeClient(c, pgClient)
   }
🧹 Nitpick comments (3)
messages/es.json (1)

415-415: “Solo Electron” is consistent with “Solo Android” (but differs from “Solo para iOS”).
Probably fine, but consider whether you want the “Solo/solo para” phrasing standardized across platform labels in the UI.

supabase/functions/_backend/utils/cloudflare.ts (2)

71-72: trackDeviceUsageCF does not handle Electron platform.

The trackDeviceUsageCF function only maps 'ios' → 1 and defaults to 0 for everything else. This means Electron devices will be counted as Android in the MAU analytics. Consider extending this to match trackDevicesCF.

♻️ Suggested fix to add Electron support
-    // Platform: 0 = android, 1 = ios
-    const platformValue = platform?.toLowerCase() === 'ios' ? 1 : 0
+    // Platform: 0 = android, 1 = ios, 2 = electron
+    const platformLower = platform?.toLowerCase()
+    const platformValue = platformLower === 'ios' ? 1 : platformLower === 'electron' ? 2 : 0

Apply the same change at both lines 71-72 and 87-88.

Also applies to: 87-88


821-849: readLastMonthDevicesByPlatformCF does not include Electron in its return type or query.

The DevicesByPlatform interface and readLastMonthDevicesByPlatformCF function only track ios and android. Consider extending these to include electron for consistency with the admin overview.

♻️ Suggested extension for Electron support
 export interface DevicesByPlatform {
   total: number
   ios: number
   android: number
+  electron: number
 }

 export async function readLastMonthDevicesByPlatformCF(c: Context): Promise<DevicesByPlatform> {
   if (!c.env.DEVICE_USAGE) {
-    return { total: 0, ios: 0, android: 0 }
+    return { total: 0, ios: 0, android: 0, electron: 0 }
   }

   const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10)
-  // Platform: double1 = 0 for android, 1 for ios
+  // Platform: double1 = 0 for android, 1 for ios, 2 for electron
   const query = `SELECT
     COUNT(DISTINCT blob1) AS total,
     COUNT(DISTINCT CASE WHEN double1 = 1 THEN blob1 END) AS ios,
-    COUNT(DISTINCT CASE WHEN double1 = 0 THEN blob1 END) AS android
+    COUNT(DISTINCT CASE WHEN double1 = 0 THEN blob1 END) AS android,
+    COUNT(DISTINCT CASE WHEN double1 = 2 THEN blob1 END) AS electron
   FROM device_usage
   WHERE timestamp >= toDateTime('${formatDateCF(oneMonthAgo)}')
     AND timestamp < now()`

And update the return statement accordingly.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1484874 and d3df775.

📒 Files selected for processing (29)
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/hi.json
  • messages/id.json
  • messages/it.json
  • messages/ja.json
  • messages/ko.json
  • messages/pl.json
  • messages/pt-br.json
  • messages/ru.json
  • messages/tr.json
  • messages/vi.json
  • messages/zh-cn.json
  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/pg.ts
  • supabase/functions/_backend/utils/postgres_schema.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/seed.sql
  • tests/channel_self.test.ts
  • tests/updates.test.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • messages/pt-br.json
  • messages/vi.json
  • messages/tr.json
  • supabase/migrations/20260108000000_add_electron_platform.sql
  • supabase/functions/_backend/plugins/updates.ts
  • messages/hi.json
  • messages/ko.json
  • tests/channel_self.test.ts
  • messages/ja.json
  • messages/ru.json
  • messages/id.json
  • messages/zh-cn.json
  • supabase/functions/_backend/utils/pg.ts
  • messages/de.json
  • messages/pl.json
  • tests/updates.test.ts
  • messages/fr.json
  • supabase/functions/_backend/utils/postgres_schema.ts
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use Vue 3 <script setup> syntax exclusively for all Vue component scripts
Use Tailwind utility classes for layout and spacing in Vue components
Use DaisyUI components (d-btn, d-input, d-card) for interactive elements in Vue components
Use Konsta components ONLY for safe area helpers (top/bottom insets) in Vue components; avoid other uses
Use useRoute() from vue-router to access route parameters and useRouter() for programmatic navigation in Vue components

src/**/*.vue: Use Vue 3 with Composition API and <script setup> syntax for frontend components
Use lean utility classes and composition-friendly patterns rather than bespoke CSS in Vue components
Use DaisyUI (d- prefixed classes) for buttons, inputs, and other interactive primitives to keep behavior and spacing consistent
Konsta components are reserved for the safe area helpers; avoid importing konsta anywhere else in the app
Prefer Vue 3 Composition API in Vue components

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
src/**/*.{ts,tsx,vue,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ~/ alias for imports from src/ directory in frontend TypeScript and Vue components

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
src/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Frontend ESLint must pass before commit; run bun lint:fix to auto-fix issues in frontend files

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
src/**/*.{vue,css}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{vue,css}: Use TailwindCSS with DaisyUI components for styling
Mirror the palette from src/styles/style.css (e.g., --color-primary-500: #515271) when introducing new UI colors

Files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
**/*.{js,ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use single quotes and no semicolons in JavaScript/TypeScript code

Files:

  • src/components/dashboard/AppSetting.vue
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/update.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use path aliases: ~/ maps to src/ for imports in TypeScript files

Files:

  • src/components/dashboard/AppSetting.vue
  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • src/components/dashboard/DeploymentBanner.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/update.ts
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/update.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/update.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

supabase/functions/**/*.ts: Never use the Supabase admin SDK (with service key) for user-facing APIs; always use the client SDK with user authentication so RLS policies are enforced
The admin SDK should only be used for accessing data that is not user-accessible or for internal operations (triggers, CRON jobs, etc.)
When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Files:

  • supabase/functions/_backend/plugins/channel_self.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/update.ts
supabase/seed.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Seed database with supabase db reset to apply all migrations and test data from supabase/seed.sql

Update supabase/seed.sql to back new or evolved tests, keeping fixtures focused on current behavior while leaving committed migrations unchanged

Files:

  • supabase/seed.sql
🧠 Learnings (14)
📚 Learning: 2025-05-29T18:21:17.703Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1107
File: src/components/dashboard/AppSetting.vue:85-182
Timestamp: 2025-05-29T18:21:17.703Z
Learning: In setUpdateChannelSync function in src/components/dashboard/AppSetting.vue, the database update code at the end is intentionally outside the conflict-resolution if block and should run for cases where sync is being toggled without conflicts or after conflicts are resolved. The return statements inside the dialog handling correctly prevent database updates when the user cancels.

Applied to files:

  • src/components/dashboard/AppSetting.vue
📚 Learning: 2025-12-23T01:19:04.593Z
Learnt from: riderx
Repo: Cap-go/capgo PR: 1297
File: src/components/dashboard/DeploymentBanner.vue:77-79
Timestamp: 2025-12-23T01:19:04.593Z
Learning: In the Cap-go codebase, ensure that app permission checks never include the role 'owner'. App-level permissions should be based on the user_min_right enum with values: read, upload, write, admin, super_admin (and NOT owner). This pattern applies across Vue components that perform permission checks; if you find a check referencing 'owner' for app-level access, replace it with the appropriate user_min_right value and keep organization-level owner handling in organization.ts.

Applied to files:

  • src/components/dashboard/AppSetting.vue
  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to cloudflare_workers/plugin/index.ts : Plugin Worker (port 8788) routes: `/updates`, `/channel_self`, `/stats`

Applied to files:

  • supabase/functions/_backend/plugins/channel_self.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All database operations must use `getPgClient()` or `getDrizzleClient()` from `utils/pg.ts` for PostgreSQL access during active migration to Cloudflare D1

Applied to files:

  • supabase/functions/_backend/plugins/channel_self.ts
  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to cloudflare_workers/api/index.ts : API Worker (port 8787) routes: `/bundle`, `/app`, `/device`, `/channel`, `/private/*`, `/triggers`

Applied to files:

  • src/components/dashboard/DeploymentBanner.vue
📚 Learning: 2026-01-09T18:24:11.070Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T18:24:11.070Z
Learning: Applies to supabase/seed.sql : Update `supabase/seed.sql` to back new or evolved tests, keeping fixtures focused on current behavior while leaving committed migrations unchanged

Applied to files:

  • supabase/seed.sql
  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/seed.sql : Seed database with `supabase db reset` to apply all migrations and test data from `supabase/seed.sql`

Applied to files:

  • supabase/seed.sql
📚 Learning: 2026-01-09T18:24:11.070Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T18:24:11.070Z
Learning: Applies to supabase/migrations/**/*.sql : `get_identity_org_allowed()` is an absolute last resort; only use it when the table genuinely has NO app_id column and there is NO way to join to get an app_id

Applied to files:

  • supabase/seed.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use Drizzle ORM query patterns with `schema` from `postgress_schema.ts` for all database operations; use `aliasV2()` for self-joins or multiple table references

Applied to files:

  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Run `bun types` after schema changes to regenerate TypeScript types from Supabase

Applied to files:

  • src/types/supabase.types.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use structured logging with `cloudlog({ requestId: c.get('requestId'), message: '...' })` for all backend logging

Applied to files:

  • supabase/functions/_backend/utils/cloudflare.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Use shared backend code from `supabase/functions/_backend/` across all deployment platforms; never create platform-specific implementations outside this directory

Applied to files:

  • supabase/functions/_backend/utils/cloudflare.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/utils/update.ts
🧬 Code graph analysis (3)
supabase/functions/_backend/plugins/channel_self.ts (2)
supabase/functions/_backend/utils/postgres_schema.ts (1)
  • channels (63-83)
supabase/functions/_backend/utils/pg.ts (2)
  • getCompatibleChannelsPg (759-803)
  • getDrizzleClient (220-222)
src/types/supabase.types.ts (1)
supabase/functions/_backend/utils/supabase.types.ts (1)
  • Json (1-7)
supabase/functions/_backend/utils/update.ts (3)
supabase/functions/_backend/utils/logging.ts (1)
  • cloudlog (3-15)
supabase/functions/_backend/utils/stats.ts (1)
  • sendStatsAndDevice (86-96)
supabase/functions/_backend/utils/hono.ts (1)
  • simpleError200 (213-222)
🔇 Additional comments (27)
messages/it.json (3)

76-76: Translation is consistent with existing Android/iOS “platform disabled” wording.
Matches the established “Bloccato - Piattaforma … disabilitata” pattern.


415-415: “Solo Electron” channel label matches the existing single-platform labels.
Consistent with “Solo Android” / “Solo iOS”.


1132-1132: Platform label “Electron” is correct and consistent with other platform labels.
Keeping it as the product/platform name (not translated) matches Android/iOS handling.

messages/es.json (2)

76-76: Translation matches existing “Bloqueado - Plataforma … deshabilitada” pattern.
Looks consistent with the Android/iOS equivalents.


1132-1132: “Electron” as a proper name is appropriate here.
No issues.

supabase/functions/_backend/utils/supabase.types.ts (2)

619-619: LGTM! Electron field additions to channels table types are consistent.

The electron: boolean field is correctly added as required in Row, and optional (electron?: boolean) in both Insert and Update types, which aligns with typical database column patterns where defaults are applied.

Also applies to: 640-640, 661-661


3063-3063: LGTM! Platform enum and stats_action enum properly extended for Electron.

The platform_os enum now includes "electron" alongside "ios" and "android", and stats_action includes "disablePlatformElectron" consistent with existing disablePlatformIos and disablePlatformAndroid actions.

Also applies to: 3127-3127, 3317-3317, 3381-3381

supabase/seed.sql (4)

537-542: LGTM! Channel seed data correctly includes Electron platform support.

The channel inserts properly include the electron column with appropriate boolean values:

  • production (id=1): electron='t' (true)
  • no_access (id=2): electron='f' (false)
  • two_default (id=3): electron='t' (true)
  • production for stats app (id=4): electron='t' (true)
  • electron_only (id=5): ios='f', android='f', electron='t' - correctly models an Electron-only channel.

556-557: LGTM! Electron test device properly added to seed data.

The new device entry uses platform='electron' with appropriate metadata (plugin_version='7.0.0', os_version='Linux 5.15'), providing test coverage for Electron platform queries.


563-563: LGTM! Sequence correctly updated for new channel.

The channel_id_seq is properly incremented from 5 to 6 to accommodate the new electron_only channel.


855-866: LGTM! reset_and_seed_app_data function properly updated for Electron support.

The function correctly:

  • Declares electron_only_channel_id variable (line 755)
  • Adds electron column to channel inserts
  • Creates an electron_only channel with ios='f', android='f', electron='t'
  • Captures the new channel ID via the SELECT/INTO pattern

Note: The electron_only channel doesn't have a corresponding deploy_history entry (lines 867-872), which is intentional based on the test scenarios, but worth verifying this is the expected behavior for your tests.

supabase/functions/_backend/utils/cloudflare.ts (3)

199-201: LGTM! Platform encoding correctly extended for Electron in trackDevicesCF.

The platform value mapping is clear and correct:

  • 'ios' → 1
  • 'electron' → 2
  • everything else (android) → 0

594-594: LGTM! Platform decoding correctly handles Electron in readDevicesCF.

The reverse mapping properly converts the numeric platform value back to the string representation, maintaining consistency with the encoding in trackDevicesCF.


1198-1198: LGTM! Admin platform overview properly extended for Electron devices.

The AdminPlatformOverview interface and getAdminPlatformOverview function correctly:

  • Add electron_devices to the interface
  • Query sum(if(double1 = 2, 1, 0)) AS electron_devices in the platform query
  • Include electron_devices in the Promise.all type annotation
  • Return electron_devices in the final payload

Also applies to: 1419-1427, 1447-1447, 1480-1480

src/types/supabase.types.ts (4)

3072-3137: Enums/Constants updated correctly for Electron + new stats actions.
platform_os includes "electron" (Line 3072) and stats_action adds disablePlatformElectron (Line 3136) with matching Constants.public.Enums.* entries (Line 3329-3394). This should keep frontend/backends aligned.

Also applies to: 3310-3419


10-34: Verify no stale __InternalSupabase coupling remains after adding graphql_public schema.

The new Database.graphql_public namespace appears correct, but DatabaseWithoutInternals = Omit<Database, "__InternalSupabase"> (line 3193) suggests code may still expect that internal key. Search the codebase for references to __InternalSupabase, DatabaseWithoutInternals, and graphql_public to confirm no broken or redundant coupling exists.


618-705: channels.electron typing is correct and consistent with the database schema.

The migration file supabase/migrations/20260108000000_add_electron_platform.sql defines the column as boolean DEFAULT true NOT NULL, which matches the type definition: Row.electron: boolean (required) and Insert.electron?: boolean / Update.electron?: boolean (optional). No changes needed.


448-449: No action needed—build_logs has no foreign key relationships in the database schema.

The Relationships: [] accurately reflects the actual database design. Tests query build_logs directly and function without issue. No codegen utilities or ORM helpers in the codebase consume relationship metadata from type definitions.

Likely an incorrect or invalid review comment.

messages/en.json (1)

78-81: Electron i18n keys follow existing conventions.
action-disable-platform-electron, channel-platform-electron, and platform-electron match the established key structure and should plug into the new disablePlatformElectron stat/action and UI labels.

Also applies to: 447-451, 1059-1063

src/components/dashboard/AppSetting.vue (1)

34-35: Channel fetch/type updated correctly to include electron.
Adding electron to the local channel shape (Line 34) and selecting it from Supabase (Line 238) is aligned with the new schema.

Also applies to: 235-248

src/components/dashboard/DeploymentBanner.vue (1)

69-116: Deployment banner now correctly accounts for Electron default channels and labels.
The platform list/filtering and getPlatformLabel() changes correctly incorporate electron.

Also applies to: 175-180, 308-317

supabase/functions/_backend/utils/update.ts (1)

216-242: Electron platform disable guard is consistent with existing iOS/Android checks.
Stat emission (disablePlatformElectron) and simpleError200 response structure match the established pattern. The channels.electron field is properly selected in getSchemaUpdatesAlias() (pg.ts:321) and included in all query results.

supabase/functions/_backend/plugins/channel_self.ts (5)

26-26: LGTM! Electron platform added to schema validation.

The enum extension aligns with the database migration and schema changes for Electron support.


214-216: LGTM! Type annotation correctly includes electron property.

The channel type now properly reflects the schema with the electron: boolean field for platform-based channel selection.


377-379: LGTM! Type annotation updated for PUT handler.

Consistent with the POST handler's channel type annotation for Electron support.


535-535: LGTM! Platform type cast correctly includes electron.

The cast matches the getCompatibleChannelsPg function signature that accepts platform: 'ios' | 'android' | 'electron'.


648-656: LGTM! Conditional appropriate for optional PG client.

The GET handler uses getPgClient(c, true) with the second parameter, which may indicate an optional/read-only client that could be undefined. The conditional check is appropriate here, unlike the PUT handler which uses getPgClient(c) without the optional flag.

riderx and others added 6 commits January 10, 2026 07:25
- Added translations for Electron platform in Vietnamese and Simplified Chinese.
- Updated AppSetting component to include Electron in channel management.
- Modified DeploymentBanner component to handle Electron channels.
- Enhanced Supabase types to support Electron platform in database schema.
- Updated backend functions to accommodate Electron in platform checks and channel compatibility.
- Added migration script to include Electron in platform_os enum and related database changes.
- Seeded database with Electron-specific channels for testing.
- Implemented tests for channel retrieval and updates for Electron platform.
- Add electron column to Drizzle schema (postgres_schema.ts)
- Add electron to channelSelect in pg.ts to load the flag for updates
- Fix z.literal to z.enum in channel_self.ts for proper platform validation
- Add electron to inline channel type definitions
- Fix inverted PG client close logic in PUT and GET handlers
- Fix seed.sql no_access channel electron flag to be consistent

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Include electron flag in getMainChannelsPg and getChannelsPg function
return types and select statements to fix TypeScript errors when
accessing channelData.channels.electron in channel_self.ts.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Reset supabase.types.ts from main and properly add only Electron changes:
- electron boolean field in channels table
- electron in platform_os enum
- disablePlatformElectron in update_fail_action enum

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add deploy_history entry for electron_only channel to fix lint warning
about unused variable.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Fix misleading permission comments in DeploymentBanner.vue to match
  actual code checks (admin, super_admin only, not owner)
- Fix bug where Electron-only channels were incorrectly set to private
  by adding .eq('electron', false) to the query filter
- Remove unnecessary conditional check in channel_self.ts PUT handler
  to match POST/DELETE handlers for consistency

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@riderx riderx force-pushed the riderx/add-electron-platform branch from 15b53bb to d357b61 Compare January 10, 2026 07:26
@sonarqubecloud
Copy link

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.

2 participants