82 Commits

Author SHA1 Message Date
kodi 94a2f4586a fix: cpu/mem container view 2026-03-27 18:23:16 +01:00
kodi 7d2f19f81f fix (containers): gebruik PODMAN_SYSTEMD_UNIT label als ground truth voor Managed By
De oude logica miste .kube quadlets volledig: het zocht alleen naar .container
bestanden op naam en gebruikte een fragiele pod-naam heuristiek als fallback.
Containers gestart via mediaserver.kube en bookstack.kube werden daardoor
als 'podman' geclassificeerd terwijl ze systemd-beheerd zijn.

PODMAN_SYSTEMD_UNIT label wordt door Podman/systemd automatisch gezet op elke
container gestart via een quadlet (.container, .kube, .pod). Dit is de enige
betrouwbare bron.

Verwijderd: _unit_is_active(), unit_active_cache, _map_pod_to_unit import.
Behouden: find_defined_containers() voor section C (offline containers) en
action routing (start/stop/restart via systemd unit).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 11:14:50 +01:00
kodi fba9b59445 docs: update documentatie voor app_volumes en tabs tree view
- CLAUDE.md: app_volumes.py in module-tabel, frontend tabs lijst, py_compile en smoke tests
- ARCHITECTURE.md: app_volumes.py in feature routers, py_compile en smoke tests
- API_GOLDEN.md: volumes endpoints gedocumenteerd (GET/POST/DELETE/prune/exists)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 18:26:08 +01:00
kodi 2dfe53895b feat (ui): compacte IDE-sidebar tree view voor Files tabblad
- Vervang kaart-stijl folder-rijen door compacte, platte rijen (2px padding, geen border)
- Verwijder badge-tellers (📁 N, 📄 N) uit folder-rijen
- Voeg .btn.tiny toe voor kleine actieknoppen (+/✕) in boom
- Alle mappen standaard ingeklapt; localStorage behoudt uitgeklapte staat
- file-entry hover highlight; verwijder bottom-border per rij

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 18:19:04 +01:00
kodi 5f6719464d fix (ui/volumes): herstel container-koppeling via inspect endpoint
containers-dashboard geeft Mounts als strings (destination paden).
Volledige mount-info (Type + Name) zit alleen in /containers/inspect/{name}.

Fix: voor containers met niet-lege Mounts parallel inspect ophalen,
daarna filteren op Type === "volume" voor named volume koppeling.

Getest: postgresdb_data → postgres-db, n8n_data → n8n.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:51:37 +01:00
kodi 249d24721c feat (ui): voeg Volumes tabblad toe aan webui
Nieuw tabblad na Images met:
- Tabel: Naam, Driver, Mountpoint (afgekapt + tooltip), Aangemaakt
  (relatieve tijd), Labels (pills), Containers (pills via Mounts koppeling)
- Toolbar: Ververs, + Volume, Prune (met bevestigingsdialoog)
- Verwijder knop per rij (uitgeschakeld als volume in gebruik)
- Create Volume modal: naam (verplicht) + labels (key=value per regel)
- Lege staat via renderStateBox

volumes.js: _volEsc() voor XSS-safe rendering, encodeURIComponent
voor onclick-handlers, parallel fetch volumes + containers-dashboard
voor container-koppeling via Mounts[].Name.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:34:29 +01:00
kodi f8bbb783b0 feat (volumes): voeg volumes router toe aan backend
Nieuw bestand control/app_volumes.py met Libpod volume operaties:
- GET  /volumes          — lijst alle volumes (optioneel ?filters=key=value)
- POST /volumes          — volume aanmaken (name, driver, labels, driverOpts)
- GET  /volumes/{name}   — details van één volume
- GET  /volumes/{name}/exists — bestaanskontrolle (204 → true, 404 → false)
- DELETE /volumes/{name} — volume verwijderen (?force=true optioneel)
- POST /volumes/prune    — ⚠️ verwijdert alle ongebruikte volumes

Filters: key=value formaat wordt automatisch omgezet naar
{"key":["value"]} JSON dat de Libpod API verwacht.

Containerfile: COPY app_volumes.py toegevoegd.
app.py: init_volumes_router geregistreerd.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 13:25:58 +01:00
kodi 4404c02967 docs: update AGENTS/SAFE_FILES/rationale na D-Bus verwijdering
- AGENTS.md: run-commando bijgewerkt (verwijder brede /run/user/1000
  mount en DBUS_SESSION_BUS_ADDRESS); notitie D-Bus niet meer vereist
