Files
VibeFinance/BEHEER.md
T
Jordy HoogeveenandClaude Opus 5 1c0eed61f6 Dependencies naar de nieuwste versies + update-check in de testsuite
Upgrades
- Frontend: React 19.2, Vite 8.2, @vitejs/plugin-react 6.1, ESLint 9.39
- Backend: Express 5.2, Helmet 8.3, express-rate-limit 8.7, pino 10.3,
  pino-http 11, pg 8.23, dotenv 17.4, bcryptjs 3.0, ESLint 10.9
- Lockfiles opnieuw gegenereerd (backend had er geen)

Breaking changes opgevangen
- Express 5 laat kale wildcards in routes niet toe: app.use("/api/*") is een
  prefix-mount geworden en app.get("*") pad-loze middleware
- Vite 8 bundelt met Rolldown, dat de object-vorm van manualChunks niet kent;
  omgezet naar build.rollupOptions.output.advancedChunks
- Rate-limit headers verschillen per RFC-draft; de test kijkt nu naar de hele
  RateLimit-headerfamilie in plaats van naar RateLimit-Limit
- ESLint blijft in de frontend op 9: eslint-plugin-react ondersteunt nog geen
  ESLint 10 (peer <= ^9.7)

Update-check bij het testen
- docker/check-updates.mjs vergelijkt beide package.json's met het
  npm-register; werkt zonder node_modules en zonder npm install
- test.ps1 draait dit als stap 1 van 4, met -Strict (falen) en -SkipDeps
  (offline). Ook informatief in de Test-stage van de pipeline
- Bewuste uitzonderingen met reden in docker/update-exceptions.json
- dev.ps1 up gebruikt --renew-anon-volumes, anders houdt de dev-container de
  oude node_modules na een upgrade

Overig
- ESLint flat configs voor beide packages; npm run lint werkte niet omdat er
  geen configuratie was. Beide draaien nu groen (alleen waarschuwingen over
  bestaande ongebruikte variabelen)
- README.md, BEHEER.md en Changelog.md bijgewerkt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 12:21:06 +02:00

11 KiB

VibeFinance — Beheer

De app draait in 2 containers: app (Express API + gebouwde frontend) en postgres. Eén image, één origin — geen aparte webserver en geen interne proxy.


Ontwikkeling

.\dev.ps1                      # build + start (standaard)
.\dev.ps1 build                # alleen bouwen
.\dev.ps1 up -Target app       # alleen de app herbouwen + herstarten
.\dev.ps1 up -Target postgres  # alleen de database herstarten
.\dev.ps1 logs                 # logs van de app volgen
.\dev.ps1 test                 # testsuite draaien
.\dev.ps1 down                 # stoppen én volumes wissen
.\dev.ps1 push                 # dev-image naar registry pushen

Op macOS/Linux: gebruik ./dev.sh met dezelfde argumenten.

In dev draait één container beide processen (zie docker/dev-entrypoint.sh):

Adres Wat
http://localhost Vite dev-server met hot reload
http://localhost:3001/api/health de API rechtstreeks

Vite proxyt /api naar localhost:3001 binnen dezelfde container.

⚠️ Alleen .\dev.ps1 down wist de development-database (docker compose down -v). .\dev.ps1 up doet een gewone down en laat het volume staan.


Testen

.\test.ps1              # dependency-check + backend-tests + build + smoketest
.\test.ps1 -Unit        # dependency-check + backend-tests
.\test.ps1 -NoSmoke     # zonder de stack te starten
.\test.ps1 -Strict      # faal als een dependency achterloopt
.\test.ps1 -SkipDeps    # dependency-check overslaan (bijv. offline)

Alles loopt in Docker; Node op de host is niet nodig.

Stap Wat er gebeurt
Dependency-check docker/check-updates.mjs vergelijkt package.json met het npm-register
Backend-tests Dockerfile target test → node --test in backend/test/, zonder database
Productiebuild Dockerfile target production — faalt de Vite-build, faalt deze stap
Smoketest app + postgres starten en /api/health en / opvragen

De dependency-check draait standaard bij elke testronde, dus je ziet direct of er updates open staan. Pakketten die bewust achterblijven zet je met een reden in docker/update-exceptions.json; die worden als [vast ] gemeld en laten de check niet falen. Zonder netwerk: -SkipDeps. In een CI-gate: -Strict.

De check los draaien:

docker run --rm -v ${PWD}:/repo -w /repo node:22-alpine node docker/check-updates.mjs
docker run --rm -v ${PWD}:/repo -w /repo node:22-alpine node docker/check-updates.mjs --strict

Losse backend-tests en linting in een lopende dev-container:

docker compose -f docker-compose.dev.yml exec app npm test
docker compose -f docker-compose.dev.yml exec app npm run lint
docker compose -f docker-compose.dev.yml exec -w /app/frontend app npm run lint


Release workflow

# 1. Versienummer in package.json van "x.x.x-dev" naar "x.x.x"
# 2. Changelog.md bijwerken — die sectie wordt de release-notes
# 3. Token met release-rechten zetten
$env:GITEA_TOKEN = "<token>"

.\release.ps1            # test, bouw (amd64+arm64), push, tag, Gitea-release
.\release.ps1 -DryRun    # droogloop — toont alle stappen zonder uit te voeren
.\release.ps1 -NoBuild   # sla docker build over, alleen tag + release
.\release.ps1 -SkipTests # sla de testsuite over (niet aanbevolen)

# 4. Versienummer in package.json naar "x.x.(x+1)-dev" voor volgende cyclus

Het script bouwt één image voor linux/amd64 en linux/arm64, zodat dezelfde tag op een Raspberry Pi en op een x86-server werkt.


CI/CD (Azure DevOps)

azure-pipelines.yml doet in drie stages hetzelfde als de lokale scripts:

Stage Wat
Test docker build --target test + docker run → backend-tests
Build productie-image bouwen en smoketesten tegen een postgres-container
Publish multi-arch image (amd64 + arm64) pushen naar de registry

Publish loopt alleen op main/master of een tag. Vul vóór het eerste gebruik de variabele dockerRegistryServiceConnection in met de naam van je Docker Registry service connection in Azure DevOps.


Docker

# Update via pre-built images
docker compose pull && docker compose up -d

# Reset inclusief database  ⚠️ wist alle data
docker compose down -v && docker compose up -d

PostgreSQL versie-upgrade

Bij een upgrade van PostgreSQL (bijv. 16 → 18) is de bestaande data niet compatibel. Stappen:

# 1. Backup maken
docker exec vibefinance_postgres pg_dump -U vibefinance vibefinance > backup-$(date +%F).sql

# 2. Oude containers en volumes verwijderen
docker compose down -v

# 3. Nieuwe versie starten
docker compose up -d

# 4. Backup terugzetten
docker exec -i vibefinance_postgres psql -U vibefinance -d vibefinance < backup-YYYY-MM-DD.sql

Architectuur — één app-container

De Express-app serveert zowel de API als de gebouwde frontend:

Verzoek Wat de app doet
/api/... REST API (rate limited)
/assets/... statische build uit STATIC_DIR, 1 jaar immutable gecached
al het overige index.html — fallback voor React-routing

STATIC_DIR staat standaard op /app/public; daar zet de Dockerfile de Vite-build neer. Bestaat die map niet (bijv. in dev), dan serveert de app alleen de API en logt dat bij het starten.

Ontbreekt de build in het image, dan krijg je op / een 404 en werkt alleen /api/.... Controleer dan de frontend-build stage in de Dockerfile.


Logs en diagnose

# Live logs (dev) — beide processen van de app-container
docker compose -f docker-compose.dev.yml logs -f app

# Live logs (productie)
docker compose logs -f

# Shell in de app-container (dev)
docker compose -f docker-compose.dev.yml exec app sh

# Status containers
docker compose ps

# Database inspecteren (dev)
docker exec -it vibefinance-postgres-dev psql -U vibefinance -d vibefinance

# Database inspecteren (productie)
docker exec -it vibefinance_postgres psql -U vibefinance -d vibefinance

Data persistentie

De backend slaat alle data op in PostgreSQL.

Omgeving Volume Mount pad
Productie vibefinance_pgdata /var/lib/postgresql
Development postgres_dev_data /var/lib/postgresql

PostgreSQL 18 gebruikt PGDATA=/var/lib/postgresql/18/docker. Het volume is gemount op /var/lib/postgresql zodat data bewaard blijft na een container restart.

Backup maken:

# Dev
docker exec vibefinance-postgres-dev pg_dump -U vibefinance vibefinance > backup-$(date +%F).sql

# Productie
docker exec vibefinance_postgres pg_dump -U vibefinance vibefinance > backup-$(date +%F).sql

Backup terugzetten:

# Dev
docker exec -i vibefinance-postgres-dev psql -U vibefinance -d vibefinance < backup-2026-04-08.sql

