Skip to content

feat(apps): ship native shells and release downloads - #180

Merged
atulmgupta merged 4 commits into
mainfrom
native-apps
Sep 29, 2026
Merged

atulmgupta merged 4 commits into
mainfrom
native-apps

Conversation

@atulmgupta

Copy link
Copy Markdown
Collaborator

What changed

  • Add generic Android/iOS Capacitor and Windows Electron shells with first-launch server selection, app sign-in, and theme-aware branding.
  • Publish privacy and native app setup documentation.
  • Extend the existing gated Release workflow to attach an unsigned NSIS installer (.exe), unsigned SDK-packaged MSIX, and debug-signed Android test APK. The debug APK is not a Play Store build, and unsigned Windows packages require signing for sideloading.

Why

Let self-hosted users install and configure the app for their own servers; make testing binaries downloadable from GitHub Releases without claiming Store-ready signing.

How to test

  • npm test --prefix apps/desktop; npm run dist --prefix apps/desktop -- --win nsis appx; ./apps/desktop/package-msix.ps1 -Appx -Msix
  • Build web/dist, npx cap sync android from apps/mobile, and gradlew assembleDebug from apps/mobile/android; install the APK on an attached device.
  • go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/release.yml; npm run docs:build --prefix docs; npx tsc --noEmit from web/

Android APK and Windows packages were built and their formats verified locally. Emulator launch was blocked on this machine by Android Emulator reporting too many instances despite adb showing no device.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Credential leakage, missing Electron CSP protection, identity-schema mismatch, and routing defects must be resolved before release.

Review effort: Balanced
Findings: 2 High severity · 4 Medium severity

Open (6)
What changed in this PR

Adds generic Capacitor and Electron clients for self-hosted TeslaSync servers, app-token authentication, native deep links, platform packaging, and release artifacts.

Changes:

  • Adds Android/iOS and Windows shells with server selection and authenticated API/SSE routing.
  • Adds app-bound API keys, Digital Asset Links, CORS configuration, and schema support.
  • Extends release packaging, documentation, privacy disclosures, and branded assets.