- SAFE_FILES.md: verwijder DBUS_SESSION_BUS_ADDRESS; beschrijf
  concrete mounts (Podman socket + helper directory)
- podman-helper-rationale.md: daemon-reload sectie bijgewerkt —
  gaat nu via helper ipv D-Bus; samenvattingstabel gecorrigeerd

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:28:22 +01:00
kodi bae6fd8b9f docs (CLAUDE.md): documenteer health check gedrag en helper architectuur
Beschrijf dat systemd_user.reachable afgeleid is van helper.ok,
dat de container zelf geen D-Bus/systemctl aanroepen doet, en dat
alle systemctl-acties (incl. daemon-reload) via de helper-socket lopen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:54:43 +01:00
kodi ed94ee31f4 feat (helper): daemon-reload via helper; verwijder D-Bus afhankelijkheid
- podman-helper: voeg daemon-reload toe aan ALLOWED_ACTIONS; actions
  in NO_UNIT_ACTIONS slaan unit-validatie over en bouwen cmd zonder
  unit argument
- app_system: /daemon-reload endpoint gebruikt nu _helper_call in
  plaats van directe subprocess; verwijder subprocess import
- app_system: health check legt systemd_reachable af van helper_ok
  in plaats van systemctl --user list-units — de helper draait als
  host-user en impliceert systemd bereikbaarheid
- CLAUDE.md: verwijder DBUS_SESSION_BUS_ADDRESS env var; D-Bus mount
  is niet meer nodig

Deploy: kopieer podman-helper.py naar host, daemon-reload, restart
helper, rebuild backend image, herstart container zonder bus mount.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:39:10 +01:00
kodi 5196e7840f fix (helper): verplaats socket naar dedicated submap /run/podman-mvp/
Vervangt file bind-mount door directory mount om stale inode probleem
op te lossen: bij file bind-mounts bindt Podman de inode op run-tijd;
als podman-helper stopt en de socket verwijdert, wijst de container
nog steeds naar de verwijderde inode. Een directory mount lost altijd
op naar de huidige mapinhoud inclusief nieuwe inodes.

Wijzigingen:
- podman-helper.py: SOCKET_PATH → XDG_RUNTIME_DIR/podman-mvp/podman-helper.sock
- common.py: HELPER_SOCKET → /run/podman-mvp/podman-helper.sock
- CLAUDE.md: run-commando gebruikt -v /run/user/1000/podman-mvp:/run/podman-mvp

Deploy: kopieer podman-helper.py naar host, daemon-reload, restart helper,
rebuild backend image, herstart container met nieuwe mount.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:50:31 +01:00
kodi a05d79ae2c fix (helper): verwijder ExecStopPost socket cleanup
ExecStopPost=-/bin/rm -f ${XDG_RUNTIME_DIR}/podman-helper.sock verwijderde
het socketbestand bij stoppen. Hierdoor werd bij herstart een nieuw inode
aangemaakt, terwijl de container-bind-mount nog het oude inode vasthield
(stale mount). Gevolg: health check en _helper_call faalden na herstart
ook al was de helper running.

De cleanup is overbodig: podman-helper.py doet os.unlink() bij opstarten
(regel 153) en bij afsluiten via finally-block (regel 178).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 08:31:38 +01:00
kodi 5e7d1b887c feat (health): voeg helper socket check toe, drie visuele states
Backend (/api/health):
- Importeer HELPER_SOCKET uit common.py
- Voeg helper-check toe: connect() op /run/podman-helper.sock, timeout=2s
- ok blijft true als alleen de helper ontbreekt (waarschuwing, geen fout)
- Nieuwe response key: "helper": {"ok": bool}

Frontend (pingApi / setApiState):
- pingApi() roept nu /api/health aan i.p.v. /pods-dashboard
- setApiState(state, msg) accepteert 'ok' / 'warn' / 'error'
- Gele dot met --warn kleur als helper.ok=false maar core OK
- refreshActive() delegeert statusupdate aan pingApi()
- Detailbericht bij fout: toont welk component (podman/systemd) faalt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 08:06:38 +01:00
kodi e469508570 feat (docs): voeg Swagger UI toe op /docs, lokaal gebundeld
- Swagger UI v5.32.1 lokaal in assets/swagger-ui/ (geen CDN, offline bruikbaar)
- webui/html/docs/index.html: custom pagina die /api/openapi.json laadt
  met requestInterceptor zodat Try it out via same-origin werkt
- Link toegevoegd aan dashboard "Snel acties": API docs ↗ (opent in nieuw tabblad)
- Docstrings toegevoegd aan destructieve endpoints (app_containers, app_images):
  container stop/restart, image remove (batch + single), image prune
  geven nu ⚠️-waarschuwingen in de Swagger UI beschrijving
- Backend rebuild nodig voor docstrings zichtbaar in spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 07:30:51 +01:00
kodi c338955320 refactor (networks): herschrijf networks_usage, bundel D3 lokaal
- Verwijder phase-3 hex-ID fallback (~160 regels): NetworkSettings.Networks
  uit container inspect is de ground truth, niet netwerk-inspect + scannen
- Filter infra containers via IsInfra flag + naam-regex ^[0-9a-f]+-infra$
- Voeg IP en aliases toe aan byNetwork container entries (via inspect)
- Bridge containers krijgen altijd een inspect-call voor IP/aliases;
  pasta/host/none containers worden overgeslagen
- D3 v7.9.0 lokaal gebundeld (assets/js/d3.min.js, CDN-afhankelijkheid weg)
- Nieuw webui/Containerfile voor reproduceerbare webui image builds

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 16:28:39 +01:00
kodi f016c2bae0 perf: stats poll via lichtgewicht /api/stats i.p.v. /containers-dashboard
De frontend haalde CPU/mem stats op via het zware /containers-dashboard
endpoint (Podman call + os.walk + systemctl subprocesses per container).
Nu gaat de stats poll via een nieuw /api/stats endpoint dat alleen de
bestaande in-memory cache teruggeeft (<5ms vs ~400ms).

- app_containers.py: /api/stats endpoint toegevoegd (cache direct return)
- app_containers.py: _STATS_SHOWN_NAMES bijgehouden per dashboard call
  (filtert infra/management containers eruit op basis van _dashboard_source)
- containers.js: pollContainersDashboardStatsOnce() gebruikt /api/stats

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 15:09:53 +01:00
kodi e922cea167 added helper 2026-03-22 14:39:38 +01:00
kodi 7d2c205930 feat: systemd unit acties via podman-helper Unix socket
start/stop/restart van systemd units gaan nu via de host-helper
(/run/podman-helper.sock) in plaats van directe systemctl subprocess
vanuit de container. Hiermee wordt de user namespace isolatie omzeild
die D-Bus calls vanuit de container onbetrouwbaar maakt.

- common.py: _helper_call(action, unit) toegevoegd
- app_system.py: /{action}/{unit} route gebruikt helper voor start/stop/restart
- app_containers.py: container_action() gebruikt helper
- daemon-reload en is-active blijven subprocess (read-only, werkt al)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 11:24:25 +01:00
kodi 580c301718 refactor: verplaats run() duplicaat naar common.py
run() stond identiek in app.py en app_system.py. Verplaatst naar
common.py als single source of truth; beide modules importeren
nu de centrale versie.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 10:26:34 +01:00
kodi 1c61854143 fix: verwijder dode Flask-stijl legacy route in app_system.py
De route @router.post("/api/<action>/<unit>") gebruikte Flask-syntaxis
die nooit matcht in FastAPI. Dead code verwijderd.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 10:22:25 +01:00
kodi bacab3b20a fix (security): sluit path traversal in legacy /workloads/ endpoints
Drie endpoints gebruikten os.path.join zonder validatie, waardoor een
aanvaller buiten WORKLOADS_DIR kon lezen/schrijven. Vervangen door de
bestaande _files_safe_join() helper die al door alle /files/ endpoints
werd gebruikt.

