Skip to content

Add Tesla Fleet API connector for vehicle data sync - #1210

Open
penso wants to merge 2 commits into
mainfrom
claude/tesla-fleet-api-connector-kuwps0
Open

Add Tesla Fleet API connector for vehicle data sync#1210
penso wants to merge 2 commits into
mainfrom
claude/tesla-fleet-api-connector-kuwps0

Conversation

@penso

@penso penso commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds moltis-connector-tesla, a read-only adapter that keeps a local copy of Tesla vehicle data in the shared connector snapshot store. It never sends vehicle commands and never wakes a sleeping car.

Two dataset shapes. The connector store retires any item a run does not re-observe, which is right for "current state" and wrong for history. So:

  • State datasets key items by VIN, so each sync replaces the stored row and the dataset always holds the latest reading.
  • History datasets key items by {vin}:{rfc3339} and carry forward the most recent maxSamples observations per vehicle. Older samples are left unobserved, which is what retires them on commit.

Sleeping vehicles are skipped, not woken. Requesting vehicle data from a sleeping Tesla wakes it and drains the battery, and Fleet API rate-limits the endpoint. The connector reads each vehicle's connectivity state first and skips any car that is not online: a state dataset carries the previous reading forward untouched (keeping its original observedAt, since it is stale), a history dataset records no sample. The first sync of an unreachable vehicle still writes a row so the vehicle is visible with its connectivity state and no data.

Credentials. Moltis does not run the authorization-code flow: that redirect URI belongs to a developer application registered against a domain the operator controls, so the account stores a user-supplied refresh token instead. Fleet API answers 403/412 for a client whose partner registration is incomplete, which maps to a dedicated error naming that setup step rather than a generic failure.

Supporting changes

  • PASSWORD_FIELD becomes SECRET_FIELDS and covers refreshToken, so the token gets the same vault encryption CalDAV passwords already get. Editing a connection without retyping the token preserves the stored one.
  • account_view swaps an eleven-element tuple for a named struct; adding two more positional fields to it was no longer readable.
  • Vault credential handling moves from connectors.rs to connectors_secrets.rs, and the Tesla gateway tests to connectors_tests/tesla.rs, keeping both files under the 1500-line limit.
  • New tesla_connector agent tool (trusted-only, read-only): list_datasets, list_vehicles, get_vehicle, search_readings.
  • Settings UI (connection + dataset forms) in en, fr, zh, zh-TW; docs/src/tesla.md plus connectors.md and SUMMARY.md entries.

Bugs caught by the new tests

  1. charging_state never parsed — Tesla returns it PascalCase ("Charging") inside an otherwise snake_case payload, so every value silently became Unknown.
  2. The Tesla connection form did nothing — SaveButton defaults to type="button", so filling every field and clicking save sent no RPC and showed no error.
  3. get_vehicle could report a stored car as absent — it asked for one row by fuzzy full-text VIN match, then checked the VIN exactly, so another vehicle could rank first and get filtered out.

Validation

Completed

  • cargo fmt --all -- --check
  • cargo clippy -p moltis-connector-tesla --all-targets (clean)
  • cargo clippy -p moltis-gateway --all-targets (clean)
  • ./scripts/check-file-size.sh
  • bash scripts/check-changelog-guard.sh origin/main HEAD
  • cargo test -p moltis-connector-tesla — 35 tests (26 unit + 9 sync integration)
  • cargo test -p moltis-gateway connectors — 40 tests
  • cargo check -p moltis-connector-tesla --no-default-features and --features metrics
  • cd crates/web/ui && npx tsc --noEmit (0 errors)
  • cd crates/web/ui && npx @biomejs/biome check src/pages/connectors/ src/types/connector.ts src/locales/ (no new diagnostics)
  • cd crates/web/ui && npm run build
  • cd crates/web/ui && npx playwright test e2e/specs/settings-connectors.spec.js — 10/10 passing, including 3 new Tesla specs

Remaining

  • Full Rust suite and full E2E suite — left to CI per CLAUDE.md
  • ./scripts/local-validate.sh 1210 — not run; the sandbox hit its disk allowance mid-session, so the release binary never built and E2E ran against a debug build instead
  • Live Fleet API verification against a real Tesla account and a registered developer application — see Manual QA

Manual QA

Everything below needs a real Tesla developer application: registered at developer.tesla.com, public key hosted at https://<your-domain>/.well-known/appspecific/com.tesla.3p.public-key.pem, partner registration completed, and a refresh token with openid offline_access vehicle_device_data (plus vehicle_location for coordinates).

  1. Connection. Settings → Connectors → Connections → Add Tesla connection. Enter the account region, client ID, and refresh token. Save, then Test connection — it should list the vehicles on the account with their connectivity state.
  2. Credential is never echoed. Reopen the connection for editing: the refresh token field is blank with a "leave blank to keep" placeholder. Rename the connection and save without retyping the token, then confirm syncing still works.
  3. State dataset. Create a dataset in state mode with the default endpoints. Sync twice while the car is awake and confirm the item count stays at one per vehicle and observedAt advances.
  4. History dataset. Create a second dataset in history mode with maxSamples set low (say 3). Sync four or more times and confirm the item count caps at 3 per vehicle and the oldest reading drops out.
  5. Sleeping car (the important one). Wait until the vehicle reports asleep in the Tesla app, then run a sync. Confirm the car does not wake, the state dataset still shows the previous reading with its original observedAt, and the history dataset gains no sample. The gateway logs an info line naming the skipped count.
  6. Missing partner registration. Point a connection at a client ID whose partner registration is incomplete and hit Test connection. The error should name that setup step rather than reporting a generic failure.
  7. Agent read path. From a trusted session, ask the agent for the car's charge level and recent charging history, and confirm it answers from tesla_connector without contacting Tesla.
  8. Vault. With vault encryption enabled and the vault unlocked, confirm refreshToken is stored encrypted in <data_dir>/connectors.db; with the vault sealed, confirm syncing fails with an actionable "vault is sealed" message rather than a panic.

claude added 2 commits August 18, 2026 02:20
Adds `moltis-connector-tesla`, a read-only adapter that keeps a local copy
of Tesla vehicle data in the shared connector snapshot store.

A Tesla dataset takes one of two shapes, because the connector store's
snapshot semantics retire any item a run does not re-observe:

- State datasets key items by VIN, so each sync replaces the stored row and
  the dataset always holds the latest reading.
- History datasets key items by `{vin}:{rfc3339}` and carry forward the most
  recent `maxSamples` observations per vehicle. Older samples are left
  unobserved, which is what retires them on commit.

Requesting vehicle data from a sleeping Tesla wakes it and drains the
battery, and Fleet API rate-limits the endpoint, so the connector reads each
vehicle's connectivity state first and skips any car that is not online
rather than waking it. A state dataset carries the previous reading forward
untouched; a history dataset records no sample. The first sync of an
unreachable vehicle still writes a row so the vehicle is visible with its
connectivity state and no data.

Moltis does not run the authorization-code flow: that redirect URI belongs
to a developer application registered against a domain the operator
controls, so the account stores a user-supplied refresh token instead. Fleet
API answers 403/412 for a client whose partner registration is incomplete,
which maps to a dedicated error naming that setup step rather than a generic
failure.

Supporting changes:

- `PASSWORD_FIELD` becomes `SECRET_FIELDS` and covers `refreshToken`, so the
  token gets the same vault encryption CalDAV passwords already get. Editing
  a connection without retyping the token preserves the stored one.
- `account_view` swaps an eleven-element tuple for a named struct; adding two
  more positional fields to it was no longer readable.
- Vault credential handling moves from `connectors.rs` to
  `connectors_secrets.rs`, and the Tesla gateway tests to
  `connectors_tests/tesla.rs`, keeping both files under the size limit.
`SaveButton` defaults to `type="button"`, so the Tesla connection modal's
save control never submitted its form: filling in every field and clicking
save did nothing, sending no RPC and showing no error. Pass `type="submit"`
as the other connector modals do, and use the same create-versus-save label
convention so a new connection reads "Add connection".

Also fixes `tesla_connector`'s `get_vehicle`, which asked the reader for a
single row filtered by full-text VIN match and then checked the VIN exactly.
Full-text matching is fuzzy, so another vehicle's reading could rank first
and get filtered out, reporting a stored vehicle as absent. It now scans a
bounded window of candidates and returns the newest reading whose VIN
matches.

Both were caught by the new E2E and tool tests added alongside them.
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a read-only Tesla Fleet API connector with encrypted refresh-token storage, state and history synchronization, agent querying, gateway lifecycle integration, web configuration, localization, tests, and setup documentation.

  • Introduces bounded Fleet API and OAuth clients with region, VIN, endpoint, and retention validation.
  • Persists current vehicle state or capped historical samples while carrying forward sleeping and offline vehicles.
  • Integrates Tesla account and dataset management into gateway RPCs, vault lifecycle handling, agent tools, and the connectors UI.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable non-blocking issue identified.

The Tesla connector validates external inputs, bounds API responses, avoids waking unreachable vehicles, commits synchronization results atomically, preserves credentials during edits, and consistently integrates vault, gateway, tool, UI, test, and documentation paths.

Important Files Changed

Filename Overview
crates/connector-tesla/src/client.rs Implements bounded, timed Fleet API requests and refresh-token authentication against fixed regional endpoints.
crates/connector-tesla/src/config.rs Defines and validates Tesla account, region, dataset mode, VIN, endpoint, and retention configuration.
crates/connector-tesla/src/connector.rs Implements atomic state and history synchronization, VIN selection, unreachable-vehicle carry-forward, and sample retention.
crates/connector-tesla/src/tool.rs Adds read-only agent operations for listing and searching locally synchronized Tesla data.
crates/gateway/src/connectors.rs Integrates Tesla account lifecycle, connection testing, dataset validation, and synchronization into the connector manager.
crates/gateway/src/connectors_secrets.rs Extends structured connector-secret encryption and migration handling to Tesla refresh tokens.
crates/web/ui/src/pages/connectors/TeslaConnectionForm.tsx Adds create and edit flows that preserve stored refresh tokens unless the user supplies a replacement.
crates/web/ui/src/pages/connectors/TeslaDatasetFields.tsx Adds typed Tesla dataset controls and payload construction for mode, VINs, endpoints, and retention.
docs/src/tesla.md Documents Fleet API application setup, authorization scopes, account configuration, data retention, and security considerations.

Sequence Diagram

sequenceDiagram
  participant UI as Connectors UI
  participant GW as Gateway
  participant Vault
  participant Tesla as Tesla Fleet API
  participant Store as Connector Store
  participant Agent as Tesla Agent Tool

  UI->>GW: Create account and dataset
  GW->>Vault: Encrypt refresh token
  GW->>Store: Persist account and dataset
  GW->>Vault: Decrypt refresh token for sync
  GW->>Tesla: Refresh OAuth access token
  GW->>Tesla: List vehicles
  loop Reachable selected vehicles
    GW->>Tesla: Request configured vehicle data
  end
  GW->>Store: Commit state or retained history snapshot
  Agent->>Store: Query datasets, vehicles, or readings
  Store-->>Agent: Return synchronized local data
Loading

Reviews (1): Last reviewed commit: "fix(connectors): make the Tesla connecti..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 39 untouched benchmarks
⏩ 9 skipped benchmarks1


Comparing claude/tesla-fleet-api-connector-kuwps0 (9ea04e1) with main (ebdca33)

Open in CodSpeed

Footnotes

  1. 9 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@penso
penso force-pushed the claude/tesla-fleet-api-connector-kuwps0 branch from ffd7c4a to 9ea04e1 Compare August 18, 2026 02:26
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