File Description
.env.example Documents Android asset links.
.github/​workflows/​release.yml Builds native release artifacts.
apps/​desktop/​.gitignore Ignores desktop outputs.
apps/​desktop/​README.md Documents Electron packaging.
apps/​desktop/​assets.js Resolves bundled web assets.
apps/​desktop/​assets.test.js Tests asset resolution.
apps/​desktop/​assets/​icon.ico Adds Windows icon.
apps/​desktop/​electron-builder.yml Configures Windows packages.
apps/​desktop/​main.js Implements Electron main process.
apps/​desktop/​package-lock.json Locks desktop dependencies.
apps/​desktop/​package-msix.ps1 Repackages and validates MSIX.
apps/​desktop/​package.json Defines desktop scripts.
apps/​desktop/​preload.js Bridges shell integration.
apps/​desktop/​titlebar.js Validates title-bar messages.
apps/​desktop/​titlebar.test.js Tests title-bar validation.
apps/​mobile/​.gitignore Ignores mobile dependencies.
apps/​mobile/​README.md Documents mobile builds.
apps/​mobile/​android/​.gitignore Ignores Android outputs.
apps/​mobile/​android/​app/​.gitignore Ignores app build outputs.
apps/​mobile/​android/​app/​build.gradle Configures Android app build.
apps/​mobile/​android/​app/​capacitor.build.gradle Configures Capacitor plugins.
apps/​mobile/​android/​app/​proguard-rules.pro Adds ProGuard defaults.
apps/​mobile/​android/​app/​src/​androidTest/​java/​com/​getcapacitor/​myapp/​ExampleInstrumentedTest.java Adds Android instrumented test.
apps/​mobile/​android/​app/​src/​main/​AndroidManifest.xml Declares Android shell and links.
apps/​mobile/​android/​app/​src/​main/​java/​com/​teslasync/​app/​MainActivity.java Adds Capacitor activity.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-hdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-ldpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-mdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-hdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-ldpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-mdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-xhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-xxhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-night-xxxhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-xhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-xxhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-land-xxxhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-night/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-hdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-ldpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-mdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-hdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-ldpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-mdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-xhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-xxhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-night-xxxhdpi/​splash.png Adds dark splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-xhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-xxhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-port-xxxhdpi/​splash.png Adds splash asset.
apps/​mobile/​android/​app/​src/​main/​res/​drawable-v24/​ic_launcher_foreground.xml Defines adaptive icon foreground.
apps/​mobile/​android/​app/​src/​main/​res/​drawable/​ic_launcher_background.xml Defines launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​drawable/​splash.png Adds default splash.
apps/​mobile/​android/​app/​src/​main/​res/​layout/​activity_main.xml Defines WebView activity layout.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-anydpi-v26/​ic_launcher.xml Defines adaptive launcher icon.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-anydpi-v26/​ic_launcher_round.xml Defines round launcher icon.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-hdpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-hdpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-hdpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-hdpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-ldpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-ldpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-ldpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-ldpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-mdpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-mdpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-mdpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-mdpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xhdpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xhdpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xhdpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xhdpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxhdpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxhdpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxhdpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxhdpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxxhdpi/​ic_launcher.png Adds launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxxhdpi/​ic_launcher_background.png Adds launcher background.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxxhdpi/​ic_launcher_foreground.png Adds launcher foreground.
apps/​mobile/​android/​app/​src/​main/​res/​mipmap-xxxhdpi/​ic_launcher_round.png Adds round launcher asset.
apps/​mobile/​android/​app/​src/​main/​res/​values/​ic_launcher_background.xml Defines launcher color.
apps/​mobile/​android/​app/​src/​main/​res/​values/​strings.xml Defines Android app strings.
apps/​mobile/​android/​app/​src/​main/​res/​values/​styles.xml Defines Android themes.
apps/​mobile/​android/​app/​src/​main/​res/​xml/​data_extraction_rules.xml Restricts Android backups.
apps/​mobile/​android/​app/​src/​main/​res/​xml/​file_paths.xml Configures FileProvider paths.
apps/​mobile/​android/​app/​src/​test/​java/​com/​getcapacitor/​myapp/​ExampleUnitTest.java Adds local Android test.
apps/​mobile/​android/​build.gradle Configures Android toolchain.
apps/​mobile/​android/​capacitor.settings.gradle Registers Capacitor modules.
apps/​mobile/​android/​gradle.properties Defines Gradle settings.
apps/​mobile/​android/​gradle/​wrapper/​gradle-wrapper.jar Adds Gradle wrapper.
apps/​mobile/​android/​gradle/​wrapper/​gradle-wrapper.properties Pins Gradle distribution.
apps/​mobile/​android/​gradlew Adds Unix Gradle launcher.
apps/​mobile/​android/​gradlew.bat Adds Windows Gradle launcher.
apps/​mobile/​android/​settings.gradle Defines Android modules.
apps/​mobile/​android/​variables.gradle Pins Android dependencies.
apps/​mobile/​assets/​icon.png Adds mobile icon source.
apps/​mobile/​assets/​splash.png Adds mobile splash source.
apps/​mobile/​capacitor.config.json Configures Capacitor shell.
apps/​mobile/​icons/​icon-128.webp Adds mobile icon.
apps/​mobile/​icons/​icon-192.webp Adds mobile icon.
apps/​mobile/​icons/​icon-256.webp Adds mobile icon.
apps/​mobile/​icons/​icon-48.webp Adds mobile icon.
apps/​mobile/​icons/​icon-512.webp Adds mobile icon.
apps/​mobile/​icons/​icon-72.webp Adds mobile icon.
apps/​mobile/​icons/​icon-96.webp Adds mobile icon.
apps/​mobile/​ios/​.gitignore Ignores iOS outputs.
apps/​mobile/​ios/​App/​App.xcodeproj/​project.pbxproj Configures Xcode project.
apps/​mobile/​ios/​App/​App.xcworkspace/​xcshareddata/​IDEWorkspaceChecks.plist Adds workspace metadata.
apps/​mobile/​ios/​App/​App/​AppDelegate.swift Integrates Capacitor lifecycle.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​AppIcon.appiconset/​AppIcon-512@2x.png Adds iOS app icon.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​AppIcon.appiconset/​Contents.json Defines iOS icon set.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Contents.json Defines iOS assets.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Contents.json Defines splash variants.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@1x~universal~anyany-dark.png Adds dark splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@1x~universal~anyany.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@2x~universal~anyany-dark.png Adds dark splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@2x~universal~anyany.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@3x~universal~anyany-dark.png Adds dark splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​Default@3x~universal~anyany.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​splash-2732x2732-1.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​splash-2732x2732-2.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Assets.xcassets/​Splash.imageset/​splash-2732x2732.png Adds splash asset.
apps/​mobile/​ios/​App/​App/​Base.lproj/​LaunchScreen.storyboard Defines iOS launch screen.
apps/​mobile/​ios/​App/​App/​Base.lproj/​Main.storyboard Defines Capacitor controller.
apps/​mobile/​ios/​App/​App/​Info.plist Configures iOS app and links.
apps/​mobile/​ios/​App/​Podfile Declares Capacitor pods.
apps/​mobile/​package-lock.json Locks mobile dependencies.
apps/​mobile/​package.json Defines mobile dependencies.
apps/​msix/​.gitignore Ignores MSIX output.
apps/​msix/​README.md Documents PWABuilder flow.
apps/​msix/​package.ps1 Adds PowerShell preflight.
apps/​msix/​package.sh Adds shell preflight.
apps/​twa/​.gitignore Ignores TWA secrets.
apps/​twa/​README.md Documents TWA builds.
apps/​twa/​build.sh Builds TWA artifacts.
apps/​twa/​init.sh Initializes per-domain TWA.
docker-compose.yml Exposes native-app configuration.
docs/​.vitepress/​config.ts Links app and privacy docs.
docs/​apps.md Documents native apps.
docs/​privacy.md Adds privacy policy.
helm/​teslasync/​templates/​configmap.yaml Renders CORS and asset links.
helm/​teslasync/​values.yaml Adds native-app values.
internal/​api/​apikey/​handler.go Creates app-bound API keys.
internal/​api/​apikey/​handler_test.go Tests app-key behavior.
internal/​api/​apikey_middleware.go Authenticates bearer app tokens.
internal/​api/​apikey_middleware_test.go Tests token middleware.
internal/​api/​assetlinks_test.go Tests asset-links endpoint.
internal/​api/​middleware/​csrf.go Allows validated app tokens.
internal/​api/​middleware/​csrf_test.go Tests app-token CSRF handling.
internal/​api/​router.go Wires auth and asset links.
internal/​auth/​apptoken.go Carries app-token identity.
internal/​auth/​apptoken_test.go Tests identity context.
internal/​auth/​session_tracker.go Skips app-token sessions.
internal/​config/​config.go Loads asset-links configuration.
migrations/​000254_api_keys_subject.down.sql Removes app-token binding.
migrations/​000254_api_keys_subject.up.sql Adds app-token binding.
ops/​migrations/​manifest.yaml Records migration risk.
web/​nginx.conf Proxies well-known resources.
web/​public/​favicon.svg Updates favicon branding.
web/​public/​icons/​README.md Documents icon generation.
web/​public/​icons/​apple-touch-icon.png Updates Apple icon.
web/​public/​icons/​icon-192.png Updates PWA icon.
web/​public/​icons/​icon-192.svg Updates icon source.
web/​public/​icons/​icon-512.png Updates PWA icon.
web/​public/​icons/​icon-512.svg Updates icon source.
web/​public/​icons/​icon-maskable-192.png Updates maskable icon.
web/​public/​icons/​icon-maskable-192.svg Updates maskable source.
web/​public/​icons/​icon-maskable-512.png Updates maskable icon.
web/​public/​icons/​icon-maskable-512.svg Updates maskable source.
web/​scripts/​generate-app-icons.mjs Generates cross-platform icons.
web/​src/​App.tsx Mounts server and link routing.
web/​src/​api/​client.ts Adds remote bearer requests.
web/​src/​api/​devtools.ts Authenticates import uploads.
web/​src/​api/​hooks/​useAdmin.ts Supports app-key creation.
web/​src/​api/​hooks/​useVehiclePhoto.ts Authenticates photo uploads.
web/​src/​api/​sseClient.ts Supports remote SSE.
web/​src/​components/​feedback/​ReauthDialog.tsx Authenticates reauthorization calls.
web/​src/​components/​ui/​FontProvider.tsx Loads remote font settings.
web/​src/​components/​ui/​MaskedValue.tsx Authenticates reveal audits.
web/​src/​components/​ui/​ThemeProvider.tsx Loads remote theme settings.
web/​src/​features/​admin/​components/​api-keys/​ApiKeyCard.tsx Displays app-bound keys.
web/​src/​features/​admin/​components/​api-keys/​CreateApiKeyModal.test.tsx Tests app-key form.
web/​src/​features/​admin/​components/​api-keys/​CreateApiKeyModal.tsx Adds app sign-in option.
web/​src/​features/​admin/​pages/​ApiPlaygroundPage.tsx Authenticates playground requests.
web/​src/​features/​server/​ConnectPage.test.tsx Tests server connection flow.
web/​src/​features/​server/​ConnectPage.tsx Implements server picker.
web/​src/​features/​server/​NativeDeepLinks.test.ts Tests native link allowlist.
web/​src/​features/​server/​NativeDeepLinks.tsx Routes native deep links.
web/​src/​features/​server/​ServerGate.tsx Enforces first-launch setup.
web/​src/​features/​settings/​components/​ServerSection.tsx Adds server settings.
web/​src/​features/​settings/​pages/​SettingsPage.tsx Registers server section.
web/​src/​features/​system/​hooks/​useStatusLiveSSE.ts Routes status SSE remotely.
web/​src/​hooks/​useAiStream.ts Authenticates AI streaming.
web/​src/​hooks/​useSSE.ts Routes signal SSE remotely.
web/​src/​i18n/​en.json Adds canonical English strings.
web/​src/​i18n/​en/​locale-admin.json Generates admin translations.
web/​src/​i18n/​en/​locale-settings.json Generates connection translations.
web/​src/​i18n/​en/​runtime-manifest.json Registers runtime namespace.
web/​src/​i18n/​en/​shell.json Adds route label.
web/​src/​i18n/​en/​usage-manifest.json Registers translation usage.
web/​src/​index.css Styles desktop title bar.
web/​src/​lib/​__tests__/​appIcon.test.ts Updates icon expectations.
web/​src/​lib/​appIcon.ts Updates icon background.
web/​src/​lib/​automationSSE.ts Routes automation SSE remotely.
web/​src/​lib/​eventStream.test.ts Tests authenticated SSE transport.
web/​src/​lib/​eventStream.ts Implements fetch-backed SSE.
web/​src/​lib/​resilience.ts Routes resilient remote requests.
web/​src/​lib/​routePrefetch.ts Prefetches connection page.
web/​src/​lib/​routeRegistry.ts Registers connection route.
web/​src/​lib/​serverConnection.test.ts Tests connection state.
web/​src/​lib/​serverConnection.ts Manages server and token state.
web/​src/​lib/​sseManager.ts Uses authenticated SSE.
web/​src/​types/​admin.ts Adds app-key subject type.
web/​vite.config.ts Registers protocol handler.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/desktop/main.js
Comment on lines +32 to +35
const data = await fs.promises.readFile(file);
return new Response(data, {
headers: { 'Content-Type': MIME[path.extname(file)] || 'application/octet-stream' },
});
Comment thread web/src/lib/resilience.ts
headers: { 'Content-Type': 'application/json' },
...restOpts,
...(demoCredentialsMode() ? { credentials: demoCredentialsMode() } : {}),
headers: authHeaders(optHeaders ?? { 'Content-Type': 'application/json' }),
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();

