@@ -12,13 +12,10 @@ All request/response bodies are JSON unless noted otherwise.
1212- On successful login, the server sets a signed, httpOnly cookie named
1313 ` diun_session ` (` SameSite=Lax ` , ` Secure ` when served over HTTPS,
1414 ` Max-Age ` = ` SESSION_TTL ` seconds).
15- - Protected routes (everything except ` /api/auth/login ` , ` /api/health ` , and
16- ` /api/diun/webhook ` ) require a valid ` diun_session ` cookie. If it is
17- missing, invalid, or expired, the server responds ` 401 Unauthorized ` with
15+ - Protected routes (everything except ` /api/auth/login ` and ` /api/health ` )
16+ require a valid ` diun_session ` cookie. If it is missing, invalid, or
17+ expired, the server responds ` 401 Unauthorized ` with
1818 ` { "error": "unauthorized" } ` .
19- - The Diun webhook route uses a separate auth mechanism: a static bearer
20- token (` DIUN_WEBHOOK_TOKEN ` ) in the ` Authorization ` header. It does not
21- use the session cookie.
2219
2320## Endpoints
2421
@@ -43,19 +40,20 @@ All request/response bodies are JSON unless noted otherwise.
4340- Auth: cookie (optional — never errors, reports status).
4441- Response: ` 200 { "authenticated": boolean } `
4542
46- ### ` POST /api/diun/webhook `
47-
48- - Auth: token — header ` Authorization: Bearer <DIUN_WEBHOOK_TOKEN> ` . ` 401 `
49- if missing/invalid.
50- - Body: Diun webhook payload (see below).
51- - Response: ` 204 No Content ` on successful ingest. ` 400 ` if the payload is
52- malformed.
53-
5443### ` GET /api/containers `
5544
5645- Auth: cookie.
5746- Response: ` 200 ` — array of container items (shape below).
5847
48+ ### ` GET /api/diagnostics `
49+
50+ - Auth: cookie.
51+ - Response: ` 200 { "stacks": { "stacksDir": "/opt/stacks", "mounted": true } } ` .
52+ ` mounted ` is ` false ` when the configured ` STACKS_DIR ` isn't present inside
53+ the container (the host stacks dir isn't mounted, or is mounted at a
54+ different path) — which breaks compose-based updates. The dashboard uses
55+ this to warn before an update is attempted.
56+
5957### ` POST /api/check `
6058
6159- Auth: cookie.
@@ -162,13 +160,15 @@ always returns normalized refs.
162160 "project" : " web" ,
163161 "service" : " nginx" ,
164162 "image" : " nginx:latest" ,
163+ "tag" : " latest" ,
164+ "currentVersion" : " 1.27.3" ,
165165 "currentDigest" : " sha256:..." ,
166166 "updateAvailable" : true ,
167167 "availableDigest" : " sha256:..." ,
168168 "pinned" : false ,
169169 "state" : " running" ,
170- "composeFile" : " /stacks/web/docker- compose.yml " ,
171- "workingDir" : " /stacks/web"
170+ "composeFile" : " /opt/ stacks/web/compose.yaml " ,
171+ "workingDir" : " /opt/ stacks/web"
172172}
173173```
174174
@@ -178,56 +178,30 @@ Field notes:
178178- ` project ` / ` service ` — derived from the ` com.docker.compose.project ` /
179179 ` com.docker.compose.service ` labels.
180180- ` image ` — image ref as configured (tag, not digest).
181+ - ` tag ` — the tag portion of ` image ` (e.g. ` latest ` , ` 1.27 ` ), or ` null ` if
182+ the ref is digest-pinned.
183+ - ` currentVersion ` — human-readable version from the running image's
184+ ` org.opencontainers.image.version ` label, if it sets one (else ` null ` ).
181185- ` currentDigest ` — digest of the image the running container was created
182186 from.
183- - ` updateAvailable ` — ` true ` if the most recent unresolved Diun event for
184- this image's normalized ref reports a digest different from
185- ` currentDigest ` .
187+ - ` updateAvailable ` — ` true ` if the most recent unresolved update event
188+ (from the registry check) for this image's normalized ref reports a digest
189+ different from ` currentDigest ` .
186190- ` availableDigest ` — the digest from that unresolved event, if any (else
187191 ` null ` ).
188- - ` pinned ` — ` true ` if the image ref is in the ` pinned ` table (update
189- indicator is suppressed, but manual update is still allowed).
192+ - ` pinned ` — ` true ` if the image ref is in the ` pinned ` table ("Pin Version":
193+ update indicator is suppressed and the container is grouped separately, but
194+ a manual update is still allowed).
190195- ` state ` — Docker container state (` running ` , ` exited ` , etc.).
191196- ` composeFile ` / ` workingDir ` — derived from
192197 ` com.docker.compose.project.config_files ` /
193198 ` com.docker.compose.project.working_dir ` labels; used to run `docker
194199 compose` commands for that container.
195200
196- ## Diun webhook payload
197-
198- Diun's webhook notifier posts a JSON body shaped roughly like:
199-
200- ``` json
201- {
202- "status" : " update" ,
203- "image" : " nginx:latest" ,
204- "digest" : " sha256:abc123..." ,
205- "provider" : " docker" ,
206- "hub_link" : " https://hub.docker.com/_/nginx" ,
207- "platform" : " linux/amd64" ,
208- "metadata" : {
209- "hostname" : " docker-host-1" ,
210- "container" : " nginx" ,
211- "..." : " additional Diun metadata fields"
212- }
213- }
214- ```
201+ ## Update events
215202
216- Fields we read:
217-
218- - ` status ` — ` "new" ` (first time Diun sees this image) or ` "update" ` (a
219- newer digest was found). Both are recorded; only ` "update" ` events are
220- meaningful for the update indicator.
221- - ` image ` — the image ref Diun checked, used to derive ` normalized_ref `
222- (registry/repo without tag-specific noise, used to key
223- ` update_events.normalized_ref ` ).
224- - ` digest ` — the new digest Diun observed.
225- - ` provider ` — Diun provider (` docker ` , ` swarm ` , etc.) — stored for
226- reference.
227- - ` hub_link ` — informational link, stored for reference.
228- - ` platform ` — image platform string, stored for reference.
229- - ` metadata ` — passthrough object with additional Diun-provided context;
230- stored as part of ` raw_json ` , not parsed individually.
231-
232- The full raw payload is stored as ` raw_json ` in ` update_events ` for
233- debugging/audit, regardless of which fields are explicitly parsed.
203+ ` update_events ` rows are produced solely by the active registry check
204+ (` POST /api/check ` and the background scheduler). Each records the
205+ ` normalized_ref ` and the registry-reported ` digest ` ; a row is ` resolved ` once
206+ the running container's digest matches it (the update was applied). There is
207+ no external notifier — the app queries registries directly.
0 commit comments