Endpoints: /workloads/read/, /workloads/save-file, /workloads/deploy/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 09:52:27 +01:00
kodi 2c5cb07cdb feat (ui): exec fase 5 2026-03-06 19:55:31 +01:00
kodi 3da82255ff feat (ui): exec fase 4 2026-03-06 18:38:58 +01:00
kodi a4099867a5 feat (ui): exec fase 3 2026-03-06 18:13:55 +01:00
kodi 39a33e5711 feat (ui): exec fase 2 2026-03-06 17:25:11 +01:00
kodi 92e0e04905 feat (ui): exec fase 1 2026-03-04 16:39:41 +01:00
kodi d96fc19f41 feat (backend): exec fase 1 2026-03-04 16:33:24 +01:00
kodi 8045fdc869 feat (ui): aantal netwerken weergeven in netwerk knop in linker menu 2026-03-04 15:30:48 +01:00
kodi a1609c8ea7 Opschonen app.css: Stap 1 & 2 voltooid
Stap 1: Verwijderen ongebruikte tokens en selectors
- Ongebruikte tokens: --badge-green-*, --badge-yellow-*
- Ongebruikte selectors: .pill, .data-table, .badge-green/yellow
- Resultaat: -38 regels, lagere onderhoudslast.

Stap 2: Consolidatie en opschonen cascade
- .mapLegend volledig geconsolideerd naar één definitieve set.
- Overlappende file-row fallback verwijderd.
- Resultaat: -68 regels, cascade opgeschoond.
2026-03-04 08:13:45 +01:00
kodi 6bf30db62c feat (ui): Light/Dark Theme added Complete 2026-03-04 07:48:58 +01:00
kodi ebefd2d80c feat (ui): Light/Dark Theme added 02 2026-03-04 07:29:43 +01:00
kodi 1d5bdd5089 feat (ui): Light/Dark Theme added 2026-03-03 15:17:52 +01:00
kodi 3a80ba09af feat(ui): ondersteuning Containerfile zichtbaar in build UI
- Label aangepast naar 'Dockerfile/Containerfile'
- Picker-titel aangepast naar 'Kies Dockerfile/Containerfile'
- Default waarde van buildDockerfile input leeggemaakt
- Validatiemelding aangepast naar 'Dockerfile/Containerfile'

Geen backend- of API-wijzigingen; dockerfile blijft leidend veld.
2026-03-01 11:09:18 +01:00
kodi 417d08b162 Fix: voorkom pods uit .container workloads
/api/pods-dashboard genereerde onterecht 'pod<basename>' entries voor .container Quadlet-bestanden, wat leidde tot lege nep-pods zoals 'podn8n' in de WebUI.

Alleen echte pod-workloads (.pod, evt. .kube) mogen nog een Source:"systemd" pod-row opleveren.

Geen endpoint- of schemawijzigingen. Alleen filtering in control/app_pods.py aangepast.
2026-03-01 08:41:20 +01:00
kodi 7d84733b17 refractor: afgerond 2026-02-28 15:51:58 +01:00
kodi df2a577402 refactor(api): move system endpoints into app_system router 2026-02-28 13:00:20 +01:00
kodi 1226b0654e refactor(api): move /test-hybrid into app_system router 2026-02-28 11:58:55 +01:00
kodi e61f2ccf76 refactor(api): move /health into app_system router 2026-02-28 10:51:22 +01:00
kodi 492edc2ec0 refactor(api): remove DI callables, routers import common directly 2026-02-28 10:02:42 +01:00
kodi 61b2748854 refactor(api): introduce shared common helpers (mechanical extract) 2026-02-28 09:14:35 +01:00
kodi a8d62fa340 chore(api): remove unused imports and BASE_DIR from app.py 2026-02-28 07:41:10 +01:00
kodi 278d31b68c refactor(api): move containers endpoints and stats poller into app_containers router 2026-02-27 16:01:15 +01:00
kodi efd4fe46d7 refactor(api): move pods endpoints into app_pods router 2026-02-27 15:02:53 +01:00
kodi cab706deb2 refactor(api): move networks endpoints into app_networks router 2026-02-27 14:23:43 +01:00
kodi 3d516c96e4 refactor(api): move files/workloads endpoints into app_files router 2026-02-27 13:55:09 +01:00
kodi 65395cf7e8 chore(api): remove legacy systemd allowlist 2026-02-27 12:39:34 +01:00
kodi b21d2cb2ac refact (ui): 01 2026-02-25 18:17:08 +01:00
kodi 8e4e0067ff feat(api): add cached container cpu/mem fields on containers-dashboard 2026-02-25 14:42:03 +01:00
kodi 658e41cfba feat(dashboard): add cached cpu/mem stats fields to containers-dashboard 2026-02-25 14:10:49 +01:00
kodi b89a31a068 feat(api): Codex: add /health endpoint with podman + systemd checks 2026-02-25 13:16:53 +01:00