assertEquals("com.getcapacitor.app", appContext.getPackageName());
return
}

_, _ = q.Exec(r.Context(), `UPDATE api_keys SET last_used_at = NOW() WHERE id = $1`, id)
-- as an app token and additionally authenticates as that subject on the
-- whole API via `Authorization: Bearer`, so a phone/desktop app can sign
-- in to any self-hosted server.
ALTER TABLE api_keys ADD COLUMN IF NOT EXISTS subject VARCHAR(255);
Comment thread web/src/App.tsx
<Route path="s/:token" element={<SafeRoute name="SharedDrive"><SharedDrive /></SafeRoute>} />
<Route path="watch" element={<SafeRoute name="WatchFace"><WatchFace /></SafeRoute>} />
<Route path="onboarding" element={<SafeRoute name="Onboarding"><Onboarding /></SafeRoute>} />
<Route path="connect" element={<SafeRoute name="Connect"><ConnectPage /></SafeRoute>} />
Copilot AI review requested due to automatic review settings September 28, 2026 23:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Native authentication misses several direct downloads and streams, leaks tokens on one demo fallback path, and has unresolved credential-security and Android-test defects.

Review effort: Balanced
Findings: 3 High severity · 6 Medium severity · 1 Low severity

Open (10)

}

var subjectArg *string
if body.AppToken {
Comment thread internal/api/router.go

// ServeAssetLinks serves the deployment-specific Android Digital Asset Links
// statement list; an unset value leaves the association endpoint disabled.
func ServeAssetLinks(configuredJSON string) http.HandlerFunc {
Comment thread web/src/api/client.ts
* pipeline.
*/
import { resilientFetch, ApiError, getApiBase, isApiError, camelCaseKeys } from '../lib/resilience'
import { authHeaders, isRemoteMode } from '../lib/serverConnection'
Comment thread web/src/i18n/en.json
"subtitle": "Enter your TeslaSync address to continue.",
"serverLabel": "Server address",
"serverPlaceholder": "https://teslasync.example.com",
"serverHint": "Your self-hosted TeslaSync URL — local addresses like http://192.168.1.10:4000 work too.",
Copilot AI review requested due to automatic review settings September 29, 2026 00:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Remote authentication currently has credential-disclosure risks and leaves at least one protected stream unusable from native shells.

Review effort: Balanced
Findings: 4 High severity · 6 Medium severity · 1 Low severity

Open (11)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Ignore mobile signing key files

apps/​mobile/​android/​.gitignore:58

The mobile README tells distributors to create and back up a signing key, but this new ignore file leaves both common key formats trackable. Uncomment these patterns so a release keystore cannot be committed accidentally.

Comment on lines +73 to +75
setBusy(true)
try {
const probe = await probeServer(normalized.url, token.trim() === '' ? null : token)
Copilot AI review requested due to automatic review settings September 29, 2026 04:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Protected resources, token-expiry recovery, Windows navigation, and Android validation contain blocking native-app failures.

Review effort: Balanced
Findings: 4 High severity · 6 Medium severity · 2 Low severity

Open (12)
Previously missed (5)

In code that hasn't changed since last review

Medium severity External navigation and download flows are blocked

apps/​desktop/​main.js:110

The shell blocks every navigation away from the private app origin and denies every new window without handing approved URLs to the OS. As a result, existing documentation/support links and window.open(...) download flows become inert in the Windows app. Add a strict http:/https: allowlist and open accepted external links with shell.openExternal; keep authenticated API downloads on a dedicated fetch/save path.

Medium severity Error logs expose forward-auth user identity

internal/​api/​apikey/​handler.go:190

The forward-auth subject is commonly an email address or username, so adding it to this error log exposes user identity in backend logs. Keep the operational context but remove the raw subject field.

Medium severity Revoked tokens trigger endless event-stream retries

web/​src/​features/​system/​hooks/​useStatusLiveSSE.ts:130

FetchEventStream marks 401/403 responses as CLOSED specifically to stop retrying a rejected token, but this hook treats every CLOSED error as reconnectable at lines 157–162. A revoked app token therefore causes /system/status/live to be retried forever. Detect this terminal remote-token state and remain offline or invoke the shared authentication recovery instead.

Medium severity Protected resource URLs omit authentication

web/​src/​lib/​resilience.ts:58

Using the selected server as the API base does not authenticate URL-only consumers. Existing apiUrl() callers such as vehicle-photo <img src> values and export/download anchors now point at the remote server without the session-stored Authorization header, so those resources return 401 on the forward-auth setup this feature is designed to support. Convert protected resources to authenticated fetches (then blob/object URLs or a native save/open bridge) instead of exposing them as plain navigation URLs.

Medium severity Expired native tokens lack recovery path

web/​src/​lib/​serverConnection.ts:159

A revoked or expired stored app token leaves native users without a recovery path. API 401s still invoke the browser-session reauthentication modal, but the connection gate remains bypassed while this token is in sessionStorage and Electron blocks navigation to the external IdP. Remote-mode authentication failures need to clear the token and return to /connect (or make the modal perform that native-specific recovery).

name: Build Android test APK
needs: version
# The Android SDK is preinstalled on GitHub-hosted Ubuntu runners.
runs-on: ubuntu-latest
@atulmgupta
atulmgupta merged commit d9a3993 into main Sep 29, 2026
84 of 85 checks passed
@atulmgupta
atulmgupta deleted the native-apps branch September 29, 2026 06:57

This branch had an error being deployed

1 failed deployment
github-pages — 7838ffe6 Deployed Sep 29, 2026 by atulmgupta via Build & Deploy Docs #69
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants