# DriverVault

A car control & service-tracking system (originally "Car Control Project").
Built incrementally — starting with a **car maintenance tracker** (modeled on
`Car Service.xlsx`) and growing toward live integration with the car via a
cellular ESP32 device and third-party services (Toyota Connected, EV chargers).

## Architecture

All clients communicate with the database **only through the API Server** —
nothing talks to PocketBase directly.

```
                       ┌──────────────────┐
   Web App (Vue) ─────▶│                  │
   Phone App (Flutter)▶│   API Server     │────▶  PocketBase
   Home Assistant ────▶│   (Go, stdlib)   │       (10.2.1.10:8027)
   Car Agent (ESP32) ─▶│                  │
                       └──────────────────┘
```

| Component | Stack | Status | Docs |
|---|---|---|---|
| **API Server** | Go (stdlib) | ✅ built, running, verified | [API Server/README.md](API%20Server/README.md) |
| **Database** | PocketBase | ✅ running, schema + seed done | — |
| **Web App** | Vue 3 + Vite + Tailwind v4 | ✅ full feature set (below) | [Web App/README.md](Web%20App/README.md) |
| **Phone App** | Flutter (Android) | ✅ web parity + biometric login | [Phone App/README.md](Phone%20App/README.md) |
| **Docker** | Compose (multi-container / all-in-one) | ✅ deployment configs | [Docker/README.md](Docker/README.md) · [Docker-AIO/README.md](Docker-AIO/README.md) |
| **Car Agent Device** | ESP32 + SIM7600 (LILYGO TTGO) | 🚧 firmware in progress | [Car Agent Device](Car%20Agent%20Device) |
| **Home Assistant Plugin** | — | ⬜ later | — |

The Web and Phone apps are at feature parity.

## Features

- **Maintenance tracking** — cars, service history (date/odometer + which parts
  were changed), and a per-car parts catalog, with next-due date/km status from
  the spreadsheet formulas.
- **Technical checks** — the mandatory roadworthiness inspections (przegląd
  techniczny / MOT / TÜV): result, cost, station and the certificate's
  valid-until, which overrides the car's interval and drives the next-due date.
- **Maintenance log** — workshop visits and repairs outside the routine schedule:
  type/status, workshop, parts used, labour + parts cost, invoice, warranty-until.
- **Fuel tracking** — refills with derived efficiency (average / best / worst
  consumption, cost per km, price per litre). Consumption is measured between
  full tanks, so partial fills roll into the next full one.
- **Documents** — insurance, registration, road tax and the rest, each with a
  server-computed renewal/expiry state.
- **Reminders** — date- and/or odometer-triggered, one-off or recurring, plus
  read-only reminders the server derives from documents and service records.
- **Attachments** — one optional file (PDF or image) per service record,
  technical check, maintenance entry, refill, document and part; fetched back
  through the API Server, never a public URL.
- **Accounts** — PocketBase-token login, profile + appearance preferences
  (theme/locale/date format/currency/font), avatar, email verification, data
  export/import, and an account-deletion state machine.
- **Organizations & roles** — multi-tenant `user` / `admin` / `superadmin`
  roles; admins manage users within their own organization, superadmins span all.
  Any user without an organization can create one and becomes its admin.
- **Per-user ownership & sharing** — each car has an owner and can be shared with
  other users as read or write; the UI mirrors the server's access checks.
- **Integrations** — per-user connectors under a superadmin → org-admin → user
  cascade. Built-in today: **Toyota Connected** (read-only vehicle data), the
  **Anker Solix** V1 EV charger and the **Greencell** HabuDen wallbox (read over
  the owner's own MQTT broker — no Greencell cloud is involved). **Apprise**
  joins them as a server-wide connector rather than a per-user one: it hands a
  message to an Apprise gateway the operator runs, which fans it out to any of
  the 100+ services Apprise speaks.
- **Cars from the manufacturer's own service** — import a car straight off a
  connected account (MyToyota today), choosing what to pull in, and read everything
  that service knows about it from a dedicated first tab on the car. Generic over
  providers: the next manufacturer is one adapter in the API Server.
- **EV charging control** — for Anker Solix chargers the owner can start, stop
  and limit charging from the Charging screen over whichever of three transports
  their control mode picks: **Anker's own cloud** (commands ride the connection
  the charger already holds to Anker, so nothing has to be reachable — the mode
  for a charger on a customer's network), **Modbus TCP** on the local network, or
  an **OCPP 1.6J Central System** the charger dials back into.
- **Translated UI** — the interface reads its text from per-language files
  (English, Polish, Danish today), with English as the fallback for any
  untranslated string. See [TRANSLATIONS.md](TRANSLATIONS.md).
- **Phone biometric login & app lock** — fingerprint / face sign-in with an
  app-lock that requires an unlock on relaunch. See the Phone App README.

## Auth model

All apps share one auth model: **authentication is PocketBase's own.**
`POST /api/auth/login` is proxied to the PocketBase users collection and the
client keeps the token PocketBase minted — the API Server does **not** issue its
own JWT. Every protected request carries `Authorization: <token>` (both
`Bearer <token>` and a raw token are accepted) and the server re-resolves it
against PocketBase on each call, so a role change or a deletion takes effect
immediately. Tokens are stateless, so there is no per-device session list;
changing an account's password rotates its token key and invalidates every token
already issued. Access to cars/records is gated by per-user ownership and shares;
user management requires the admin or superadmin role. Creating an organization
is the one management action open to a plain user — it promotes them to admin of
the organization they just created.

## Domain (from `Car Service.xlsx`)

- **Cars** — one per vehicle (was: one spreadsheet sheet), with spec fields
  (engine / transmission / differential oil, brake fluid, coolant, VIN, fuel
  type, build / first-registration dates, …) and configurable service intervals.
- **Service records** — date + odometer per service, plus which parts were
  changed (oil & oil filter, engine air filter, cabin air filter).
- **Parts** — per-car catalog of part numbers.

Key spreadsheet formulas, reproduced by the API Server on read:

```
Next Service Date = service date + serviceIntervalDays   (default 365; Excel: =A+365)
Next Service Km   = service km   + serviceIntervalKm      (default 15 000; Excel: =B+15000)
```

Intervals are configurable per car.

## Getting started

Bring up the stack in this order — each app's README has the details:

1. **[API Server](API%20Server/README.md)** — configure `.env`, run
   `setup-pocketbase.mjs`, start the server. This must be running for either app.
2. **[Web App](Web%20App/README.md)** — `npm install && npm run dev`
   (proxies `/api` to the server).
3. **[Phone App](Phone%20App/README.md)** — `flutter build apk` /
   `flutter run` with `--dart-define=API_BASE=http://<server-ip>:8080/api`.

Or skip all of that and bring the whole stack up with **Docker**, which runs the
schema setup itself — see [Docker](Docker/README.md) (PocketBase + API Server +
Web App as three containers) or [Docker-AIO](Docker-AIO/README.md) (all three
in a single image).

## Layout

```
DriverVault/
├── API Server/            # Go gateway to PocketBase (the only DB client)
├── Web App/               # Vue 3 + Vite + Tailwind v4 SPA + Go BFF
├── Phone App/             # Flutter (Android)
├── Car Agent Device/      # ESP32 + SIM7600 firmware (LILYGO TTGO T-SIM7600)
├── Home Assistant Plugin/ # later phase
├── Docker/                # Compose deployment (API Server + Web App)
└── Docker-AIO/            # single all-in-one image
```
