Stop the flow store leaking git zombies, honour VITE_API_URL from .env

`FlowStore._git` now passes `-c gc.auto=0`, so `git commit` no longer forks a
background `gc --auto` that reparents onto PID 1 and stays there unreaped. With
auto-gc off nothing packs on its own, so `_commit` runs a foreground `git gc`
every 500 commits — the trigger a long-lived seeding session actually reaches.

`docker/compose.yml` takes the frontend's `VITE_API_URL` build arg from the
environment, keeping `https://api.${DOMAIN}` only as the fallback. `setup.sh`
already derives the scheme from `ENVIRONMENT`, so an `up --build` that does not
layer `compose.local.yml` stops shipping a bundle that calls `https://api.localhost`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01StpRc2C6au1WJ1EUU7fsfu
This commit is contained in:
2026-08-23 16:49:46 +02:00
co-authored by Claude Opus 5
parent c81d6cb21a
commit ce465e7b0e
5 changed files with 46 additions and 24 deletions
+8 -22
View File
@@ -16,20 +16,12 @@ Deferring because out of scope is fine, but don't mention deferring than.
- FEAT/UI: check if PWA (https://whatpwacando.today/) notifications could be used to have a panel sending notifications to the device event bus (or generally using PWA to retrieve e.g. location etc). We could introduce a general concept of having a panel (a device, like a wall panel or a phone where the pwa (dashboard) runs) being effectively a node with various outputs. Then various inputs could trigger actions like authentification (i.e. you get home and get a notification which allows you to authenticate the door unlock), get notified on alarms (native alarm connector) or to query geolocation (check where the user is before turning of all lights) etc
- BUG/UI sync the theme state between panels and installations
- BUG/UI some dashboard widgets (like the color picker) are scrollable; we should make sure that no widgets (except for text widgets or list-related widgets) are scrollable
- INFRA document `make update` in the docs; this command is intended to run as a fire-and-forget command when updating a local installation
- CHORE/UI: the house panels are laid out for 1280x800 — twelve columns, twelve
rows. A chart's fixed chrome is now its title line and legend: the range picker
moved up onto the title and gave back its row, so the budget is nearer forty
pixels than eighty and a third chart may now fit — worth measuring against the
panel before adding one. The temperature history was the one dropped;
`history.climate_*` still answers, so it is a tile away.
- BUG/INFRA: `compose.yml` builds the frontend with `VITE_API_URL=https://api.${DOMAIN}`
and only `compose.local.yml` overrides it to `http`. Any `up --build` that does not layer
the local file therefore ships a bundle calling `https://api.localhost`, which fails with
`ERR_CERT_AUTHORITY_INVALID` and breaks login entirely — nothing terminates TLS locally.
It recurs every time the stack is brought up without the override, so it is not a stale
image but a default that is wrong for the local target. Either flip the default or make the
local target the one the Makefile always passes.
- FEAT/UI: a bar's nested reading is captioned by its port name, which is
chosen for the graph rather than for somebody reading it across a room.
`Segment` now takes an optional `label`; the house dashboard sets one
@@ -51,14 +43,14 @@ Deferring because out of scope is fine, but don't mention deferring than.
`Supervisor.cancel_all` was just fixed for. Latent rather than live: a supervised
node leaves those handles `None`, so only a node built on its own (a test, a
preview) awaits there.
- BUG/INFRA: **475 zombie `git` processes** in the API container after a seeding
session. `FlowStore._git` uses `subprocess.run`, which reaps its own child — these
are the `git gc --auto` daemons `git commit` spawns, reparented to PID 1 when their
parent exits. PID 1 is the FastAPI process, which never reaps orphans. Harmless at
484 processes against a 34719 limit, but it grows with every save, and a container
that commits per keystroke will get there. Fix: `git -c gc.auto=0 commit`, since a
store that never packs is a separate (and real) concern — 1898 commits had left
5863 loose objects and no packs.
- BUG/INFRA: **zombie `python` processes in the API container**, twelve of them in
groups of four with matching elapsed times — one group per worker pool. `_Worker.kill()`
waits on the process it kills, so these are workers orphaned when the process holding
their `Popen` went away without stopping the pool, which is what uvicorn `--reload`
does on every source edit. They reparent onto PID 1, and PID 1 in the container is the
reloader, which reaps nothing that is not its own child. `init: true` on the backend
service hands PID 1 to an init that does reap orphans, and would close the whole class
rather than one source of it.
- PERF/API: seeding nineteen flows takes two reloads each — one to publish, one to
stop — so a full rebuild of every flow in the installation runs about forty times
for one seed. It is the slowest thing about standing an installation up, and a
@@ -424,12 +416,6 @@ Open on purpose. Each names what should bring it back.
with its schemas, so a generator (the way n3xd generates its command catalog) is the
obvious fix once the type list stops moving.
- `make update`/`make up` (production overlay) runs `up -d --remove-orphans` under the
same `fluksio-app` project as `make dev`, so it silently deletes the local Traefik
container `fluksio-app-proxy-1`. With `REVERSE_PROXY=external` and no host proxy,
the whole stack then has nothing bound to :80 and `*.localhost` stops resolving.
Either drop `--remove-orphans` or make `update` refuse when `ENVIRONMENT=local`.
- CHORE: `frontend/vite.config.js` and `frontend/vite.config.d.ts` are committed build
output of `vite.config.ts` and fail `biome check` as tracked (semicolons, 4-space
indent). The pre-commit hook therefore fails for anyone who stages any other file