# Productie
docker exec -i vibefinance_postgres psql -U vibefinance -d vibefinance < backup-2026-04-08.sql

Gebruikersbeheer

De eerste geregistreerde gebruiker krijgt automatisch de Admin-rol. Verdere accounts kunnen via de app aangemaakt worden (Gebruikersbeheer, Admin vereist) of via de API.

Rollen:

Rol Rechten
Admin Alles, inclusief gebruikersbeheer
Bewerker Data lezen en bewerken
Viewer Alleen lezen

Productie checklist

  • POSTGRES_PASSWORD instellen op een sterk wachtwoord
  • JWT_SECRET aanpassen (genereer met openssl rand -hex 64)
  • CORS_ORIGIN instellen op je domeinnaam
  • APP_PORT aanpassen indien poort 3400 al in gebruik is
  • Testsuite groen (test.ps1 / ./test.sh)
  • TLS afhandelen via een externe reverse proxy (bijv. Nginx Proxy Manager, Caddy, Traefik)

Dependencies bijwerken

Node hoeft niet op de host te staan; de lockfiles zijn met een container bij te werken. Per map (frontend en backend):

# Laatste versies opzoeken
docker run --rm -v ${PWD}/frontend:/w -w /w node:22-alpine npm outdated

# Versies in package.json aanpassen, daarna de lockfile herschrijven
docker run --rm -v ${PWD}/frontend:/w -w /w node:22-alpine npm install --package-lock-only

Daarna altijd de testsuite draaien — die bouwt ook het productie-image, dus een kapotte upgrade valt meteen op:

.\test.ps1

En de dev-stack herbouwen. node_modules staan in anonieme volumes; zonder --renew-anon-volumes blijven de oude versies staan. .\dev.ps1 up doet dit al automatisch:

.\dev.ps1 up

Let op bij majors: eslint-plugin-react loopt achter op ESLint (peer <= ^9.7), daarom staat de frontend op ESLint 9 en de backend op 10. Express 5 vereist benoemde wildcards in routes (/api/*splat); server.js gebruikt daarom pad-loze middleware in plaats van app.get("*").


Registry

vibehoogie.duckdns.org/vibe/vibefinance-app   (frontend + backend in één image)

Tags:
  latest          productie — meest recente release
  x.x.x           productie — specifieke versie
  latest-dev      development — meest recente dev build
  x.x.x-dev       development — specifieke dev versie

Inloggen op registry:

docker login vibehoogie.duckdns.org

Update-notificaties

De app vergelijkt de draaiende versie met de laatste release op Gitea en toont dat op het belletje in de topbalk en onder "Over VibeFinance".

Hoe de check loopt

  1. De frontend vraagt /api/update-check op de eigen backend — de Gitea API stuurt geen CORS-headers, dus de browser mag die niet direct bevragen.
  2. De backend haalt releases/latest bij Gitea op en cachet het antwoord 15 minuten.
  3. De frontend kijkt bij het openen, daarna elk half uur en bij het terugkeren naar het tabblad. Alleen een écht hoger versienummer geeft een melding.

Builds met een -dev suffix melden nooit (die lopen voor op de laatste release). Wil je de melding tijdens ontwikkeling toch testen: open de app met ?updatecheck in de URL.

Configuratie

De bron staat in de root package.json:

"repository": "https://vibehoogie.duckdns.org/vibe/VibeFinance",
"updateCheckUrl": "https://vibehoogie.duckdns.org/api/v1/repos/vibe/VibeFinance/releases/latest"

dev.ps1 zet die URL als UPDATE_CHECK_URL in de omgeving; in productie komt hij uit .env (of de default in docker-compose.yml). Beschikbare backend-variabelen:

Variabele Betekenis
UPDATE_CHECK_URL Release-API die gepolld wordt. Leeg = melding uit.
UPDATE_CHECK_TOKEN Alleen nodig als de repo in Gitea niet publiek leesbaar is.

Een release publiceren

Een kale Git-tag is niet genoeg: releases/latest geeft alleen echte releases terug. release.ps1 maakt die aan (stap 4) met de changelog-sectie van die versie als release-notes. Daarvoor is een Gitea-token met release-rechten nodig:

$env:GITEA_TOKEN = "<token>"
.\release.ps1

Zonder token slaat het script die stap over met een waarschuwing — images en tag staan dan wel klaar, maar gebruikers zien geen melding tot de release bestaat.