Replace the Express service with a Next.js app on Vercel

The standalone service in server/ was never deployed anywhere, and keeping it
alongside a Vercel app would mean maintaining two implementations of the same
validation rules. It is deleted; web/ is the only ingest path now. Its routes
live at /v1/... rather than under /api, so the Android client's URL building is
unchanged and CONSUMPTION_API_URL stays a bare origin.

Credentials are split in two. INGEST_TOKEN is baked into the published APK and
must be assumed extractable — anyone can unzip an APK and read its strings — so
it opens the PUT endpoints and nothing else. Reading the history needs the
dashboard password, which is never compiled into anything and reaches the
browser as an HMAC-signed httpOnly cookie. The MongoDB URI stays a server-side
environment variable; the car has never held one and still does not.

The dashboard is a phone-shaped reader for the same data: totals for energy
taken and paid, a daily energy chart, an efficiency trend, and every DC session
with its power/SOC curve. It reuses the head unit's OLED palette so the two read
as one app. Every page is a server component and the charts are hand-rolled SVG,
so the whole thing renders without shipping client JavaScript.

MongoClient is cached on globalThis: a fresh client per request means a fresh
pool per request, and Atlas starts refusing connections long before the traffic
would justify it. Index creation moved to the first write of each warm lambda,
since a serverless deployment has no boot step to hang it on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
TCFDONMEZ
2026-10-08 14:21:37 +03:00
co-authored by Claude Opus 5
parent e9bfa1217b
commit 8242797ece
40 changed files with 3120 additions and 1319 deletions
-27
View File
@@ -1,27 +0,0 @@
# FatihsMG4 consumption API
The Android app never connects to MongoDB directly and never contains a MongoDB URI. This
service stores completed daily totals in `daily_consumption` and each completed charge,
including its SOC/power curve and price, in `charging_sessions`.
## Run
1. Copy `.env.example` to `.env` and fill in the MongoDB Atlas URI and a random API token.
2. Export the variables (Node does not load `.env` automatically), then run `npm install` and
`npm start`.
3. Build the Android app with the public HTTPS service address and the same token:
```sh
CONSUMPTION_API_URL=https://your-api.example.com \
CONSUMPTION_API_TOKEN=your-random-token \
./gradlew assembleUnstableRelease
```
If either Android build variable is missing, cloud sync is disabled and local consumption
tracking continues unchanged. The car retries locally queued charging sessions every five minutes.
Daily consumption is uploaded once after the day closes; missed days are retried in order.
The future mobile client can read authenticated history from:
- `GET /v1/consumption/:installationId`
- `GET /v1/charging-sessions/:installationId`