The schema applies itself, and the setup script stops hiding failures

Migrations were run by hand and nothing recorded which had run, so
re-running the setup script against an existing database failed on the
first CREATE TABLE, and shipping a new migration gave an operator no way
to know whether an estate had it. A missed migration is not a startup
error - it is a query referencing a column that is not there, surfacing
later on whichever endpoint touches it first.

server/internal/migrate applies pending migrations at boot and refuses to
start against a schema it does not match. One transaction per file
holding both the DDL and the row that records it; an advisory lock so two
servers starting at once cannot both apply 008; checksums so an edited
migration is refused by name rather than silently skipped; numeric
ordering so 010 does not run before 009. `migrate -baseline N` adopts a
database built before any of this existed, because "the clients table
exists" does not say whether 007's index does.

Verified on the live database: adopted 001-007, applied 008.

008 adds two indexes on `purchases`, found by asking the database which
foreign keys had nothing behind them and then checking what queries the
table. The conversion report filters client_id + occurred_at, which is
exactly the estate-wide case with no site to narrow it.

run-local.sh had two bugs, both found by running it rather than reading
it: it reused a broker container whose bind mount pointed at a directory
that no longer existed, and it discarded stderr on the mosquitto_passwd
call, so under `set -e` it exited at step 5 with no output at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HViLj9gYNRtSr7YVZmW5sn
This commit is contained in:
2026-09-04 12:06:52 +05:30
parent dad04e8cda
commit 5453c26e4c
11 changed files with 941 additions and 8 deletions

61
RUN.md
View File

@@ -215,3 +215,64 @@ cd ../agent && GOOS=windows CGO_ENABLED=0 go build -o behavision-agent.exe .
These compile. They have never been RUN on Windows — no `wails build`, no
installer, no code signing.
---
## Building the Windows package
`installer/build.ps1` produces `dist\Behavision-Setup-<version>.exe`.
**It has to run on Windows.** The Go binaries and the front ends cross-compile
from a Mac (verified), but PyInstaller freezes the interpreter and native
wheels of the machine it runs on — there is no cross-target flag. The engine
.exe is built on Windows or not at all.
On the Windows box, with Python 3.11+, Go 1.21+, Node LTS and
[Inno Setup 6](https://jrsoftware.org/isdl.php) installed and on PATH:
```powershell
git clone <this repo> C:\src\Behavision
cd C:\src\Behavision
powershell -ExecutionPolicy Bypass -File installer\build.ps1 -Version 0.1.0
```
It creates the venv, runs the engine test suite (a package is not worth
building if the engine is broken), freezes the engine, builds the app and the
agent, downloads the WebView2 bootstrapper, stages `dist\Behavision\`, starts
the frozen engine once to prove it runs, and compiles the installer.
`-SkipInstaller` stops after staging, for testing without Inno Setup.
### What to check on the Windows box
1. Install as an administrator. Accept the model download.
2. `C:\Program Files\Behavision\engine\behavision.exe paths` — the state root
must be `C:\ProgramData\Behavision`, not anywhere under Program Files.
3. Launch from the Start menu. **Set this PC up on its own** — no code needed.
4. Cameras → Add camera → pick the make → Test connection → Save. The feed must
appear with no restart.
5. Check `/api/health` reports `recognition_model`. On a 16 GB machine the
166 MB r50 can lose the fallback chain to the 13 MB mbf, and embeddings are
model-tagged, so which one wins decides whether a gallery carries over.
6. Sign out of the tray (Quit) — recognition must stop with it. Reboot; the app
must come back on its own.
7. Only then link it to head office, from the sidebar.
Nothing is code-signed yet, so SmartScreen will warn on first launch.
## Schema
The server applies pending migrations when it starts and refuses to run against
a schema it does not match. Three ways to look at it by hand:
```bash
export DATABASE_URL=...
./bv-server migrate -status # what is applied, adopted, pending or CHANGED
./bv-server migrate # apply everything pending
./bv-server migrate -baseline 7 # adopt a database built before tracking existed
```
The migrations are compiled into the binary, so **rebuild before migrating** —
a stale binary honestly reports "schema up to date" about files it has never
seen. Never edit an applied migration: the checksum check will refuse it by
name, and the fix is a new file.