probe fix, the gate, and the promotion train (R-618 closed, R-630..632 opened)
gates / gates (push) Successful in 28s
gates / gates (push) Successful in 28s
Part 1: tandoor/zipline/wger probes corrected in the catalog and red-proofed live on 9202 in both directions - "Nem egeszseges" with the front door serving 200, then "Fut" after the real sync with no redeploy. tandoor's failed edge re-walked: done at +41.1s where it was failed at +361.9s. Part 2: fifteen proven versions on the live catalog, one commit per app; the guarded Update pressed on four apps on demo-hp, all four done. Opened: R-630 (paperless-ngx's probe has never run on any box - a silent absence, worse than the wrong probe that was found in one night), R-631 (five templates no static rule can judge), R-632 (28 of 53 templates never deployed by any drill). Closed: R-618. Register 318 -> 321. No product code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
# REPORT — probe fix, gate, promotion train, 2026-09-22
|
||||||
|
|
||||||
|
**The full record is `documentation/audits/PROBE-FIX-2026-09-22.md`.** This file is the session
|
||||||
|
report. The shared `REPORT.md` is deliberately not touched (two sessions in this repo clobber it).
|
||||||
|
|
||||||
|
## Not done, or changed from the brief
|
||||||
|
|
||||||
|
1. **FIFTEEN versions moved, not fourteen** — tandoor was re-walked today and became the fifteenth.
|
||||||
|
2. **I nearly dropped `nextcloud`'s MariaDB engine move on a wrong assumption.** Running
|
||||||
|
`check-engine-major.py` against that exact commit ALLOWED it by name under R-469. It moved.
|
||||||
|
Recorded as a decision the operator may reverse.
|
||||||
|
3. **The first push of the moves FAILED CI** (job 877, `15d7c2b`): no PyYAML on the runner, the new
|
||||||
|
gate answered INCONCLUSIVE. Fixed with a degraded mode + five decoys; job **878** = success.
|
||||||
|
4. **bookstack's phase trace on demo-hp is incomplete** — my own 115 s probe run pressed the Update
|
||||||
|
and timed out mid-flight. Said plainly rather than presented as a full trace.
|
||||||
|
5. **The four apps were pressed on ONE demo box, not two.** `demo-felhom` has only `opengist`
|
||||||
|
installed. I did not install four apps on it to satisfy the instruction.
|
||||||
|
|
||||||
|
**No brief claim turned out wrong.** All three probe faults were verified against the files before
|
||||||
|
any edit and all three were exactly as stated.
|
||||||
|
|
||||||
|
## What ran
|
||||||
|
|
||||||
|
- **Part 1** — the three probes fixed in one commit; red-proofed live on 9202 in **both**
|
||||||
|
directions through the product; tandoor's failed edge re-walked and now `done` at +41.1 s; a new
|
||||||
|
`--fast` catalog gate with four red-proofs and ten decoys; the never-judged templates counted.
|
||||||
|
- **Part 2** — fifteen moves, one commit per app, `catalog_since` today, all gates green, CI green
|
||||||
|
by job id; the guarded Update pressed on four apps on demo-hp, all four `done`.
|
||||||
|
|
||||||
|
## What shipped
|
||||||
|
|
||||||
|
- `app-catalog-felhom.eu` **@1ad1f34** — three probe corrections, fifteen version moves, one new
|
||||||
|
gate, `test_gate_decoys.py` 51 → 56 cases. CI job **878 = success**.
|
||||||
|
- `felhom.eu` — this report, the audit, the evidence, R-630/R-631/R-632, R-618 CLOSED, `09` §8
|
||||||
|
limitation 8, the capability map's guarded-update row, and `STATUS.md`.
|
||||||
|
- **No controller, agent or hub code.** The brief forbade it and none was needed.
|
||||||
|
|
||||||
|
## What is owed
|
||||||
|
|
||||||
|
- **What `verifying` does for a stack with no probe target** (R-630) — answerable on demo-hp, where
|
||||||
|
`paperless-ngx` is installed. Not run.
|
||||||
|
- **A live probe reading for five templates** no static rule can judge (R-631).
|
||||||
|
- **28 templates never deployed by any drill** (R-632) — the rotation's queue.
|
||||||
|
- **`vikunja` has no compose healthcheck at all**, so its probe has no oracle in either direction.
|
||||||
File diff suppressed because one or more lines are too long
@@ -1095,6 +1095,21 @@ Version strings stay in the logs, the API and the hub.
|
|||||||
name a probe the app does not answer**, so a SUCCESSFUL update of those apps ends by STOPPING
|
name a probe the app does not answer**, so a SUCCESSFUL update of those apps ends by STOPPING
|
||||||
a working app (**R-618**, P1 — tandoor measured serving HTTP 200 on the new version at four
|
a working app (**R-618**, P1 — tandoor measured serving HTTP 200 on the new version at four
|
||||||
samples across five minutes, then stopped).
|
samples across five minutes, then stopped).
|
||||||
|
**CLOSED 2026-09-22, and the closing changed the numbers above:** the three probes were
|
||||||
|
corrected (`app-catalog-felhom.eu@793c4fb`), red-proofed live on 9202 in both directions, and a
|
||||||
|
static gate now refuses a probe that does not match the same service's own compose healthcheck.
|
||||||
|
**tandoor's edge was re-walked with nothing else changed and ended `done` at +41.1 s** where it
|
||||||
|
had ended `failed` at +361.9 s — so the tally is **15 proven, 2 failed, 4 inconclusive**, and all
|
||||||
|
fifteen are on the live catalog since 2026-09-22.
|
||||||
|
**WHAT THE CLOSING FOUND, and it is the part worth carrying forward:** a wrong probe was the
|
||||||
|
LOUD failure. Two quiet ones sit beside it. `paperless-ngx` has no container whose name matches
|
||||||
|
its stack name, so `findProbeContainer` returns nothing and **its probe has never run on any box**
|
||||||
|
— an absence, with no badge to contradict it (**R-630**). And five more templates cannot be judged
|
||||||
|
statically at all, one of which (`home-assistant`) is correct only because its check type cannot
|
||||||
|
fail (**R-631**). **So "the probe is right" is now enforced for 47 of 53 templates and still
|
||||||
|
unknown for six.**
|
||||||
|
**AND THE SWEEP'S REAL CEILING, counted rather than felt: 28 of the 53 templates have never been
|
||||||
|
deployed by any drill** (**R-632**) — the widening above went from 3 apps to 21, and 21 is not 53.
|
||||||
9. **The hub does not record image tags at all.** Its report's container payload carries name, state,
|
9. **The hub does not record image tags at all.** Its report's container payload carries name, state,
|
||||||
CPU and memory, and no image field (spike §5). So the fleet view of §6 slice 7 needs a hub-side
|
CPU and memory, and no image field (spike §5). So the fleet view of §6 slice 7 needs a hub-side
|
||||||
change; it is not derivable from what is already reported.
|
change; it is not derivable from what is already reported.
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
# THE MORNING AFTER — probe fix, gate, and the promotion train, 2026-09-22
|
||||||
|
|
||||||
|
Evidence: `probe-fix-2026-09-22/`. The night this follows: `DRILL-update-night-2026-09-21.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Not done, or changed from the brief
|
||||||
|
|
||||||
|
**Read this first. Everything else in this document is a claim; this section is where the claims
|
||||||
|
are bounded.**
|
||||||
|
|
||||||
|
1. **The brief said "the fourteen proven versions". FIFTEEN moved.** The night's fourteen included
|
||||||
|
`nextcloud`'s MariaDB engine move; tandoor was re-walked today and became the fifteenth. Both are
|
||||||
|
named below with why.
|
||||||
|
|
||||||
|
2. **I nearly dropped `nextcloud`'s engine move on a wrong assumption, and the gate corrected me.**
|
||||||
|
I assumed `check-engine-major.py` would refuse `mariadb:11.6 -> 12.3` and had written it up as
|
||||||
|
"dropped, named". Running the gate against that exact commit instead of assuming it ALLOWED the
|
||||||
|
move by name, citing **R-469** (Slice 4 shipped; `MARIADB_AUTO_UPGRADE=1` is already in that
|
||||||
|
template, verified by reading it). The brief forbade **PostgreSQL** engine moves; this is MariaDB
|
||||||
|
and it was proven end to end in 217.4 s. It moved. **This is the second time in two days that
|
||||||
|
running the instrument beat reasoning about it** — see R-628.
|
||||||
|
|
||||||
|
3. **The first push of the fifteen moves FAILED CI, and I found it by checking rather than by being
|
||||||
|
told.** Job **877** on `15d7c2b` read `conclusion: failure`: the CI runner has no PyYAML and the
|
||||||
|
new gate answered INCONCLUSIVE, which the runner rightly refuses to call a pass. Fixed with a
|
||||||
|
degraded line-reader mode and five more decoy cases; job **878** on `1ad1f34` is `success`.
|
||||||
|
**The moves themselves were never in doubt — the gate that shipped beside them was.**
|
||||||
|
|
||||||
|
4. **bookstack's phase trace on demo-hp is INCOMPLETE and the reason is my own instrument.** A
|
||||||
|
115-second probe run, meant only to list which apps were installed, pressed the Update as
|
||||||
|
designed and then hit its timeout mid-update. Its phases are recorded to `+21.6 s starting`; the
|
||||||
|
rest was read off the box afterwards (`done`, pin and installed both at `26.05.5`). The second,
|
||||||
|
full run then pressed Update on an already-current app and completed in **3.1 s**, moving
|
||||||
|
nothing. That second trace is real and is reported, but it is **not** a `26.05.2 -> 26.05.5`
|
||||||
|
trace. Said here rather than presented as one.
|
||||||
|
|
||||||
|
5. **The brief asked me to "list templates the night's sweep could not judge". The honest answer
|
||||||
|
needed three categories, not one** — 20 with a verdict record, 4 deployed as props with no edge
|
||||||
|
walked, 1 deployed only to measure its probe, and **28 never deployed at all**. Filed as R-632
|
||||||
|
with the machine-readable list.
|
||||||
|
|
||||||
|
6. **Two things the brief could not have known, both found by the new gate and both left OPEN:**
|
||||||
|
`paperless-ngx`'s health probe has never run on any box (R-630), and five templates cannot be
|
||||||
|
judged by any static rule (R-631). Neither is fixed here: R-630's fix is product code or a
|
||||||
|
container rename on live boxes, and the brief forbade product code.
|
||||||
|
|
||||||
|
**One brief claim that turned out wrong:** none. All three probe faults the brief named were
|
||||||
|
verified against the files before any edit and all three were exactly as stated — tandoor's compose
|
||||||
|
line 42 dials `127.0.0.1:80/accounts/login/`, zipline's line 38 dials `/api/healthcheck`, wger's
|
||||||
|
line 42 dials `127.0.0.1:8000`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 1 — the probes
|
||||||
|
|
||||||
|
### 1.1 The fix
|
||||||
|
|
||||||
|
One commit, `app-catalog-felhom.eu@793c4fb`. No `image:` line moved, so no `catalog_since` moved.
|
||||||
|
|
||||||
|
| app | was | is | the oracle that was already in the file |
|
||||||
|
|---|---|---|---|
|
||||||
|
| tandoor | port `8080` | port `80` | `wget --spider -q http://127.0.0.1:80/accounts/login/` |
|
||||||
|
| zipline | path `/api/health` | path `/api/healthcheck` | `http.get('http://127.0.0.1:3000/api/healthcheck', …)` |
|
||||||
|
| wger | port `80` | port `8000` | `wget --spider -q http://127.0.0.1:8000` |
|
||||||
|
|
||||||
|
### 1.2 Red-proofed live on 9202, through the product, in both directions
|
||||||
|
|
||||||
|
Deployed at the **live (unfixed) pin** first. Evidence `probe-fix-2026-09-22/probe-before-observe.json`,
|
||||||
|
`front-door-before.json`, `probe-after.json`.
|
||||||
|
|
||||||
|
| | tandoor | zipline | wger |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **BEFORE — controller state** | `unhealthy` | `unhealthy` | `unhealthy` |
|
||||||
|
| **BEFORE — the app page, HU** | `Nem egészséges` | `Nem egészséges` | `Nem egészséges` |
|
||||||
|
| **BEFORE — the app page, EN** | `Not healthy` | `Not healthy` | `Not healthy` |
|
||||||
|
| **BEFORE — docker's own healthcheck** | `healthy, healthy` | `healthy, healthy` | `healthy` |
|
||||||
|
| **BEFORE — the front door, followed** | **200** `Login / Sign In` | **200** `Zipline` | **200** `wger Workout Manager` |
|
||||||
|
| **AFTER — controller state** | `running` | `running` | `running` |
|
||||||
|
| **AFTER — the app page, HU / EN** | `Fut` / `Running` | `Fut` / `Running` | `Fut` / `Running` |
|
||||||
|
|
||||||
|
The fix arrived through the **real sync**: `POST /api/sync` answered
|
||||||
|
*„Sablonok frissítve — frissítve: tandoor, wger, zipline"*, and all three read `running` at the next
|
||||||
|
poll — **no redeploy, no container restart**.
|
||||||
|
|
||||||
|
**The badge I quote is the HEALTH word, not the version badge.** The version badge reads
|
||||||
|
`Naprakész` / `Up to date` in both states and would have proved nothing; a first pass captured it
|
||||||
|
and it was corrected. The scan strips `<script>` and `<style>` first (the same page carries those
|
||||||
|
words inside a script block).
|
||||||
|
|
||||||
|
### 1.2b tandoor's edge, re-walked
|
||||||
|
|
||||||
|
Via the drill catalog (`09` §6.5 — `git.repo_url` **and** `rm -rf <data>/catalog-cache`, R-615).
|
||||||
|
Evidence `probe-fix-2026-09-22/tandoor-rerun/`.
|
||||||
|
|
||||||
|
| | 2026-09-21, before the fix | 2026-09-22, after |
|
||||||
|
|---|---|---|
|
||||||
|
| entered `verifying` | +58.4 s | **+5.2 s** |
|
||||||
|
| outcome | **`failed` at +361.9 s**, app STOPPED | **`done` at +41.1 s** |
|
||||||
|
| seed read back after | **UNUSABLE** — `No such container: tandoor` | **found = True** |
|
||||||
|
| `installed_images` | rolled back to `2.6.13` | `2.6.15` |
|
||||||
|
| containers | none | both `running`, `restarts=0` |
|
||||||
|
|
||||||
|
**Same app, same versions, same button. The only change is one port number.** tandoor's verdict
|
||||||
|
moves `failed -> proven` and it is on the live catalog.
|
||||||
|
|
||||||
|
**Teardown, stated:** `controller.yaml` restored, `git.repo_url` read back as the live catalog,
|
||||||
|
`<data>/data/catalog-cache` re-cloned from the live remote and quoted
|
||||||
|
(`probe-fix-2026-09-22/teardown-catalog-pointer.txt`), drill repo reset to the live `main`.
|
||||||
|
|
||||||
|
### 1.3 The gate
|
||||||
|
|
||||||
|
`app-catalog-felhom.eu/scripts/check-probe-matches-compose.py`, registered in `catalog_gates.py` as
|
||||||
|
a **`--fast`** row, so it runs in the pre-push hook and in CI.
|
||||||
|
|
||||||
|
**The oracle was already in every template.** The probed service's own compose `healthcheck.test`
|
||||||
|
dials the app on loopback. The gate resolves the probed service exactly as `findProbeContainer`
|
||||||
|
does (`healthprobe.go:297`) and compares.
|
||||||
|
|
||||||
|
**Two verdicts, and the narrower one is a measurement.** A wrong PORT refuses for every check type —
|
||||||
|
nothing listens, every dial is refused. A wrong PATH refuses **only** where the probe can fail on
|
||||||
|
it: `probeHTTP` calls any response healthy for `type: http`, and for `type: api` with no `expect`
|
||||||
|
block (`healthprobe.go:253-262`). So the path rule convicts `zipline` and merely warns about
|
||||||
|
`home-assistant`, whose badge is right today and breaks the day someone adds an `expect`.
|
||||||
|
|
||||||
|
**Red-proofs, four:** on the unfixed tree (`d4392e2a10f4` — the hash the brief names, and the repo's
|
||||||
|
HEAD when I started) it refuses all three; on the fixed tree it passes; a clean app given a wrong
|
||||||
|
port is refused; an `api`+`expect` probe given a wrong path is refused. Each of the three real
|
||||||
|
faults is **re-introduced by the test** rather than read off the tree, because reading them off the
|
||||||
|
tree would have gone green for the wrong reason the moment R-618 was fixed.
|
||||||
|
|
||||||
|
**Decoys, both ways, ten in total** (suite now **56 cases**): the port moved in a YAML comment;
|
||||||
|
Traefik's `loadbalancer.server.port`; a published `ports:` mapping; a NON-probed sidecar's own
|
||||||
|
healthcheck; a path mismatch on a probe that cannot fail on it; and five more with **PyYAML shadowed
|
||||||
|
out** — the mode CI actually runs — where the three faults must still be refused.
|
||||||
|
|
||||||
|
**`--root=<dir>`** exists so the suite judges its own clone. Without it every case would read
|
||||||
|
identical bytes and pass for nothing: the constant-for-measurement shape this repo's suite already
|
||||||
|
warns about.
|
||||||
|
|
||||||
|
**Run over all 53 — six WARNINGS, none a conviction and none a pass:**
|
||||||
|
|
||||||
|
| app | why no verdict |
|
||||||
|
|---|---|
|
||||||
|
| `paperless-ngx` | no container name matches the stack name — **the probe has never run** (R-630) |
|
||||||
|
| `vikunja` | the probed service has no compose healthcheck — no oracle |
|
||||||
|
| `crafty-controller`, `mealie`, `uptime-kuma` | the healthcheck runs through a python/script helper — no loopback URL to read |
|
||||||
|
| `home-assistant` | path mismatch on a probe that cannot fail on it — right today, fragile (R-631) |
|
||||||
|
|
||||||
|
### 1.4 What the night's sweep could not judge
|
||||||
|
|
||||||
|
**28 of 53 templates have never been deployed by any drill** (R-632). Full list in the register and
|
||||||
|
in `probe-fix-2026-09-22/not-judged.json`. Also: 4 were deployed as props in the bad-days legs with
|
||||||
|
no edge walked (`bentopdf`, `glance`, `uptime-kuma`, `wishlist`), and 1 only to measure its probe
|
||||||
|
(`wger`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 2 — the promotion train
|
||||||
|
|
||||||
|
### The moves
|
||||||
|
|
||||||
|
Fifteen commits, one per app, `catalog_since: "2026-09-22"` on each. Every gate run before each commit; nothing forced, nothing dropped. `check-image-resolvable.py` confirms all 18 unique pins still exist upstream.
|
||||||
|
|
||||||
|
| app | move | commit |
|
||||||
|
|---|---|---|
|
||||||
|
| `actualbudget` | 26.7.0 -> 26.9.0 | `2060032` |
|
||||||
|
| `audiobookshelf` | 2.35.1 -> 2.36.1 | `6525b8e` |
|
||||||
|
| `bookstack` | 26.05.2 -> 26.05.5 | `ac4828f` |
|
||||||
|
| `docmost` | 0.95.0 -> 0.96.0 | `6d8cd87` |
|
||||||
|
| `grafana` | 13.1.0 -> 13.2.2 | `068f445` |
|
||||||
|
| `home-assistant` | 2026.7.2 -> 2026.9.3 | `4405f12` |
|
||||||
|
| `mealie` | v3.20.1 -> v3.27.0 | `008348b` |
|
||||||
|
| `n8n` | 2.31.3 -> 2.40.5 | `4132e35` |
|
||||||
|
| `navidrome` | 0.63.2 -> 0.64.0 | `7708a04` |
|
||||||
|
| `papra` | 26.6.1 -> 26.6.2 | `e96887e` |
|
||||||
|
| `privatebin` | 2.0.5 -> 2.0.6 | `f547f16` |
|
||||||
|
| `romm` | 5.0.0 -> 5.3.0 | `15f9ebf` |
|
||||||
|
| `tandoor` | 2.6.13 -> 2.6.15 | `c3807c7` |
|
||||||
|
| `vikunja` | 2.3.0 -> 2.6.0 | `22f598b` |
|
||||||
|
| `nextcloud` | **ENGINE** `mariadb:11.6` -> `mariadb:12.3` | `39374d5` |
|
||||||
|
|
||||||
|
### The guarded Update, pressed on both demo boxes
|
||||||
|
|
||||||
|
#### `demo-hp` — https://192.168.0.138
|
||||||
|
|
||||||
|
| app | badge before (HU / EN) | phases | pin after | installed after | front-door state |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| `bookstack` | `Naprakész` / `Up to date` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +2.1s → `done` +3.1s | `lscr.io/linuxserver/bookstack:26.05.5` | `lscr.io/linuxserver/bookstack:26.05.5` | `running` |
|
||||||
|
| `docmost` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.0s → `starting` +79.0s → `verifying` +91.3s → `done` +106.6s | `docmost/docmost:0.96.0` | `docmost/docmost:0.96.0` | `running` |
|
||||||
|
| `privatebin` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +4.1s → `verifying` +5.2s → `done` +15.4s | `privatebin/pdo:2.0.6` | `privatebin/pdo:2.0.6` | `running` |
|
||||||
|
| `romm` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +13.3s → `verifying` +40.0s → `done` +74.8s | `rommapp/romm:5.3.0` | `rommapp/romm:5.3.0` | `running` |
|
||||||
|
|
||||||
|
Page after the update, as the household reads it:
|
||||||
|
|
||||||
|
- **`bookstack`** — HU: *← Alkalmazások BookStack Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Egyszerű wiki platform - polcok, könyvek, fejezetek és oldalak ~150M RAM productivity Pi k*
|
||||||
|
EN: *← Apps BookStack Running Up to date Open ↗ Log Export Settings A simple wiki platform - shelves, books, chapters and pages ~150M RAM productivity Runs on Pi Move to anoth*
|
||||||
|
- **`docmost`** — HU: *← Alkalmazások Docmost Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Modern wiki és dokumentáció platform Notion-szerű szerkesztővel ~200M RAM productivity Csak *
|
||||||
|
EN: *← Apps Docmost Running Up to date Open ↗ Log Export Settings A modern wiki and documentation platform with a Notion-like editor ~200M RAM productivity x86 only Move to an*
|
||||||
|
- **`privatebin`** — HU: *← Alkalmazások PrivateBin Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Titkosított szöveg megosztás - a szerver nem látja a tartalmat ~30M RAM security Pi kompa*
|
||||||
|
EN: *← Apps PrivateBin Running Up to date Open ↗ Log Export Settings Encrypted text sharing - the server never sees the content ~30M RAM security Runs on Pi Move to another st*
|
||||||
|
- **`romm`** — HU: *← Alkalmazások RomM Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Retró játékgyűjtemény kezelő, böngésző és lejátszó ~300M RAM media HDD szükséges Csak x86 Hova *
|
||||||
|
EN: *← Apps RomM Running Up to date Open ↗ Log Export Settings Retro game collection manager, browser and player ~300M RAM media Needs a hard drive x86 only Where do I put my *
|
||||||
|
|
||||||
|
#### `demo-felhom` — https://192.168.0.149
|
||||||
|
|
||||||
|
**Not installed on this box, so not pressed:** `bookstack`, `docmost`, `privatebin`, `romm`.
|
||||||
|
|
||||||
|
| app | badge before (HU / EN) | phases | pin after | installed after | front-door state |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
|
||||||
|
Page after the update, as the household reads it:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**The second box, honestly:** the four moved apps were pressed on **one** demo box, not two, because
|
||||||
|
they exist on only one. Both boxes are on catalog `1ad1f34`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What this leaves open
|
||||||
|
|
||||||
|
| row | what |
|
||||||
|
|---|---|
|
||||||
|
| **R-630** (new, P2) | `paperless-ngx`'s probe has never run on any box. Not fixed: both candidate fixes are product code or rename a running container on live boxes. **Not measured, and said so:** what `verifying` does for a stack with no probe target. |
|
||||||
|
| **R-631** (new, P3) | five templates no static rule can judge; `home-assistant` is right only because its check type cannot fail. |
|
||||||
|
| **R-632** (new, P3) | 28 of 53 templates have never been deployed by any drill. This is the rotation's queue. |
|
||||||
|
| **R-618** | **CLOSED** — three probes fixed, red-proofed live both ways, gate shipped with ten decoys, tandoor re-walked `failed -> proven`. |
|
||||||
|
| **R-462** | widened: the night's `14 proven / 3 failed / 4 inconclusive` becomes **15 proven / 2 failed / 4 inconclusive**, and all fifteen are now on the live catalog. |
|
||||||
|
|
||||||
|
**`unproven.py --summary` did not move:** 55 claims, 20 walked, 35 not walked — the same as
|
||||||
|
2026-08-22. Nothing here changed a claim's status; it changed the evidence behind one row of the
|
||||||
|
capability map.
|
||||||
|
|
||||||
|
## Fences
|
||||||
|
|
||||||
|
**`Peti's box` is parked and was not touched.** It receives a badge if it ever syncs and nothing
|
||||||
|
else. Nothing ran on DooPlex beyond ordinary pushes, nothing on `ep0`. `felhom-controller`,
|
||||||
|
`felhom-agent` and the hub were read only — **no product code was written.** No golden, no bake, no
|
||||||
|
vouch, no `--no-verify`, no branch. `local-lvm` untouched, no `prune`, `tester-1` never reset.
|
||||||
|
|
||||||
|
## Repository state
|
||||||
|
|
||||||
|
| repo | head | CI |
|
||||||
|
|---|---|---|
|
||||||
|
| `app-catalog-felhom.eu` | `1ad1f34` | job **878** `success` (job **877** on `15d7c2b` was `failure` — see "Not done" §3) |
|
||||||
|
| `felhom.eu` | this commit | all 16 gates green locally |
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
## Part 2 — the promotion train
|
||||||
|
|
||||||
|
### The moves
|
||||||
|
|
||||||
|
Fifteen commits, one per app, `catalog_since: "2026-09-22"` on each. Every gate run before each commit; nothing forced, nothing dropped. `check-image-resolvable.py` confirms all 18 unique pins still exist upstream.
|
||||||
|
|
||||||
|
| app | move | commit |
|
||||||
|
|---|---|---|
|
||||||
|
| `actualbudget` | 26.7.0 -> 26.9.0 | `2060032` |
|
||||||
|
| `audiobookshelf` | 2.35.1 -> 2.36.1 | `6525b8e` |
|
||||||
|
| `bookstack` | 26.05.2 -> 26.05.5 | `ac4828f` |
|
||||||
|
| `docmost` | 0.95.0 -> 0.96.0 | `6d8cd87` |
|
||||||
|
| `grafana` | 13.1.0 -> 13.2.2 | `068f445` |
|
||||||
|
| `home-assistant` | 2026.7.2 -> 2026.9.3 | `4405f12` |
|
||||||
|
| `mealie` | v3.20.1 -> v3.27.0 | `008348b` |
|
||||||
|
| `n8n` | 2.31.3 -> 2.40.5 | `4132e35` |
|
||||||
|
| `navidrome` | 0.63.2 -> 0.64.0 | `7708a04` |
|
||||||
|
| `papra` | 26.6.1 -> 26.6.2 | `e96887e` |
|
||||||
|
| `privatebin` | 2.0.5 -> 2.0.6 | `f547f16` |
|
||||||
|
| `romm` | 5.0.0 -> 5.3.0 | `15f9ebf` |
|
||||||
|
| `tandoor` | 2.6.13 -> 2.6.15 | `c3807c7` |
|
||||||
|
| `vikunja` | 2.3.0 -> 2.6.0 | `22f598b` |
|
||||||
|
| `nextcloud` | **ENGINE** `mariadb:11.6` -> `mariadb:12.3` | `39374d5` |
|
||||||
|
|
||||||
|
### The guarded Update, pressed on both demo boxes
|
||||||
|
|
||||||
|
#### `demo-hp` — https://192.168.0.138
|
||||||
|
|
||||||
|
| app | badge before (HU / EN) | phases | pin after | installed after | front-door state |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| `bookstack` | `Naprakész` / `Up to date` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +2.1s → `done` +3.1s | `lscr.io/linuxserver/bookstack:26.05.5` | `lscr.io/linuxserver/bookstack:26.05.5` | `running` |
|
||||||
|
| `docmost` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.0s → `starting` +79.0s → `verifying` +91.3s → `done` +106.6s | `docmost/docmost:0.96.0` | `docmost/docmost:0.96.0` | `running` |
|
||||||
|
| `privatebin` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +4.1s → `verifying` +5.2s → `done` +15.4s | `privatebin/pdo:2.0.6` | `privatebin/pdo:2.0.6` | `running` |
|
||||||
|
| `romm` | `Frissítés elérhető — ma` / `Update available — today` | `safety-dump` +0.0s → `pulling` +1.1s → `starting` +13.3s → `verifying` +40.0s → `done` +74.8s | `rommapp/romm:5.3.0` | `rommapp/romm:5.3.0` | `running` |
|
||||||
|
|
||||||
|
Page after the update, as the household reads it:
|
||||||
|
|
||||||
|
- **`bookstack`** — HU: *← Alkalmazások BookStack Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Egyszerű wiki platform - polcok, könyvek, fejezetek és oldalak ~150M RAM productivity Pi k*
|
||||||
|
EN: *← Apps BookStack Running Up to date Open ↗ Log Export Settings A simple wiki platform - shelves, books, chapters and pages ~150M RAM productivity Runs on Pi Move to anoth*
|
||||||
|
- **`docmost`** — HU: *← Alkalmazások Docmost Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Modern wiki és dokumentáció platform Notion-szerű szerkesztővel ~200M RAM productivity Csak *
|
||||||
|
EN: *← Apps Docmost Running Up to date Open ↗ Log Export Settings A modern wiki and documentation platform with a Notion-like editor ~200M RAM productivity x86 only Move to an*
|
||||||
|
- **`privatebin`** — HU: *← Alkalmazások PrivateBin Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Titkosított szöveg megosztás - a szerver nem látja a tartalmat ~30M RAM security Pi kompa*
|
||||||
|
EN: *← Apps PrivateBin Running Up to date Open ↗ Log Export Settings Encrypted text sharing - the server never sees the content ~30M RAM security Runs on Pi Move to another st*
|
||||||
|
- **`romm`** — HU: *← Alkalmazások RomM Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Retró játékgyűjtemény kezelő, böngésző és lejátszó ~300M RAM media HDD szükséges Csak x86 Hova *
|
||||||
|
EN: *← Apps RomM Running Up to date Open ↗ Log Export Settings Retro game collection manager, browser and player ~300M RAM media Needs a hard drive x86 only Where do I put my *
|
||||||
|
|
||||||
|
#### `demo-felhom` — https://192.168.0.149
|
||||||
|
|
||||||
|
**Not installed on this box, so not pressed:** `bookstack`, `docmost`, `privatebin`, `romm`.
|
||||||
|
|
||||||
|
| app | badge before (HU / EN) | phases | pin after | installed after | front-door state |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
|
||||||
|
Page after the update, as the household reads it:
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"demo-hp": {
|
||||||
|
"catalog_cache": "1ad1f34 gates: probe-matches-compose runs in CI's no-PyYAML mode (R-618)\norigin\thttps://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git (fetch)",
|
||||||
|
"apps": {
|
||||||
|
"bookstack": {
|
||||||
|
"deployed": true,
|
||||||
|
"state": "running",
|
||||||
|
"catalog_images": {
|
||||||
|
"bookstack": "lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"bookstack-db": "mariadb:12.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docmost": {
|
||||||
|
"deployed": true,
|
||||||
|
"state": "running",
|
||||||
|
"catalog_images": {
|
||||||
|
"docmost": "docmost/docmost:0.96.0",
|
||||||
|
"docmost-postgres": "postgres:16-alpine",
|
||||||
|
"docmost-redis": "redis:7-alpine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nextcloud": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"privatebin": {
|
||||||
|
"deployed": true,
|
||||||
|
"state": "running",
|
||||||
|
"catalog_images": {
|
||||||
|
"privatebin": "privatebin/pdo:2.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"romm": {
|
||||||
|
"deployed": true,
|
||||||
|
"state": "running",
|
||||||
|
"catalog_images": {
|
||||||
|
"romm": "rommapp/romm:5.3.0",
|
||||||
|
"romm-db": "mariadb:11.4",
|
||||||
|
"romm-redis": "redis:7-alpine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tandoor": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"zipline": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"wger": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"demo-felhom": {
|
||||||
|
"catalog_cache": "1ad1f34 gates: probe-matches-compose runs in CI's no-PyYAML mode (R-618)\norigin\thttps://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git (fetch)",
|
||||||
|
"apps": {
|
||||||
|
"bookstack": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"docmost": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"nextcloud": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"privatebin": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"romm": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"tandoor": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"zipline": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
},
|
||||||
|
"wger": {
|
||||||
|
"deployed": false,
|
||||||
|
"state": "not_deployed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
######## demo-hp
|
||||||
|
base=https://192.168.0.138 Host=felhom.enkisfelhom.hu
|
||||||
|
deployed apps: adventurelog, bentopdf, bookstack, calibre-web, docmost, kimai, opengist, paperless-ngx, privatebin, romm
|
||||||
|
will update: ['bookstack', 'docmost', 'privatebin', 'romm'] | NOT installed here: []
|
||||||
|
sync -> 200 {'ok': True, 'data': {'ok': True, 'message': 'Sablonok naprakészek — nincs változás'}, 'message': 'Sablonok naprakészek — nincs változás'}
|
||||||
|
|
||||||
|
==== bookstack
|
||||||
|
badge HU: [{'title': 'Ez az alkalmazás a legfrissebb elérhető változatot futtatja.', 'text': 'Naprakész'}]
|
||||||
|
badge EN: [{'title': 'This app is running the newest version available.', 'text': 'Up to date'}]
|
||||||
|
before: {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.5', 'bookstack-db': 'mariadb:12.3'}
|
||||||
|
+ 0.0s phase=safety-dump None
|
||||||
|
+ 1.1s phase=pulling None
|
||||||
|
+ 2.1s phase=starting None
|
||||||
|
+ 3.1s phase=done None
|
||||||
|
after : {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.5', 'bookstack-db': 'mariadb:12.3'} | installed: {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.5', 'bookstack-db': 'mariadb:12.3'}
|
||||||
|
|
||||||
|
==== docmost
|
||||||
|
badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
|
badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
|
before: {'docmost': 'docmost/docmost:0.95.0', 'docmost-postgres': 'postgres:16-alpine', 'docmost-redis': 'redis:7-alpine'}
|
||||||
|
+ 0.0s phase=safety-dump None
|
||||||
|
+ 1.0s phase=pulling None
|
||||||
|
+ 79.0s phase=starting None
|
||||||
|
+ 91.3s phase=verifying None
|
||||||
|
+ 106.6s phase=done None
|
||||||
|
after : {'docmost': 'docmost/docmost:0.96.0', 'docmost-postgres': 'postgres:16-alpine', 'docmost-redis': 'redis:7-alpine'} | installed: {'docmost': 'docmost/docmost:0.96.0', 'docmost-postgres': 'postgres:16-alpine', 'docmost-redis': 'redis:7-alpine'}
|
||||||
|
|
||||||
|
==== privatebin
|
||||||
|
badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
|
badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
|
before: {'privatebin': 'privatebin/pdo:2.0.5'}
|
||||||
|
+ 0.0s phase=safety-dump None
|
||||||
|
+ 1.1s phase=pulling None
|
||||||
|
+ 4.1s phase=starting None
|
||||||
|
+ 5.2s phase=verifying None
|
||||||
|
+ 15.4s phase=done None
|
||||||
|
after : {'privatebin': 'privatebin/pdo:2.0.6'} | installed: {'privatebin': 'privatebin/pdo:2.0.6'}
|
||||||
|
|
||||||
|
==== romm
|
||||||
|
badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
|
badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
|
before: {'romm': 'rommapp/romm:5.0.0', 'romm-db': 'mariadb:11.4', 'romm-redis': 'redis:7-alpine'}
|
||||||
|
+ 0.0s phase=safety-dump None
|
||||||
|
+ 1.1s phase=pulling None
|
||||||
|
+ 13.3s phase=starting None
|
||||||
|
+ 40.0s phase=verifying None
|
||||||
|
+ 74.8s phase=done None
|
||||||
|
after : {'romm': 'rommapp/romm:5.3.0', 'romm-db': 'mariadb:11.4', 'romm-redis': 'redis:7-alpine'} | installed: {'romm': 'rommapp/romm:5.3.0', 'romm-db': 'mariadb:11.4', 'romm-redis': 'redis:7-alpine'}
|
||||||
|
|
||||||
|
######## demo-felhom
|
||||||
|
base=https://192.168.0.149 Host=felhom.demo-felhom.eu
|
||||||
|
deployed apps: opengist
|
||||||
|
will update: [] | NOT installed here: ['bookstack', 'docmost', 'privatebin', 'romm']
|
||||||
|
sync -> 200 {'ok': True, 'data': {'ok': True, 'message': 'Sablonok naprakészek — nincs változás'}, 'message': 'Sablonok naprakészek — nincs változás'}
|
||||||
|
|
||||||
|
written demo-updates.json
|
||||||
@@ -0,0 +1,580 @@
|
|||||||
|
{
|
||||||
|
"demo-hp": {
|
||||||
|
"box": "demo-hp",
|
||||||
|
"base": "https://192.168.0.138",
|
||||||
|
"deployed": [
|
||||||
|
"adventurelog",
|
||||||
|
"bentopdf",
|
||||||
|
"bookstack",
|
||||||
|
"calibre-web",
|
||||||
|
"docmost",
|
||||||
|
"kimai",
|
||||||
|
"opengist",
|
||||||
|
"paperless-ngx",
|
||||||
|
"privatebin",
|
||||||
|
"romm"
|
||||||
|
],
|
||||||
|
"not_installed": [],
|
||||||
|
"apps": {
|
||||||
|
"bookstack": {
|
||||||
|
"badge_before_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások BookStack Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Egyszerű wiki platform - polcok, könyvek, fejezetek és oldalak ~150M RAM productivity Pi kompatibilis Áthelyezés másik t"
|
||||||
|
},
|
||||||
|
"badge_before_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps BookStack Running Up to date Open ↗ Log Export Settings A simple wiki platform - shelves, books, chapters and pages ~150M RAM productivity Runs on Pi Move to another storage You can move this a"
|
||||||
|
},
|
||||||
|
"before": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"bookstack": "lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"bookstack-db": "mariadb:12.3"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"bookstack": {
|
||||||
|
"ref": "lscr.io/linuxserver/bookstack:26.05.2",
|
||||||
|
"digest": "sha256:3db259db582808ab498d49ae96b0a63f935d9cf3635c9d5bd8b8815c6ff1f8a1",
|
||||||
|
"at": "2026-09-02T18:28:54Z"
|
||||||
|
},
|
||||||
|
"bookstack-db": {
|
||||||
|
"ref": "mariadb:12.3",
|
||||||
|
"digest": "sha256:a02fe89cb597d4375812b2eac90cf9d0775d4686daa7f7cc750ebbcad7525bbc",
|
||||||
|
"at": "2026-09-02T18:28:54Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"image: mariadb:12.3"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"bookstack|lscr.io/linuxserver/bookstack:26.05.5|running|Up 16 seconds (healthy)",
|
||||||
|
"bookstack-db|mariadb:12.3|running|Up 21 seconds (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"accepted": true,
|
||||||
|
"code": "202",
|
||||||
|
"answer": "{'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.1,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 2.1,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 3.1,
|
||||||
|
"phase": "done",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"bookstack": "lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"bookstack-db": "mariadb:12.3"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"bookstack": {
|
||||||
|
"ref": "lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"digest": "sha256:189c796273469115cf810e53f450e15b93184018e4728cd65fcaef8aa93584bc",
|
||||||
|
"at": "2026-09-22T09:05:22Z"
|
||||||
|
},
|
||||||
|
"bookstack-db": {
|
||||||
|
"ref": "mariadb:12.3",
|
||||||
|
"digest": "sha256:805c8e104bd563d5bfa24fadd3f31cd419ea859cb5277f32b5dbf2db714f9ed1",
|
||||||
|
"at": "2026-09-22T09:05:22Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: lscr.io/linuxserver/bookstack:26.05.5",
|
||||||
|
"image: mariadb:12.3"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"bookstack|lscr.io/linuxserver/bookstack:26.05.5|running|Up 21 seconds (healthy)",
|
||||||
|
"bookstack-db|mariadb:12.3|running|Up 27 seconds (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page_after_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások BookStack Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Egyszerű wiki platform - polcok, könyvek, fejezetek és oldalak ~150M RAM productivity Pi kompatibilis Áthelyezés másik t"
|
||||||
|
},
|
||||||
|
"page_after_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps BookStack Running Up to date Open ↗ Log Export Settings A simple wiki platform - shelves, books, chapters and pages ~150M RAM productivity Runs on Pi Move to another storage You can move this a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docmost": {
|
||||||
|
"badge_before_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
|
||||||
|
"text": "Frissítés elérhető — ma"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások Docmost Fut Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások Modern wiki és dokumentáció platform Notion-szerű szerkesztővel ~200M RAM productivity Csak x86 Áthelyezés m"
|
||||||
|
},
|
||||||
|
"badge_before_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "A newer version of this app is available. Select the Update button to start it.",
|
||||||
|
"text": "Update available — today"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps Docmost Running Update available — today Open ↗ Log Export Settings A modern wiki and documentation platform with a Notion-like editor ~200M RAM productivity x86 only Move to another storage Yo"
|
||||||
|
},
|
||||||
|
"before": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"docmost": "docmost/docmost:0.95.0",
|
||||||
|
"docmost-postgres": "postgres:16-alpine",
|
||||||
|
"docmost-redis": "redis:7-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"docmost": {
|
||||||
|
"ref": "docmost/docmost:0.95.0",
|
||||||
|
"digest": "sha256:41c8d777cf23c74e78f94e676aec328b7d7856f48df5e573543dac68d371e37c",
|
||||||
|
"at": "2026-09-03T00:30:36Z"
|
||||||
|
},
|
||||||
|
"docmost-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:cf78e76683b9ca8c5733cbbdce6c9262b45b6767934dd0a95e671f9a0fc20685",
|
||||||
|
"at": "2026-09-03T00:30:36Z"
|
||||||
|
},
|
||||||
|
"docmost-redis": {
|
||||||
|
"ref": "redis:7-alpine",
|
||||||
|
"digest": "sha256:ff02b58f971e7d7d156a1267e283fcbbeee91773b6aa36c49dac28ecfe28eadf",
|
||||||
|
"at": "2026-09-03T00:30:36Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: docmost/docmost:0.95.0",
|
||||||
|
"image: postgres:16-alpine",
|
||||||
|
"image: redis:7-alpine"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"docmost|docmost/docmost:0.95.0|running|Up 4 hours (healthy)",
|
||||||
|
"docmost-postgres|postgres:16-alpine|running|Up 4 hours (healthy)",
|
||||||
|
"docmost-redis|redis:7-alpine|running|Up 4 hours (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"accepted": true,
|
||||||
|
"code": "202",
|
||||||
|
"answer": "{'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.0,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 79.0,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 91.3,
|
||||||
|
"phase": "verifying",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 106.6,
|
||||||
|
"phase": "done",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"docmost": "docmost/docmost:0.96.0",
|
||||||
|
"docmost-postgres": "postgres:16-alpine",
|
||||||
|
"docmost-redis": "redis:7-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"docmost": {
|
||||||
|
"ref": "docmost/docmost:0.96.0",
|
||||||
|
"digest": "sha256:b56947fcfd08aab8fae12a377e1792784786adbf8b96e4281f14ef4fc072685a",
|
||||||
|
"at": "2026-09-22T09:07:17Z"
|
||||||
|
},
|
||||||
|
"docmost-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T09:07:17Z"
|
||||||
|
},
|
||||||
|
"docmost-redis": {
|
||||||
|
"ref": "redis:7-alpine",
|
||||||
|
"digest": "sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499",
|
||||||
|
"at": "2026-09-22T09:07:17Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: docmost/docmost:0.96.0",
|
||||||
|
"image: postgres:16-alpine",
|
||||||
|
"image: redis:7-alpine"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"docmost|docmost/docmost:0.96.0|running|Up 18 seconds (healthy)",
|
||||||
|
"docmost-postgres|postgres:16-alpine|running|Up 29 seconds (healthy)",
|
||||||
|
"docmost-redis|redis:7-alpine|running|Up 29 seconds (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page_after_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások Docmost Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Modern wiki és dokumentáció platform Notion-szerű szerkesztővel ~200M RAM productivity Csak x86 Áthelyezés másik tárhelyre"
|
||||||
|
},
|
||||||
|
"page_after_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps Docmost Running Up to date Open ↗ Log Export Settings A modern wiki and documentation platform with a Notion-like editor ~200M RAM productivity x86 only Move to another storage You can move thi"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"privatebin": {
|
||||||
|
"badge_before_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
|
||||||
|
"text": "Frissítés elérhető — ma"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások PrivateBin Fut Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások Titkosított szöveg megosztás - a szerver nem látja a tartalmat ~30M RAM security Pi kompatibilis Áthelyez"
|
||||||
|
},
|
||||||
|
"badge_before_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "A newer version of this app is available. Select the Update button to start it.",
|
||||||
|
"text": "Update available — today"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps PrivateBin Running Update available — today Open ↗ Log Export Settings Encrypted text sharing - the server never sees the content ~30M RAM security Runs on Pi Move to another storage You can mo"
|
||||||
|
},
|
||||||
|
"before": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"privatebin": "privatebin/pdo:2.0.5"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"privatebin": {
|
||||||
|
"ref": "privatebin/pdo:2.0.5",
|
||||||
|
"digest": "sha256:8a2cac16eff6caed4dc622e7b3ebd0c0ffcb28dfc0eba0b9c335636552eadac1",
|
||||||
|
"at": "2026-09-03T09:59:45Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: privatebin/pdo:2.0.5"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"privatebin|privatebin/pdo:2.0.5|running|Up 4 hours (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"accepted": true,
|
||||||
|
"code": "202",
|
||||||
|
"answer": "{'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.1,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 4.1,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 5.2,
|
||||||
|
"phase": "verifying",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 15.4,
|
||||||
|
"phase": "done",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"privatebin": "privatebin/pdo:2.0.6"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"privatebin": {
|
||||||
|
"ref": "privatebin/pdo:2.0.6",
|
||||||
|
"digest": "sha256:4c141b2326f8b353598ce9ce7507a9cfecf2dad5c60a39fea903d430e296d8f5",
|
||||||
|
"at": "2026-09-22T09:07:38Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: privatebin/pdo:2.0.6"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"privatebin|privatebin/pdo:2.0.6|running|Up 13 seconds (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page_after_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások PrivateBin Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Titkosított szöveg megosztás - a szerver nem látja a tartalmat ~30M RAM security Pi kompatibilis Áthelyezés másik tárhe"
|
||||||
|
},
|
||||||
|
"page_after_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps PrivateBin Running Up to date Open ↗ Log Export Settings Encrypted text sharing - the server never sees the content ~30M RAM security Runs on Pi Move to another storage You can move this app’s "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"romm": {
|
||||||
|
"badge_before_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
|
||||||
|
"text": "Frissítés elérhető — ma"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások RomM Fut Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások Retró játékgyűjtemény kezelő, böngésző és lejátszó ~300M RAM media HDD szükséges Csak x86 Hova tegyem a fájloka"
|
||||||
|
},
|
||||||
|
"badge_before_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "A newer version of this app is available. Select the Update button to start it.",
|
||||||
|
"text": "Update available — today"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps RomM Running Update available — today Open ↗ Log Export Settings Retro game collection manager, browser and player ~300M RAM media Needs a hard drive x86 only Where do I put my files? You reach"
|
||||||
|
},
|
||||||
|
"before": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"romm": "rommapp/romm:5.0.0",
|
||||||
|
"romm-db": "mariadb:11.4",
|
||||||
|
"romm-redis": "redis:7-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"romm": {
|
||||||
|
"ref": "rommapp/romm:5.0.0",
|
||||||
|
"digest": "sha256:91f6611eca5a4dafc4f4a1d72a1ed7dd66a11375d939f28410dc1d1de0b80b1b",
|
||||||
|
"at": "2026-09-03T09:59:45Z"
|
||||||
|
},
|
||||||
|
"romm-db": {
|
||||||
|
"ref": "mariadb:11.4",
|
||||||
|
"digest": "sha256:4f1d8d202fcf7bcb3902f63af09f9c1a050c2922a89652f22abaec0d4f015e83",
|
||||||
|
"at": "2026-09-03T09:59:45Z"
|
||||||
|
},
|
||||||
|
"romm-redis": {
|
||||||
|
"ref": "redis:7-alpine",
|
||||||
|
"digest": "sha256:ff02b58f971e7d7d156a1267e283fcbbeee91773b6aa36c49dac28ecfe28eadf",
|
||||||
|
"at": "2026-09-03T09:59:45Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: rommapp/romm:5.0.0",
|
||||||
|
"image: mariadb:11.4",
|
||||||
|
"image: redis:7-alpine"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"romm|rommapp/romm:5.0.0|running|Up 4 hours (healthy)",
|
||||||
|
"romm-db|mariadb:11.4|running|Up 4 hours (healthy)",
|
||||||
|
"romm-redis|5509c0097c60|running|Up 4 hours (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"accepted": true,
|
||||||
|
"code": "202",
|
||||||
|
"answer": "{'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.1,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 13.3,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 40.0,
|
||||||
|
"phase": "verifying",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 74.8,
|
||||||
|
"phase": "done",
|
||||||
|
"label": null,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"state": "running",
|
||||||
|
"pinned_images": {
|
||||||
|
"romm": "rommapp/romm:5.3.0",
|
||||||
|
"romm-db": "mariadb:11.4",
|
||||||
|
"romm-redis": "redis:7-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"romm": {
|
||||||
|
"ref": "rommapp/romm:5.3.0",
|
||||||
|
"digest": "sha256:dc586cb3a2c7316fcffb3dc273171b1964523f0f409e989295d26d2199df1d4e",
|
||||||
|
"at": "2026-09-22T09:08:58Z"
|
||||||
|
},
|
||||||
|
"romm-db": {
|
||||||
|
"ref": "mariadb:11.4",
|
||||||
|
"digest": "sha256:70cc072b29b4a89ae07abb2d4da2c64678a7f2dfe092751bb51c87d67dc1338b",
|
||||||
|
"at": "2026-09-22T09:08:58Z"
|
||||||
|
},
|
||||||
|
"romm-redis": {
|
||||||
|
"ref": "redis:7-alpine",
|
||||||
|
"digest": "sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499",
|
||||||
|
"at": "2026-09-22T09:08:58Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compose": [
|
||||||
|
"image: rommapp/romm:5.3.0",
|
||||||
|
"image: mariadb:11.4",
|
||||||
|
"image: redis:7-alpine"
|
||||||
|
],
|
||||||
|
"inspect": [
|
||||||
|
"romm|rommapp/romm:5.3.0|running|Up 39 seconds (healthy)",
|
||||||
|
"romm-db|mariadb:11.4|running|Up 49 seconds (healthy)",
|
||||||
|
"romm-redis|redis:7-alpine|running|Up 49 seconds (healthy)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page_after_hu": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Alkalmazások RomM Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Retró játékgyűjtemény kezelő, böngésző és lejátszó ~300M RAM media HDD szükséges Csak x86 Hova tegyem a fájlokat? Ezeket a ma"
|
||||||
|
},
|
||||||
|
"page_after_en": {
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"context": "← Apps RomM Running Up to date Open ↗ Log Export Settings Retro game collection manager, browser and player ~300M RAM media Needs a hard drive x86 only Where do I put my files? You reach these folders"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"demo-felhom": {
|
||||||
|
"box": "demo-felhom",
|
||||||
|
"base": "https://192.168.0.149",
|
||||||
|
"deployed": [
|
||||||
|
"opengist"
|
||||||
|
],
|
||||||
|
"not_installed": [
|
||||||
|
"bookstack",
|
||||||
|
"docmost",
|
||||||
|
"privatebin",
|
||||||
|
"romm"
|
||||||
|
],
|
||||||
|
"apps": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""demo.py — the guarded Update pressed on the TWO DEMO BOXES, through the product's own endpoints.
|
||||||
|
|
||||||
|
Not a harness for the scratch guest: these are the customer-shaped boxes, so this only SYNCS and
|
||||||
|
presses UPDATE on apps that are already installed. It installs nothing and removes nothing.
|
||||||
|
"""
|
||||||
|
import json, os, re, subprocess, sys, time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
SC = "/tmp/claude-1000/-mnt-5-hdd-felhom-eu-git/d029e2e6-1762-440e-956d-0760c8aea4b3/scratchpad"
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
BOXES = {
|
||||||
|
# name base url Host header ssh host vmid
|
||||||
|
"demo-hp": (None, "felhom.enkisfelhom.hu", "demo-hp", "9201"),
|
||||||
|
"demo-felhom": (None, "felhom.demo-felhom.eu", "felhom-pve", "9201"),
|
||||||
|
}
|
||||||
|
APPS = ["bookstack", "docmost", "privatebin", "romm"]
|
||||||
|
|
||||||
|
|
||||||
|
def sh(a, timeout=300, inp=None):
|
||||||
|
return subprocess.run(a, capture_output=True, text=True, timeout=timeout, input=inp)
|
||||||
|
|
||||||
|
|
||||||
|
class Box:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
base, host, sshh, vmid = BOXES[name]
|
||||||
|
self.host, self.ssh, self.vmid = host, sshh, vmid
|
||||||
|
self.base = base or self.guest_ip()
|
||||||
|
self.sess = self.csrf = None
|
||||||
|
|
||||||
|
def guest_ip(self):
|
||||||
|
r = sh(["ssh", "-o", "ConnectTimeout=15", self.ssh,
|
||||||
|
f"LC_ALL=C pct exec {self.vmid} -- hostname -I"], timeout=60)
|
||||||
|
ip = (r.stdout or "").split()
|
||||||
|
if not ip:
|
||||||
|
raise SystemExit(f"{self.name}: no guest IP ({r.stderr[:200]})")
|
||||||
|
return "https://" + ip[0]
|
||||||
|
|
||||||
|
def guest(self, script):
|
||||||
|
r = sh(["ssh", "-o", "ConnectTimeout=15", self.ssh,
|
||||||
|
f"LC_ALL=C pct exec {self.vmid} -- bash -s"], timeout=600, inp=script)
|
||||||
|
return (r.stdout or "") + (r.stderr or "")
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
pw = open(f"{SC}/.ctlpw").read().strip()
|
||||||
|
r = sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", f"Host: {self.host}",
|
||||||
|
"-X", "POST", "--data-urlencode", f"password={pw}", f"{self.base}/login"])
|
||||||
|
m = re.search(r"felhom_session=[A-Za-z0-9._-]+", r.stdout or "", re.I)
|
||||||
|
if not m:
|
||||||
|
raise SystemExit(f"{self.name}: login failed (no session cookie)")
|
||||||
|
self.sess = m.group(0)
|
||||||
|
r = sh(["curl", "-sk", "-L", "-H", f"Host: {self.host}", "-H", f"Cookie: {self.sess}",
|
||||||
|
f"{self.base}/"])
|
||||||
|
c = re.search(r'<meta name="csrf-token" content="([^"]+)"', r.stdout or "")
|
||||||
|
if not c:
|
||||||
|
raise SystemExit(f"{self.name}: login failed (no csrf token)")
|
||||||
|
self.csrf = c.group(1)
|
||||||
|
|
||||||
|
def ctl(self, method, path, data=None):
|
||||||
|
for attempt in range(2):
|
||||||
|
args = ["curl", "-sk", "-H", f"Host: {self.host}", "-H", f"Cookie: {self.sess}",
|
||||||
|
"-w", "\n%{http_code}"]
|
||||||
|
if method != "GET":
|
||||||
|
args += ["-H", f"X-CSRF-Token: {self.csrf}", "-H", "Content-Type: application/json",
|
||||||
|
"-X", method]
|
||||||
|
if data is not None:
|
||||||
|
args += ["--data", json.dumps(data)]
|
||||||
|
args.append(f"{self.base}{path}")
|
||||||
|
r = sh(args)
|
||||||
|
body, _, code = (r.stdout or "").rpartition("\n")
|
||||||
|
if code.strip() in ("302", "401") and attempt == 0:
|
||||||
|
self.login()
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
return code.strip(), json.loads(body)
|
||||||
|
except Exception:
|
||||||
|
return code.strip(), {"_raw": body[:600]}
|
||||||
|
|
||||||
|
def page(self, path):
|
||||||
|
r = sh(["curl", "-sk", "-H", f"Host: {self.host}", "-H", f"Cookie: {self.sess}",
|
||||||
|
f"{self.base}{path}"])
|
||||||
|
return r.stdout or ""
|
||||||
|
|
||||||
|
def stack(self, n):
|
||||||
|
_, d = self.ctl("GET", f"/api/stacks/{n}")
|
||||||
|
return (d.get("data") or {}) if isinstance(d, dict) else {}
|
||||||
|
|
||||||
|
|
||||||
|
def badge(box, app, lang_suffix=""):
|
||||||
|
h = box.page(f"/apps/{app}{lang_suffix}")
|
||||||
|
h = re.sub(r"<script.*?</script>|<style.*?</style>", "", h, flags=re.S)
|
||||||
|
m = re.findall(r'<span class="tag tag-[^"]*"[^>]*title="([^"]*)"[^>]*>([^<]*)<', h)
|
||||||
|
txt = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", h))
|
||||||
|
i = txt.find("←")
|
||||||
|
return {"tags": [{"title": a.strip(), "text": b.strip()} for a, b in m][:3],
|
||||||
|
"context": txt[i:i + 200] if i >= 0 else None}
|
||||||
|
|
||||||
|
|
||||||
|
def observables(box, app):
|
||||||
|
st = box.stack(app)
|
||||||
|
ac = st.get("app_config") or {}
|
||||||
|
comp = box.guest(f"grep -h 'image:' /opt/docker/stacks/{app}/docker-compose.yml 2>/dev/null")
|
||||||
|
insp = box.guest("docker ps -a --format '{{.Names}}|{{.Image}}|{{.State}}|{{.Status}}' "
|
||||||
|
f"| grep '^{app}'")
|
||||||
|
return {"state": st.get("state"), "pinned_images": ac.get("pinned_images"),
|
||||||
|
"installed_images": ac.get("installed_images"),
|
||||||
|
"compose": [l.strip() for l in comp.strip().split("\n") if l.strip()],
|
||||||
|
"inspect": [l for l in insp.strip().split("\n") if l.strip()]}
|
||||||
|
|
||||||
|
|
||||||
|
def press(box, app, cap_s=1800):
|
||||||
|
code, d = box.ctl("POST", f"/api/stacks/{app}/update")
|
||||||
|
t0 = time.time()
|
||||||
|
phases, last = [], None
|
||||||
|
if code != "202":
|
||||||
|
return {"accepted": False, "code": code, "answer": str(d)[:300], "phases": []}
|
||||||
|
while time.time() - t0 < cap_s:
|
||||||
|
st = box.stack(app)
|
||||||
|
u = st.get("update") or st.get("update_status") or {}
|
||||||
|
ph = u.get("phase") or st.get("update_phase")
|
||||||
|
if ph and ph != last:
|
||||||
|
phases.append({"t": round(time.time() - t0, 1), "phase": ph,
|
||||||
|
"label": u.get("label") or u.get("message"),
|
||||||
|
"error": u.get("error"), "hold": u.get("hold_message")})
|
||||||
|
last = ph
|
||||||
|
print(" +%7.1fs phase=%s %s" % (phases[-1]["t"], ph, phases[-1]["label"]),
|
||||||
|
flush=True)
|
||||||
|
if ph in ("done", "failed"):
|
||||||
|
break
|
||||||
|
time.sleep(1.0)
|
||||||
|
return {"accepted": True, "code": code, "answer": str(d)[:200], "phases": phases}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
only = sys.argv[1:] or list(BOXES)
|
||||||
|
out = {}
|
||||||
|
for name in only:
|
||||||
|
print(f"\n######## {name}")
|
||||||
|
b = Box(name)
|
||||||
|
print(f" base={b.base} Host={b.host}")
|
||||||
|
b.login()
|
||||||
|
code, d = b.ctl("GET", "/api/stacks")
|
||||||
|
installed = [s["name"] for s in (d.get("data") or []) if s.get("deployed")]
|
||||||
|
print(" deployed apps:", ", ".join(sorted(installed)))
|
||||||
|
todo = [a for a in APPS if a in installed]
|
||||||
|
missing = [a for a in APPS if a not in installed]
|
||||||
|
print(" will update:", todo, "| NOT installed here:", missing)
|
||||||
|
code, d = b.ctl("POST", "/api/sync")
|
||||||
|
print(" sync ->", code, str(d)[:180])
|
||||||
|
time.sleep(3)
|
||||||
|
b.ctl("POST", "/api/stacks/rescan")
|
||||||
|
time.sleep(3)
|
||||||
|
rec = {"box": name, "base": b.base, "deployed": sorted(installed),
|
||||||
|
"not_installed": missing, "apps": {}}
|
||||||
|
for app in todo:
|
||||||
|
print(f"\n ==== {app}")
|
||||||
|
before = observables(b, app)
|
||||||
|
bhu, ben = badge(b, app), badge(b, app, "?lang=en")
|
||||||
|
print(" badge HU:", bhu["tags"])
|
||||||
|
print(" badge EN:", ben["tags"])
|
||||||
|
print(" before:", before["pinned_images"])
|
||||||
|
r = press(b, app)
|
||||||
|
after = observables(b, app)
|
||||||
|
print(" after :", after["pinned_images"], "| installed:",
|
||||||
|
{k: (v or {}).get("ref") for k, v in (after["installed_images"] or {}).items()})
|
||||||
|
phu, pen = badge(b, app), badge(b, app, "?lang=en")
|
||||||
|
rec["apps"][app] = {"badge_before_hu": bhu, "badge_before_en": ben,
|
||||||
|
"before": before, "update": r, "after": after,
|
||||||
|
"page_after_hu": phu, "page_after_en": pen}
|
||||||
|
out[name] = rec
|
||||||
|
json.dump(out, open(os.path.join(HERE, "demo-updates.json"), "w"),
|
||||||
|
ensure_ascii=False, indent=2)
|
||||||
|
print("\nwritten demo-updates.json")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"tandoor": {
|
||||||
|
"code": "200",
|
||||||
|
"bytes": 4981,
|
||||||
|
"first200chars": "Login Sign In Username * Password * Forgot your password? Remember Me Sign In"
|
||||||
|
},
|
||||||
|
"zipline": {
|
||||||
|
"code": "200",
|
||||||
|
"bytes": 6405,
|
||||||
|
"first200chars": "Zipline"
|
||||||
|
},
|
||||||
|
"wger": {
|
||||||
|
"code": "200",
|
||||||
|
"bytes": 52291,
|
||||||
|
"first200chars": ". --> wger Workout Manager - Features Contact Exercises Mobile app Donate Develop Community Login Register Track your way to your ideal body Join wger, the community-driven free and open-source fitnes"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate Part 2 of the report FROM the evidence file, so the table cannot drift from it."""
|
||||||
|
import json, io, os
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
d = json.load(open(os.path.join(HERE, "demo-updates.json"), encoding="utf-8"))
|
||||||
|
mv = json.load(open(os.path.join(HERE, "moves.json"), encoding="utf-8"))
|
||||||
|
|
||||||
|
out = []
|
||||||
|
out.append("## Part 2 — the promotion train\n")
|
||||||
|
out.append("### The moves\n")
|
||||||
|
out.append("Fifteen commits, one per app, `catalog_since: \"%s\"` on each. Every gate run before "
|
||||||
|
"each commit; nothing forced, nothing dropped. `check-image-resolvable.py` confirms all "
|
||||||
|
"18 unique pins still exist upstream.\n" % mv["catalog_since"])
|
||||||
|
out.append("| app | move | commit |")
|
||||||
|
out.append("|---|---|---|")
|
||||||
|
for app, human, h in mv["moved"]:
|
||||||
|
out.append("| `%s` | %s | `%s` |" % (app, human, h))
|
||||||
|
out.append("| `nextcloud` | **ENGINE** `mariadb:11.6` -> `mariadb:12.3` | `39374d5` |")
|
||||||
|
out.append("")
|
||||||
|
out.append("### The guarded Update, pressed on both demo boxes\n")
|
||||||
|
|
||||||
|
for box, rec in d.items():
|
||||||
|
out.append("#### `%s` — %s\n" % (box, rec["base"]))
|
||||||
|
if rec["not_installed"]:
|
||||||
|
out.append("**Not installed on this box, so not pressed:** %s.\n"
|
||||||
|
% ", ".join("`%s`" % a for a in rec["not_installed"]))
|
||||||
|
out.append("| app | badge before (HU / EN) | phases | pin after | installed after | front-door state |")
|
||||||
|
out.append("|---|---|---|---|---|---|")
|
||||||
|
for app, a in rec["apps"].items():
|
||||||
|
bh = "; ".join(t["text"] for t in a["badge_before_hu"]["tags"]) or "—"
|
||||||
|
be = "; ".join(t["text"] for t in a["badge_before_en"]["tags"]) or "—"
|
||||||
|
ph = " → ".join("`%s` +%.1fs" % (p["phase"], p["t"]) for p in a["update"]["phases"]) or "—"
|
||||||
|
pin = (a["after"]["pinned_images"] or {}).get(app, "—")
|
||||||
|
ins = ((a["after"]["insta" "lled_images"] or {}).get(app) or {}).get("ref", "—")
|
||||||
|
st = a["after"]["state"]
|
||||||
|
out.append("| `%s` | `%s` / `%s` | %s | `%s` | `%s` | `%s` |" % (app, bh, be, ph, pin, ins, st))
|
||||||
|
out.append("")
|
||||||
|
out.append("Page after the update, as the household reads it:\n")
|
||||||
|
for app, a in rec["apps"].items():
|
||||||
|
hu = (a["page_after_hu"]["context"] or "").strip()
|
||||||
|
en = (a["page_after_en"]["context"] or "").strip()
|
||||||
|
out.append("- **`%s`** — HU: *%s*" % (app, hu[:170]))
|
||||||
|
out.append(" EN: *%s*" % en[:170])
|
||||||
|
out.append("")
|
||||||
|
|
||||||
|
io.open(os.path.join(HERE, "PART2.md"), "w", encoding="utf-8").write("\n".join(out) + "\n")
|
||||||
|
print("\n".join(out)[:1500])
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"moved": [
|
||||||
|
[
|
||||||
|
"actualbudget",
|
||||||
|
"26.7.0 -> 26.9.0",
|
||||||
|
"2060032"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"audiobookshelf",
|
||||||
|
"2.35.1 -> 2.36.1",
|
||||||
|
"6525b8e"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"bookstack",
|
||||||
|
"26.05.2 -> 26.05.5",
|
||||||
|
"ac4828f"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"docmost",
|
||||||
|
"0.95.0 -> 0.96.0",
|
||||||
|
"6d8cd87"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"grafana",
|
||||||
|
"13.1.0 -> 13.2.2",
|
||||||
|
"068f445"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"home-assistant",
|
||||||
|
"2026.7.2 -> 2026.9.3",
|
||||||
|
"4405f12"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"mealie",
|
||||||
|
"v3.20.1 -> v3.27.0",
|
||||||
|
"008348b"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"n8n",
|
||||||
|
"2.31.3 -> 2.40.5",
|
||||||
|
"4132e35"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"navidrome",
|
||||||
|
"0.63.2 -> 0.64.0",
|
||||||
|
"7708a04"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"papra",
|
||||||
|
"26.6.1 -> 26.6.2",
|
||||||
|
"e96887e"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"privatebin",
|
||||||
|
"2.0.5 -> 2.0.6",
|
||||||
|
"f547f16"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"romm",
|
||||||
|
"5.0.0 -> 5.3.0",
|
||||||
|
"15f9ebf"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"tandoor",
|
||||||
|
"2.6.13 -> 2.6.15",
|
||||||
|
"c3807c7"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"vikunja",
|
||||||
|
"2.3.0 -> 2.6.0",
|
||||||
|
"22f598b"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"dropped": [],
|
||||||
|
"catalog_since": "2026-09-22"
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"total": 53,
|
||||||
|
"with_verdict_record": [
|
||||||
|
"actualbudget",
|
||||||
|
"adventurelog",
|
||||||
|
"audiobookshelf",
|
||||||
|
"bookstack",
|
||||||
|
"docmost",
|
||||||
|
"gitea",
|
||||||
|
"grafana",
|
||||||
|
"home-assistant",
|
||||||
|
"mealie",
|
||||||
|
"n8n",
|
||||||
|
"navidrome",
|
||||||
|
"nextcloud",
|
||||||
|
"opengist",
|
||||||
|
"papra",
|
||||||
|
"privatebin",
|
||||||
|
"romm",
|
||||||
|
"tandoor",
|
||||||
|
"vaultwarden",
|
||||||
|
"vikunja",
|
||||||
|
"zipline"
|
||||||
|
],
|
||||||
|
"deployed_as_prop_no_edge": [
|
||||||
|
"bentopdf",
|
||||||
|
"glance",
|
||||||
|
"uptime-kuma",
|
||||||
|
"wishlist"
|
||||||
|
],
|
||||||
|
"deployed_for_probe_only": [
|
||||||
|
"wger"
|
||||||
|
],
|
||||||
|
"never_deployed": [
|
||||||
|
"calcom",
|
||||||
|
"calibre-web",
|
||||||
|
"claper",
|
||||||
|
"code-server",
|
||||||
|
"crafty-controller",
|
||||||
|
"emby",
|
||||||
|
"ghost",
|
||||||
|
"gokapi",
|
||||||
|
"gramps-web",
|
||||||
|
"homebox",
|
||||||
|
"homepage",
|
||||||
|
"immich",
|
||||||
|
"jellyfin",
|
||||||
|
"kimai",
|
||||||
|
"komga",
|
||||||
|
"onlyoffice",
|
||||||
|
"outline",
|
||||||
|
"paperless-ngx",
|
||||||
|
"plant-it",
|
||||||
|
"plex",
|
||||||
|
"radarr",
|
||||||
|
"rallly",
|
||||||
|
"recipe-importer",
|
||||||
|
"seerr",
|
||||||
|
"sonarr",
|
||||||
|
"sparkyfitness",
|
||||||
|
"termix",
|
||||||
|
"wanderer"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:51:05Z",
|
||||||
|
"tag": "after",
|
||||||
|
"app": "tandoor",
|
||||||
|
"controller_state": "running",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": {
|
||||||
|
"ref": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"digest": "sha256:f6c58afdea7a721d079ebd6ee5483f2c9da77dd1e709e16d60a82c218e80a451",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
},
|
||||||
|
"tandoor-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "200",
|
||||||
|
"front_door_bytes": 4981,
|
||||||
|
"docker_health": "healthy\nhealthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Fut",
|
||||||
|
"hu_context": "← Alkalmazások Tandoor Recipes Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az adatai",
|
||||||
|
"en": "Running",
|
||||||
|
"en_context": "← Apps Tandoor Recipes Running Up to date Open ↗ Log Export Settings A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another connected"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:51:08Z",
|
||||||
|
"tag": "after",
|
||||||
|
"app": "zipline",
|
||||||
|
"controller_state": "running",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"zipline": "ghcr.io/diced/zipline:4.6.1",
|
||||||
|
"zipline-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"zipline": {
|
||||||
|
"ref": "ghcr.io/diced/zipline:4.6.1",
|
||||||
|
"digest": "sha256:b8babbbcf4fef89c0c620e0539a47d908c750c251614309a7662ea4d8a7f501f",
|
||||||
|
"at": "2026-09-22T08:39:28Z"
|
||||||
|
},
|
||||||
|
"zipline-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T08:39:28Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "301",
|
||||||
|
"front_door_bytes": 0,
|
||||||
|
"docker_health": "healthy\nhealthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Fut",
|
||||||
|
"hu_context": "← Alkalmazások Zipline Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Screenshot és fájlmegosztó szerver ShareX/Flameshot integrációval ~100M RAM files Csak x86 Áthelyezés másik tárhelyre Ennek az alkalmazásnak a",
|
||||||
|
"en": "Running",
|
||||||
|
"en_context": "← Apps Zipline Running Up to date Open ↗ Log Export Settings A screenshot and file sharing server that works with ShareX/Flameshot ~100M RAM files x86 only Move to another storage You can move this app’s data to another "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:51:10Z",
|
||||||
|
"tag": "after",
|
||||||
|
"app": "wger",
|
||||||
|
"controller_state": "running",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"wger": "wger/server:2.6"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"wger": {
|
||||||
|
"ref": "wger/server:2.6",
|
||||||
|
"digest": "sha256:997ead43aabdcd67d054f933e07d2b23875f01bf43271a267cb7796925ca27c4",
|
||||||
|
"at": "2026-09-22T08:44:57Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "302",
|
||||||
|
"front_door_bytes": 0,
|
||||||
|
"docker_health": "healthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Fut",
|
||||||
|
"hu_context": "← Alkalmazások wger Fut Naprakész Megnyitás ↗ Napló Exportálás Beállítások Edzésnapló - edzéstervek, haladás követés és testsúly napló ~100M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az a",
|
||||||
|
"en": "Running",
|
||||||
|
"en_context": "← Apps wger Running Up to date Open ↗ Log Export Settings A workout log - training plans, progress and a weight diary ~100M RAM home Runs on Pi Move to another storage You can move this app’s data to another connected st"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:48:49Z",
|
||||||
|
"tag": "before-observe",
|
||||||
|
"app": "tandoor",
|
||||||
|
"controller_state": "unhealthy",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": {
|
||||||
|
"ref": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"digest": "sha256:f6c58afdea7a721d079ebd6ee5483f2c9da77dd1e709e16d60a82c218e80a451",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
},
|
||||||
|
"tandoor-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "200",
|
||||||
|
"front_door_bytes": 4981,
|
||||||
|
"docker_health": "healthy\nhealthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Nem egészséges",
|
||||||
|
"hu_context": "← Alkalmazások Tandoor Recipes Nem egészséges Naprakész Megnyitás ↗ Napló Exportálás Beállítások Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásna",
|
||||||
|
"en": "Not healthy",
|
||||||
|
"en_context": "← Apps Tandoor Recipes Not healthy Up to date Open ↗ Log Export Settings A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another conne"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:48:51Z",
|
||||||
|
"tag": "before-observe",
|
||||||
|
"app": "zipline",
|
||||||
|
"controller_state": "unhealthy",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"zipline": "ghcr.io/diced/zipline:4.6.1",
|
||||||
|
"zipline-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"zipline": {
|
||||||
|
"ref": "ghcr.io/diced/zipline:4.6.1",
|
||||||
|
"digest": "sha256:b8babbbcf4fef89c0c620e0539a47d908c750c251614309a7662ea4d8a7f501f",
|
||||||
|
"at": "2026-09-22T08:39:28Z"
|
||||||
|
},
|
||||||
|
"zipline-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T08:39:28Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "301",
|
||||||
|
"front_door_bytes": 0,
|
||||||
|
"docker_health": "healthy\nhealthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Nem egészséges",
|
||||||
|
"hu_context": "← Alkalmazások Zipline Nem egészséges Naprakész Megnyitás ↗ Napló Exportálás Beállítások Screenshot és fájlmegosztó szerver ShareX/Flameshot integrációval ~100M RAM files Csak x86 Áthelyezés másik tárhelyre Ennek az alka",
|
||||||
|
"en": "Not healthy",
|
||||||
|
"en_context": "← Apps Zipline Not healthy Up to date Open ↗ Log Export Settings A screenshot and file sharing server that works with ShareX/Flameshot ~100M RAM files x86 only Move to another storage You can move this app’s data to anot"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:48:54Z",
|
||||||
|
"tag": "before-observe",
|
||||||
|
"app": "wger",
|
||||||
|
"controller_state": "unhealthy",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"wger": "wger/server:2.6"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"wger": {
|
||||||
|
"ref": "wger/server:2.6",
|
||||||
|
"digest": "sha256:997ead43aabdcd67d054f933e07d2b23875f01bf43271a267cb7796925ca27c4",
|
||||||
|
"at": "2026-09-22T08:44:57Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "302",
|
||||||
|
"front_door_bytes": 0,
|
||||||
|
"docker_health": "healthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Nem egészséges",
|
||||||
|
"hu_context": "← Alkalmazások wger Nem egészséges Naprakész Megnyitás ↗ Napló Exportálás Beállítások Edzésnapló - edzéstervek, haladás követés és testsúly napló ~100M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalma",
|
||||||
|
"en": "Not healthy",
|
||||||
|
"en_context": "← Apps wger Not healthy Up to date Open ↗ Log Export Settings A workout log - training plans, progress and a weight diary ~100M RAM home Runs on Pi Move to another storage You can move this app’s data to another connecte"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"when": "2026-09-22T08:46:38Z",
|
||||||
|
"tag": "before",
|
||||||
|
"app": "tandoor",
|
||||||
|
"controller_state": "unhealthy",
|
||||||
|
"deployed": true,
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": {
|
||||||
|
"ref": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"digest": "sha256:f6c58afdea7a721d079ebd6ee5483f2c9da77dd1e709e16d60a82c218e80a451",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
},
|
||||||
|
"tandoor-postgres": {
|
||||||
|
"ref": "postgres:16-alpine",
|
||||||
|
"digest": "sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea",
|
||||||
|
"at": "2026-09-22T08:38:25Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"front_door_rc": 0,
|
||||||
|
"front_door_code": "200",
|
||||||
|
"front_door_bytes": 4981,
|
||||||
|
"docker_health": "healthy\nhealthy",
|
||||||
|
"version_badge": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"health_word": {
|
||||||
|
"hu": "Nem egészséges",
|
||||||
|
"hu_context": "← Alkalmazások Tandoor Recipes Nem egészséges Naprakész Megnyitás ↗ Napló Exportálás Beállítások Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásna",
|
||||||
|
"en": null,
|
||||||
|
"en_context": "← Apps Tandoor Recipes Not healthy Up to date Open ↗ Log Export Settings A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another conne"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,509 @@
|
|||||||
|
tandoor-postgres |
|
||||||
|
tandoor-postgres | PostgreSQL Database directory appears to contain a database; Skipping initialization
|
||||||
|
tandoor-postgres |
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: starting PostgreSQL 16.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: listening on IPv6 address "::", port 5432
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.867 CEST [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.880 CEST [29] LOG: database system was shut down at 2026-09-22 10:53:09 CEST
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.895 CEST [1] LOG: database system is ready to accept connections
|
||||||
|
tandoor | Deleting 'vue3/assets/pt_BR-tNFhL9ci.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.3796d8a521cf.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealTypeEditor-DAAKjxZB.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/sl-Nkic6vBb.c6ce1eb24108.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/nl-DIqabTrY.fcf6d7b2df13.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitEditor-54HrDOhT.9040eae92234.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FoodEditor-BR-tK8Pr.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/forwardRefs-DVyU53sF.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ca-C5QQCa9o.ff6e54a70768.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/KeywordsBar-BwJ0lEDV.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.c46924a2b9d5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-CKBxglwy.b98729efffd0.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/goto-DubWlX_o.0c25d7a8f5fa.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-CKBxglwy.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lv-BUrQRxBI.8efc7d113546.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.4d7347e87897.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Djsboh2v.92774fc66b84.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditor-DK6Qeffb.864b139cbb79.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelDeletePage-C4id8-tu.1ed7ee64e600.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/da-DHqdZ4yZ.197be8016aca.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ro-CG_JGo0i.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ExportDataSettings-BlFk8Tn-.6ccf02326ec4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.16f243b74d54.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeImportPage-DBKJ6DXr.a23aec8a9383.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.08d7c47f5d2b.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BY3ErEFj.457b3d77074e.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.b663eac25ee4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTimePicker-DNtQ2GaY.658bf461867a.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.d7c2e31a63b7.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.4ed293ceaca9.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.aa9eb5c590ab.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryLocationEditor-DIxi9S-h.5de878ee0a17.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/StartPage-0ugVot93.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-Brwft-8t.d570ceeec9ef.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.7c8b48842426.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccountSettings-BHfX12gt.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/lt-SI6E7sY1.2560d8a9d387.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/de-5mnKTxw2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-B1X0PDnA.068ca2b316db.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditor-DK6Qeffb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-CcFlDNPw.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.6b450d3cfcd0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.fe7085369993.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VStepper-lk6OG_fY.23af7e185e38.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.2642c051884b.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.e4b532c48301.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt-CXzOqbUC.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BooksPage-Dh8_wlv_.cb4aba43024a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelListPage-xoBv_A6i.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FdcSearchDialog-BvpKKey4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.7195d47ccd52.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/model_utils-a_hMB_Qu.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/useFileApi-BD_kCiAS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/he-DxNGVUQd.79ff03f4063a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/zh_Hant-CERwsE1Q.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchPage-BQ1P-4y8.ba1f4c8767b9.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryLocationEditor-DIxi9S-h.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fi-BLW_HATq.078772422941.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/nn-CkCilbi1.ccb3acb89917.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/useFileApi-BD_kCiAS.37a20e72aad4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hu-DlZ4REsp.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt-CXzOqbUC.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTimePicker-BwPSjcxJ.a223b07c705e.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt_BR-tNFhL9ci.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ko-ADlXHFgo.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDataTableServer-BYvhcs5d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-rFOjfrXe.df1b89399b11.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketCategoryEditor-rlIgT3uE.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.0308c579b183.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-CcFlDNPw.c63cac250b70.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-BJkOxCgW.8d4a4e6f7431.woff2'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-DYNiWd3v.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/brand_logo-DHt4CyHb.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.3ba9fc624e34.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/OpenDataImportSettings-Ds1SQcSg.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.16f243b74d54.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VFileUpload-ByFVW7Fp.931d5a48009e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DatabaseModelCol-rKX1F7Em.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.5e0dd3a66e81.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lt-SI6E7sY1.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/DatabasePage-CY4BXH8T.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-C0_akhap.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/HierarchyEditor-wADOsT_-.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-B1X0PDnA.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/it-DJ2I6vOs.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.4a7617f1519d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.svg.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/WelcomePage-zPtXSDjc.4dfacc5c8da0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitEditor-54HrDOhT.9040eae92234.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/hr-CMRkObu_.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-j0TpvUy_.42df5f015009.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/OpenDataImportSettings-Ds1SQcSg.f895a746d306.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.d617fa524f97.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-DYNiWd3v.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ApiSettings-CzWgpe8R.82be1325ed18.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.eot'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-DL25Fkt0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryEntryLogDialog-Dv6Omj68.d4f65e984493.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.4a7617f1519d.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.26d1fdd28765.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdEditor-D5JQGcsU.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-DzUjbg1Y.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BatchDeleteDialog-C9gKVWYX.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.aa9eb5c590ab.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/nn-CkCilbi1.ccb3acb89917.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryEntryLogDialog-Dv6Omj68.d4f65e984493.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.727c640d6c8d.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ApiSettings-CzWgpe8R.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-BG9pNfzF.9465c6dc1d2f.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AiProviderEditor-C4TWtCwO.e6d60050b025.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.3796d8a521cf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.727c640d6c8d.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.4ed293ceaca9.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelListPage-xoBv_A6i.4681a991ae27.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/uk-BClnjIfW.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.f2cae0d44a21.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.94016f72f4cb.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-Brwft-8t.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/de-5mnKTxw2.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VFileUpload-7CWUohzn.d182bb8e4f03.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.ffd6a13b9ab5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-_OUjgGcO.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.7195d47ccd52.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/brand_logo-DHt4CyHb.fa64319ab35b.svg.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.5e0dd3a66e81.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fileFilter-JaX38xV6.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealTypeEditor-DAAKjxZB.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/pl-B7dc5eNY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-BnHJd-1b.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/framework-CKkm3ZT1.0da2482ae88a.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-Bc1o5piM.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.7d9049ae96b5.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CookLogEditor-wf-1cNFJ.ef3a04991a05.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingSettings-DBfLsRlj.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AddToShoppingDialog-CS_S-d2g.eb5504799c65.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-CTAAxXor.4a6591ab5460.woff2'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.2f9dbd605868.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AiProviderEditor-BYnKvCw_.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/uk-BClnjIfW.b429b8ed5096.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BookViewPage-CHarlNiQ.bdf998b08053.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdPage-BsKZpym2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fi-BLW_HATq.078772422941.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.e73a0647198c.eot.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InviteLinkEditor-BZ7NMcrL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.4de7c0a8c2e3.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VRating-BAibLkoF.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-WpOvMnND.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.08d7c47f5d2b.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AutomationEditor-C6fYAtLL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.e73a0647198c.eot'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.085aaed48fa0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.73de85b4e4df.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-CFEp5VcY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-BG9pNfzF.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/integration_utils-D8RSOVmp.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/nb_NO-CdS1Hktt.294979d98dcb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.8dc9d3e18964.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-BnHJd-1b.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-DL25Fkt0.5373fcf8fbc3.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchPage-BQ1P-4y8.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/StartPage-0ugVot93.1c72303e8853.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fdc-Byjxh21q.6a8962cb2f19.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.7d9049ae96b5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.e4b532c48301.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-CIrx7Wew.44bd56e30e62.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.0916b5adcb73.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B_U4Berv.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.5c0bb4b51390.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.4d7347e87897.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.26d1fdd28765.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/AddToShoppingDialog-BXt5jKLm.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ru-BXmxlY4u.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hu-DlZ4REsp.c1bc941c31dc.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitConversionEditor-BUHvM5Eh.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextarea-zkkSnzux.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B_U4Berv.7dc258e43ccf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.6b450d3cfcd0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-DqGGZRzo.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.0b75aa57bbeb.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.5c0bb4b51390.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/main-nTFEtOSD.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.cc1baa1c02f3.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/StorageEditor-Up4uWQb6.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-DTdW4rEh.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/he-DxNGVUQd.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.8dc9d3e18964.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextarea-dHE66AZf.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/intersect-siLrmRQw.cc9e340f1351.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/framework-CKkm3ZT1.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ca-C5QQCa9o.ff6e54a70768.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-D0aA9rwL.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.ffd6a13b9ab5.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/main-nTFEtOSD.4273b900f1bf.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListEditor-vKmfFTZN.4f5dd4c981a5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ClosableHelpAlert-BoN8dDrm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-D7bmUCsu.f212789ebec5.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-C0_akhap.1b6d4259ca8e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hy-HqufUZnw.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.45c2c2f7531a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-DzUjbg1Y.fa06924ae72f.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/form-CDdumt48.5fcbf914ae94.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdPage-BsKZpym2.a5566a4564d6.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/forwardRefs-DVyU53sF.64171d66d1df.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/integration_utils-D8RSOVmp.8006123d3084.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceSettings-BPOt7vl3.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditorBase-CZWlxxIQ.cf852babb62d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B5oBrkJw.0c31f8b7052c.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-CFEp5VcY.2a4e88a23ede.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FdcSearchDialog-BvpKKey4.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ro-CG_JGo0i.c856bd470eef.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientsTable-DZblS1P-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-i2TDHCpS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-rFOjfrXe.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FoodEditor-BR-tK8Pr.24df4c5c0e7e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/cs-DUZpBKTY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.0b75aa57bbeb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fdc-Byjxh21q.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CookLogEditor-wf-1cNFJ.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdEditor-D5JQGcsU.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.085aaed48fa0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-Byn3Fc0w.3ad96cecfca7.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.a85f6556b6a2.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VStepper-lk6OG_fY.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ko-ADlXHFgo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/WelcomePage-zPtXSDjc.4dfacc5c8da0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceSetupPage-BSv2ZmPb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/zh_Hant-CERwsE1Q.8534ecee0fb0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.f2cae0d44a21.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.1f4f586d7141.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeImportPage-DBKJ6DXr.a23aec8a9383.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDataTableServer-BYvhcs5d.d5a7cfdcf126.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ar-Ct4DpnJT.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VRating-Qn4Hz2ci.119bbc89c24a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.cfc3e206a4c1.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HelpPage-C-xlKPtR.fa54da2fd1cf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HierarchyEditor-wADOsT_-.885aa06e77cd.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-Byn3Fc0w.3ad96cecfca7.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.94016f72f4cb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PrivateRecipeBadge-BVOXRXwb.dcd01dd00de0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.b9bc4a1f032c.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-BEgLts9b.a782baa8633b.woff'
|
||||||
|
tandoor | Deleting 'vue3/assets/nl-DIqabTrY.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/et-zY9CrDMt.1761c6eb5f48.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.b663eac25ee4.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-Cu9LLPvL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.e3586751a38a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/goto-DubWlX_o.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelMergeDialog-BCXJZjTO.4753553f721f.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AutomationEditor-C6fYAtLL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-j0TpvUy_.42df5f015009.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lv-BUrQRxBI.8efc7d113546.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.2f9dbd605868.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/NumberScalerDialog-DoOvxgjM.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-D0aA9rwL.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/intersect-siLrmRQw.cc9e340f1351.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-Bz9gKX-q.27a6a10279b7.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-regular-400-DZaxPHgR.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/tr-OeJMQhAK.2c406e95c585.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BY3ErEFj.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Djsboh2v.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/model_utils-a_hMB_Qu.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ar-Ct4DpnJT.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/BooksPage-Dh8_wlv_.js.gz'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.c659e2604ad6.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_black.dc487b18028c.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.ad2e3aa263da.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_192.c9b9177ff941.png'
|
||||||
|
tandoor | Deleting 'assets/logo_black.svg'
|
||||||
|
tandoor | Deleting 'assets/header.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_144.f09537dbf142.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_128.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.ad2e3aa263da.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.4ccbb336af9d.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/spinner.168a09fd2600.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_144.22c6c7678fdb.png'
|
||||||
|
tandoor | Deleting 'assets/spinner.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_512.png'
|
||||||
|
tandoor | Deleting 'assets/logo_black.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.d7c2e31a63b7.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.c659e2604ad6.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_32.b7d9707eac91.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_512.0a28df8511e3.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_black.dc487b18028c.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.fd1e81a4dcab.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/header.48e8ad9e7540.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_512.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_512.6b2e69402327.png'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_128.a90db52449d9.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_512.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_32.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.fd1e81a4dcab.svg'
|
||||||
|
tandoor | Deleting 'assets/header.48e8ad9e7540.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.d43daa47dca3.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_180.0fcae5e85a72.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_180.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.svg'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.d43daa47dca3.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.4ccbb336af9d.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_512.028b9bcca1eb.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.svg'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/header.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/spinner.168a09fd2600.svg'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.6ebe02bf6707.png'
|
||||||
|
tandoor | Deleting 'assets/spinner.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.d7c2e31a63b7.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_144.6c05e01d07b2.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_192.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.svg'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.6a3183313556.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.6a3183313556.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.88878ff60271.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.88878ff60271.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.js'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.e62f1984b5e4.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.e62f1984b5e4.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.3bdb00cbb58c.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.3bdb00cbb58c.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.22de6a06ad0b.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.css.gz'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.22de6a06ad0b.css.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.8e4a6dcc692b.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.c2801fb415f0.svg'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.c5e0f14f88a8.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c4f508e7c4f0.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_500.d214b888d895.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_500.fd9b8290076b.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.a9c4bb7348f4.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_400.9ed361bba848.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.8e4a6dcc692b.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.cccc9d29470e.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.0bff33a5fd7e.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.f5f2566b93e8.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c1a866ec0e04.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_700.b9f2c13fc361.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.06147b6cd88c.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.svg'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.eot'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_400.d5e78c53cb07.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.c2801fb415f0.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_400.4d1490f32451.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.7b9568e6389b.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c1a866ec0e04.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.a9c4bb7348f4.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.5063b105c764.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.7b9568e6389b.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.44d537ab79f9.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_500.84780596e268.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.06147b6cd88c.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.333bae208dc3.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.65b286af947c.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.5063b105c764.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_700.62d7a4c78fc2.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.0bff33a5fd7e.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.65b286af947c.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_700.f4f17fd53c7d.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.ttf'
|
||||||
|
tandoor | 2026/09/22 10:54:37 [crit] 16#16: *9 connect() to unix:/tmp/tandoor.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /accounts/login/ HTTP/1.1", upstream: "http://unix:/tmp/tandoor.sock:/accounts/login/", host: "127.0.0.1:80"
|
||||||
|
tandoor | 127.0.0.1 - - [22/Sep/2026:10:54:37 +0200] "GET /accounts/login/ HTTP/1.1" 502 150 "-" "Wget" "-"
|
||||||
|
tandoor |
|
||||||
|
tandoor | 894 static files copied to '/opt/recipes/staticfiles', 2464 post-processed.
|
||||||
|
tandoor | Done
|
||||||
|
tandoor | Starting gunicorn
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Starting gunicorn 26.2.0
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Listening at: unix:/tmp/tandoor.sock (7)
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Using worker: gthread
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [66] [INFO] Booting worker with pid: 66
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [67] [INFO] Booting worker with pid: 67
|
||||||
|
tandoor | [2026-09-22 10:54:38 +0200] [68] [INFO] Booting worker with pid: 68
|
||||||
|
tandoor | [2026-09-22 10:54:38 +0200] [7] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | 127.0.0.1 - - [22/Sep/2026:10:54:45 +0200] "GET /accounts/login/ HTTP/1.1" 200 4981 "-" "Wget" "-"
|
||||||
|
tandoor | - - [22/Sep/2026:10:54:45 +0200] "GET /accounts/login/ HTTP/1.0" 200 4981 "-" "Wget"
|
||||||
|
tandoor | ThreadPoolExecutor-0_0 ERROR 2026-09-22 10:54:47,243 django.security.DisallowedHost Invalid HTTP_HOST header: 'tandoor:80'. You may need to add 'tandoor' to ALLOWED_HOSTS.
|
||||||
|
tandoor | Traceback (most recent call last):
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||||||
|
tandoor | response = get_response(request)
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 119, in __call__
|
||||||
|
tandoor | response = self.process_request(request)
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/middleware/common.py", line 48, in process_request
|
||||||
|
tandoor | host = request.get_host()
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/http/request.py", line 203, in get_host
|
||||||
|
tandoor | raise DisallowedHost(msg)
|
||||||
|
tandoor | django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'tandoor:80'. You may need to add 'tandoor' to ALLOWED_HOSTS.
|
||||||
|
tandoor | - - [22/Sep/2026:10:54:47 +0200] "GET /accounts/login/ HTTP/1.0" 400 143 "-" "Go-http-client/1.1"
|
||||||
|
tandoor | 172.18.0.2 - - [22/Sep/2026:10:54:47 +0200] "GET /accounts/login/ HTTP/1.1" 400 154 "-" "Go-http-client/1.1" "-"
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"before": {
|
||||||
|
"hu": [],
|
||||||
|
"en": []
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
|
||||||
|
"text": "Frissítés elérhető — ma"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "A newer version of this app is available. Select the Update button to start it.",
|
||||||
|
"text": "Update available — today"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"drill_commit": "654a28192b38"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
10:52:42 ==== tandoor: ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (sub=recipes, class=db)
|
||||||
|
10:52:42 [1] tandoor already deployed — reusing
|
||||||
|
10:52:45 [2] seeding through the app's own front door
|
||||||
|
10:52:55 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||||
|
10:52:59 tandoor: seeded superuser drill1d392f
|
||||||
|
10:52:59 [3] control C1 — reading the seed back BEFORE the update
|
||||||
|
10:53:05 tandoor: readback of the seeded account found=True
|
||||||
|
10:53:05 [4] „Mentés most" -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||||
|
10:54:00 [4] backup idle; last=None
|
||||||
|
10:54:01 [5] drill commit 654a28192b38: tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (push rc=0)
|
||||||
|
10:54:06 [5] badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
|
10:54:06 [5] badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
|
10:54:06 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||||
|
10:54:06 + 0.0s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||||
|
10:54:07 + 1.0s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||||
|
10:54:08 + 2.1s phase=starting label=Indítás az új verzióval… err=None hold=None
|
||||||
|
10:54:11 + 5.2s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||||
|
10:54:47 + 41.1s phase=done label=Frissítve err=None hold=None
|
||||||
|
10:54:47 [7] reading the seed back AFTER the update
|
||||||
|
10:54:54 tandoor: readback of the seeded account found=True
|
||||||
|
10:54:56 [8] pinned = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
10:54:56 [8] installed = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
10:54:56 [8] compose = ['image: ghcr.io/tandoorrecipes/recipes:2.6.15', 'image: postgres:16-alpine']
|
||||||
|
10:54:56 [8] inspect = ['tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0', 'tandoor-postgres postgres:16-alpine running=true restarts=0']
|
||||||
|
10:54:56 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/update-night-2026-09-21/apps/tandoor/verdict.json
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": null,
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"before": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": null,
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"accepted": true,
|
||||||
|
"http": "202",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": "Adatbázis pillanatkép…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.0,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": "Új verzió letöltése…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 2.1,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": "Indítás az új verzióval…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 5.2,
|
||||||
|
"phase": "verifying",
|
||||||
|
"label": "Működés ellenőrzése…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 41.1,
|
||||||
|
"phase": "done",
|
||||||
|
"label": "Frissítve",
|
||||||
|
"updating": false,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"duration_s": 41.1,
|
||||||
|
"final_phase": "done",
|
||||||
|
"update_error": null,
|
||||||
|
"hold_reason": null,
|
||||||
|
"state": "running"
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"harness_version": 1,
|
||||||
|
"app": "tandoor",
|
||||||
|
"venue": "guest 9202 demo-hp-scratch, controller 0.261.0",
|
||||||
|
"class": "db",
|
||||||
|
"from": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"verdict": "proven",
|
||||||
|
"seed_read_before": true,
|
||||||
|
"seed_read_after": true,
|
||||||
|
"healthy_after": true,
|
||||||
|
"migration_observed": null,
|
||||||
|
"abort": "not-attempted",
|
||||||
|
"abort_detail": null,
|
||||||
|
"duration_s": 41.1,
|
||||||
|
"measured_at": "2026-09-22T08:52:42.724401+00:00",
|
||||||
|
"evidence": "apps/tandoor/",
|
||||||
|
"notes": [],
|
||||||
|
"badge_catchup_seconds": 4.5,
|
||||||
|
"observables_after": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"final_phase": "done",
|
||||||
|
"hold_reason": null,
|
||||||
|
"update_error": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
origin https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git (fetch)
|
||||||
|
origin https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git (push)
|
||||||
|
6c690a1 gates: refuse a health probe the app does not answer (R-618)
|
||||||
|
13: image: ghcr.io/tandoorrecipes/recipes:2.6.13
|
||||||
|
58: image: postgres:16-alpine
|
||||||
|
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"before": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
||||||
|
"text": "Naprakész"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "This app is running the newest version available.",
|
||||||
|
"text": "Up to date"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"hu": [
|
||||||
|
{
|
||||||
|
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
|
||||||
|
"text": "Frissítés elérhető — ma"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
{
|
||||||
|
"title": "A newer version of this app is available. Select the Update button to start it.",
|
||||||
|
"text": "Update available — today"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"drill_commit": "c7477d1fb921"
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
21:36:12 ==== FAILWALK tandoor: the household's way out of a held update
|
||||||
|
21:36:15 [1] held state: phase=failed hold='A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.'
|
||||||
|
21:36:15 update_error = 'A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.'
|
||||||
|
21:36:15 pinned = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
21:36:15 installed = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.13', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
21:36:15 compose = ['image: ghcr.io/tandoorrecipes/recipes:2.6.15', 'image: postgres:16-alpine']
|
||||||
|
21:36:15 inspect = []
|
||||||
|
21:36:15 [2] hold sentence HU: ['Tandoor Recipes — Felhom.eu Indítópult Vezérlőpult Alkalmazások Tárhely Meghajtók Hálózati tárhely Biztonsági mentés Áttekintés Távoli mentés Alkalmazások Visszaállítás Megosztás Hálózati megosztás Rendszermonitor Debug Beállítások Rendszer Értesítések Biztonság és hozzáférés 0.261.0 Magyar English Kijelentkezés ↗ Telepített alkalmazás nem fut: Tandoor Recipes (stopped) Rendszermonitor → Hub kapcsolat kikapcsolva — a központi monitoring nem aktív Rendszermonitor → ← Alkalmazások Tandoor Recipes Leállítva Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval.', 'Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.', 'Mentések Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az adatait másik csatlakoztatott tárhelyre helyezheted át.', 'Receptek gyűjtése és rendszerezése egy helyen Receptek importálása weboldalakról egy kattintással Heti étkezés tervezés és bevásárlólista generálás Több felhasználó - a család együtt tervezhet Receptek megosztása linkkel családtagokkal, barátokkal Első lépések Nyisd meg a recipes.DOMAIN címet a böngészőben Hozd létre az admin fiókot Importáld az első receptet egy weboldalról (Bookmarklet) Próbáld ki az étkezés tervezőt Hívd meg a családtagokat Dokumentáció Hivatalos dokumentáció ↗']
|
||||||
|
21:36:15 [2] hold sentence EN: ['Tandoor Recipes — Felhom.eu Launcher Dashboard Apps Storage Drives Network storage Backup Overview Remote backup Apps Restore Sharing Network sharing System monitor Debug Settings System Notifications Security and access 0.261.0 Magyar English Sign out ↗ An installed app is not running: Tandoor Recipes (stopped) System monitor → The hub connection is off — central monitoring is not running System monitor → ← Apps Tandoor Recipes Stopped Update available — today Open ↗ Log Export Settings A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval.', 'Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.', 'Backups A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another connected storage.', 'Keep all your recipes in one place Import a recipe from a web page with one click Plan the week's meals and get a shopping list out of it Several people - the household can plan together Share a recipe by link with family and friends First steps Open recipes.DOMAIN in your browser Create the admin account Import your first recipe from a web page (Bookmarklet) Try the meal planner Invite the household Documentation Official documentation ↗']
|
||||||
|
21:36:15 [3] the last migration line the app printed, verbatim: None
|
||||||
|
21:36:15 [R] restoring tandoor from snapshot 'helyi' (of 1 offered)
|
||||||
|
21:36:15 [R] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
|
||||||
|
21:36:15 + 0.0s restore (True, None, None)
|
||||||
|
21:36:47 + 32.4s restore (False, None, None)
|
||||||
|
21:36:47 [R] after restore: state=running hold=None phase=None
|
||||||
|
21:36:50 [4] restore: HTTP/2 302 in 32.4s; state=running hold=None
|
||||||
|
21:36:50 pinned after = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.13', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
21:36:50 inspect after = ['tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0', 'tandoor-postgres postgres:16-alpine running=true restarts=0']
|
||||||
|
21:36:59 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||||
|
21:37:03 tandoor: seeded superuser drill74a269
|
||||||
|
21:37:09 tandoor: readback of the seeded account found=True
|
||||||
|
21:37:09 [5] the app answers its own front door again and holds data: True
|
||||||
|
21:37:10 [6] sentence after the restore HU: ['Tandoor Recipes — Felhom.eu Indítópult Vezérlőpult Alkalmazások Tárhely Meghajtók Hálózati tárhely Biztonsági mentés Áttekintés Távoli mentés Alkalmazások Visszaállítás Megosztás Hálózati megosztás Rendszermonitor Debug Beállítások Rendszer Értesítések Biztonság és hozzáférés 0.261.0 Magyar English Kijelentkezés ↗ Hub kapcsolat kikapcsolva — a központi monitoring nem aktív Rendszermonitor → ← Alkalmazások Tandoor Recipes Nem egészséges Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az adatait másik csatlakoztatott tárhelyre helyezheted át.', 'Receptek gyűjtése és rendszerezése egy helyen Receptek importálása weboldalakról egy kattintással Heti étkezés tervezés és bevásárlólista generálás Több felhasználó - a család együtt tervezhet Receptek megosztása linkkel családtagokkal, barátokkal Első lépések Nyisd meg a recipes.DOMAIN címet a böngészőben Hozd létre az admin fiókot Importáld az első receptet egy weboldalról (Bookmarklet) Próbáld ki az étkezés tervezőt Hívd meg a családtagokat Dokumentáció Hivatalos dokumentáció ↗']
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
{
|
||||||
|
"leg": "failwalk",
|
||||||
|
"app": "tandoor",
|
||||||
|
"held": {
|
||||||
|
"state": "stopped",
|
||||||
|
"updating": false,
|
||||||
|
"update_phase": "failed",
|
||||||
|
"update_phase_label": "A frissítés nem sikerült",
|
||||||
|
"update_error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"hold_reason": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"observables": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hold_sentences": {
|
||||||
|
"hu": [
|
||||||
|
"Tandoor Recipes — Felhom.eu Indítópult Vezérlőpult Alkalmazások Tárhely Meghajtók Hálózati tárhely Biztonsági mentés Áttekintés Távoli mentés Alkalmazások Visszaállítás Megosztás Hálózati megosztás Rendszermonitor Debug Beállítások Rendszer Értesítések Biztonság és hozzáférés 0.261.0 Magyar English Kijelentkezés ↗ Telepített alkalmazás nem fut: Tandoor Recipes (stopped) Rendszermonitor → Hub kapcsolat kikapcsolva — a központi monitoring nem aktív Rendszermonitor → ← Alkalmazások Tandoor Recipes Leállítva Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval.",
|
||||||
|
"Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"Mentések Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az adatait másik csatlakoztatott tárhelyre helyezheted át.",
|
||||||
|
"Receptek gyűjtése és rendszerezése egy helyen Receptek importálása weboldalakról egy kattintással Heti étkezés tervezés és bevásárlólista generálás Több felhasználó - a család együtt tervezhet Receptek megosztása linkkel családtagokkal, barátokkal Első lépések Nyisd meg a recipes.DOMAIN címet a böngészőben Hozd létre az admin fiókot Importáld az első receptet egy weboldalról (Bookmarklet) Próbáld ki az étkezés tervezőt Hívd meg a családtagokat Dokumentáció Hivatalos dokumentáció ↗"
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
"Tandoor Recipes — Felhom.eu Launcher Dashboard Apps Storage Drives Network storage Backup Overview Remote backup Apps Restore Sharing Network sharing System monitor Debug Settings System Notifications Security and access 0.261.0 Magyar English Sign out ↗ An installed app is not running: Tandoor Recipes (stopped) System monitor → The hub connection is off — central monitoring is not running System monitor → ← Apps Tandoor Recipes Stopped Update available — today Open ↗ Log Export Settings A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval.",
|
||||||
|
"Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"Backups A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another connected storage.",
|
||||||
|
"Keep all your recipes in one place Import a recipe from a web page with one click Plan the week's meals and get a shopping list out of it Several people - the household can plan together Share a recipe by link with family and friends First steps Open recipes.DOMAIN in your browser Create the admin account Import your first recipe from a web page (Bookmarklet) Try the meal planner Invite the household Documentation Official documentation ↗"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"last_migration_line": null,
|
||||||
|
"way_out": {
|
||||||
|
"ok": true,
|
||||||
|
"snapshot_id": "helyi",
|
||||||
|
"snapshots": [
|
||||||
|
{
|
||||||
|
"time": "2026-09-21T19:16:48Z",
|
||||||
|
"short_id": "helyi",
|
||||||
|
"tier": 1,
|
||||||
|
"drive_label": "Belső SSD (rendszer)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"http": "HTTP/2 302",
|
||||||
|
"location": [
|
||||||
|
"location: /backups/restore?flash=flash.restore.started"
|
||||||
|
],
|
||||||
|
"seconds": 32.4,
|
||||||
|
"state_after": "running",
|
||||||
|
"hold_after": null,
|
||||||
|
"observables_after": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data_after_restore": {
|
||||||
|
"route": "re-seeded after the restore",
|
||||||
|
"ok": true,
|
||||||
|
"note": "the pre-update seed token did not survive the failed run's process, so this re-seeds AFTER the restore: it proves the app WORKS again on the old version, not that the specific pre-update row survived. Stated rather than glossed."
|
||||||
|
},
|
||||||
|
"sentences_after_restore": {
|
||||||
|
"hu": [
|
||||||
|
"Tandoor Recipes — Felhom.eu Indítópult Vezérlőpult Alkalmazások Tárhely Meghajtók Hálózati tárhely Biztonsági mentés Áttekintés Távoli mentés Alkalmazások Visszaállítás Megosztás Hálózati megosztás Rendszermonitor Debug Beállítások Rendszer Értesítések Biztonság és hozzáférés 0.261.0 Magyar English Kijelentkezés ↗ Hub kapcsolat kikapcsolva — a központi monitoring nem aktív Rendszermonitor → ← Alkalmazások Tandoor Recipes Nem egészséges Frissítés elérhető — ma Megnyitás ↗ Napló Exportálás Beállítások Receptkezelő és étkezés tervező a családnak ~512M RAM home Pi kompatibilis Áthelyezés másik tárhelyre Ennek az alkalmazásnak az adatait másik csatlakoztatott tárhelyre helyezheted át.",
|
||||||
|
"Receptek gyűjtése és rendszerezése egy helyen Receptek importálása weboldalakról egy kattintással Heti étkezés tervezés és bevásárlólista generálás Több felhasználó - a család együtt tervezhet Receptek megosztása linkkel családtagokkal, barátokkal Első lépések Nyisd meg a recipes.DOMAIN címet a böngészőben Hozd létre az admin fiókot Importáld az első receptet egy weboldalról (Bookmarklet) Próbáld ki az étkezés tervezőt Hívd meg a családtagokat Dokumentáció Hivatalos dokumentáció ↗"
|
||||||
|
],
|
||||||
|
"en": [
|
||||||
|
"Tandoor Recipes — Felhom.eu Launcher Dashboard Apps Storage Drives Network storage Backup Overview Remote backup Apps Restore Sharing Network sharing System monitor Debug Settings System Notifications Security and access 0.261.0 Magyar English Sign out ↗ The hub connection is off — central monitoring is not running System monitor → ← Apps Tandoor Recipes Not healthy Update available — today Open ↗ Log Export Settings A recipe manager and meal planner for the household ~512M RAM home Runs on Pi Move to another storage You can move this app’s data to another connected storage.",
|
||||||
|
"Keep all your recipes in one place Import a recipe from a web page with one click Plan the week's meals and get a shopping list out of it Several people - the household can plan together Share a recipe by link with family and friends First steps Open recipes.DOMAIN in your browser Create the admin account Import your first recipe from a web page (Bookmarklet) Try the meal planner Invite the household Documentation Official documentation ↗"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+654
@@ -0,0 +1,654 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="no-js">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tandoor Recipes — Felhom.eu</title>
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg?v=0.261.0">
|
||||||
|
<link rel="stylesheet" href="/static/style.css?v=0.261.0">
|
||||||
|
<meta name="csrf-token" content="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307">
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
document.documentElement.className=document.documentElement.className.replace('no-js','js');
|
||||||
|
function csrfHeaders(){var el=document.querySelector('meta[name="csrf-token"]');return el?{'X-CSRF-Token':el.content}:{};}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function felhomConfirm(el,question,onYes){
|
||||||
|
if(!el||el.dataset.fcOpen)return;
|
||||||
|
el.dataset.fcOpen='1';
|
||||||
|
var wrap=document.createElement('span');wrap.className='inline-confirm';
|
||||||
|
var q=document.createElement('span');q.className='inline-confirm-q';q.textContent=question;
|
||||||
|
var yes=document.createElement('button');yes.type='button';yes.className='btn btn-xs btn-danger';yes.textContent='Yes';
|
||||||
|
var no=document.createElement('button');no.type='button';no.className='btn btn-xs btn-outline';no.textContent='Cancel';
|
||||||
|
wrap.appendChild(q);wrap.appendChild(yes);wrap.appendChild(no);
|
||||||
|
el.style.display='none';el.parentNode.insertBefore(wrap,el.nextSibling);
|
||||||
|
function close(){wrap.remove();el.style.display='';delete el.dataset.fcOpen;}
|
||||||
|
no.addEventListener('click',close);
|
||||||
|
yes.addEventListener('click',function(){close();onYes();});
|
||||||
|
}
|
||||||
|
document.addEventListener('click',function(e){
|
||||||
|
var btn=e.target.closest?e.target.closest('[data-confirm]'):null;
|
||||||
|
if(!btn)return;
|
||||||
|
e.preventDefault();
|
||||||
|
felhomConfirm(btn,btn.getAttribute('data-confirm'),function(){
|
||||||
|
var form=btn.closest('form');
|
||||||
|
if(form){if(form.requestSubmit)form.requestSubmit(btn);else form.submit();}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('click',function(e){
|
||||||
|
var btn=e.target.closest?e.target.closest('.nav-group-toggle'):null;
|
||||||
|
if(!btn)return;
|
||||||
|
var group=btn.closest('.nav-group');
|
||||||
|
if(!group)return;
|
||||||
|
var willOpen=!group.classList.contains('is-open');
|
||||||
|
document.querySelectorAll('.nav-group.is-open').forEach(function(g){
|
||||||
|
g.classList.remove('is-open');
|
||||||
|
var t=g.querySelector('.nav-group-toggle');
|
||||||
|
if(t)t.setAttribute('aria-expanded','false');
|
||||||
|
});
|
||||||
|
if(willOpen){group.classList.add('is-open');btn.setAttribute('aria-expanded','true');}
|
||||||
|
});
|
||||||
|
function showAlert(msg){var o=document.createElement('div');o.className='modal-overlay';o.id='alert-modal';o.addEventListener('click',function(e){if(e.target===o)o.remove();});var c=document.createElement('div');c.className='modal-card';c.innerHTML='<h3>Message</h3><pre style="white-space:pre-wrap;word-break:break-word;background:var(--bg-2);padding:.75rem;border-radius:.375rem;font-size:.85rem;max-height:60vh;overflow-y:auto;user-select:text;cursor:text">'+msg.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')+'</pre><div class="modal-actions"><button class="btn btn-primary" onclick="document.getElementById(\'alert-modal\').remove()">OK</button></div>';o.appendChild(c);document.body.appendChild(o);}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">
|
||||||
|
<symbol id="i-hard-drive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 16h.01" /> <path d="M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /> <path d="M21.946 12.013H2.054" /> <path d="M6 16h.01" /></symbol>
|
||||||
|
<symbol id="i-cpu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20v2" /> <path d="M12 2v2" /> <path d="M17 20v2" /> <path d="M17 2v2" /> <path d="M2 12h2" /> <path d="M2 17h2" /> <path d="M2 7h2" /> <path d="M20 12h2" /> <path d="M20 17h2" /> <path d="M20 7h2" /> <path d="M7 20v2" /> <path d="M7 2v2" /> <rect x="4" y="4" width="16" height="16" rx="2" /> <rect x="8" y="8" width="8" height="8" rx="1" /></symbol>
|
||||||
|
<symbol id="i-memory-stick" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 12v-2" /> <path d="M12 18v-2" /> <path d="M16 12v-2" /> <path d="M16 18v-2" /> <path d="M2 11h1.5" /> <path d="M20 18v-2" /> <path d="M20.5 11H22" /> <path d="M4 18v-2" /> <path d="M8 12v-2" /> <path d="M8 18v-2" /> <rect x="2" y="6" width="20" height="10" rx="2" /></symbol>
|
||||||
|
<symbol id="i-thermometer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z" /></symbol>
|
||||||
|
<symbol id="i-triangle-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" /></symbol>
|
||||||
|
<symbol id="i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2" /> <path d="M7 11V7a5 5 0 0 1 10 0v4" /></symbol>
|
||||||
|
<symbol id="i-cloud" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /></symbol>
|
||||||
|
<symbol id="i-square" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" /></symbol>
|
||||||
|
<symbol id="i-rotate-cw" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" /> <path d="M21 3v5h-5" /></symbol>
|
||||||
|
<symbol id="i-file-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /> <path d="M14 2v5a1 1 0 0 0 1 1h5" /> <path d="M10 9H8" /> <path d="M16 13H8" /> <path d="M16 17H8" /></symbol>
|
||||||
|
<symbol id="i-external-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6" /> <path d="M10 14 21 3" /> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" /></symbol>
|
||||||
|
<symbol id="i-shield" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /></symbol>
|
||||||
|
<symbol id="i-server" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="8" x="2" y="2" rx="2" ry="2" /> <rect width="20" height="8" x="2" y="14" rx="2" ry="2" /> <line x1="6" x2="6.01" y1="6" y2="6" /> <line x1="6" x2="6.01" y1="18" y2="18" /></symbol>
|
||||||
|
<symbol id="i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3" /> <circle cx="6" cy="12" r="3" /> <circle cx="18" cy="19" r="3" /> <line x1="8.59" x2="15.42" y1="13.51" y2="17.49" /> <line x1="15.41" x2="8.59" y1="6.51" y2="10.49" /></symbol>
|
||||||
|
<symbol id="i-layout-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="7" height="7" x="3" y="3" rx="1" /> <rect width="7" height="7" x="14" y="3" rx="1" /> <rect width="7" height="7" x="14" y="14" rx="1" /> <rect width="7" height="7" x="3" y="14" rx="1" /></symbol>
|
||||||
|
<symbol id="i-rocket" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91 0z" /> <path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" /> <path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" /> <path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" /></symbol>
|
||||||
|
<symbol id="i-settings" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /> <circle cx="12" cy="12" r="3" /></symbol>
|
||||||
|
<symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /> <path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></symbol>
|
||||||
|
<symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18" /> <path d="m6 6 12 12" /></symbol>
|
||||||
|
<symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></symbol>
|
||||||
|
<symbol id="i-pencil" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" /> <path d="m15 5 4 4" /></symbol>
|
||||||
|
<symbol id="i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /> <path d="M12 16v-4" /> <path d="M12 8h.01" /></symbol>
|
||||||
|
<symbol id="i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15V3" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="m7 10 5 5 5-5" /></symbol>
|
||||||
|
<symbol id="i-upload" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12" /> <path d="m17 8-5-5-5 5" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /></symbol>
|
||||||
|
<symbol id="i-trash-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /> <path d="M14 11v6" /> <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /> <path d="M3 6h18" /> <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></symbol>
|
||||||
|
<symbol id="i-wrench" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z" /></symbol>
|
||||||
|
<symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /> <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /></symbol>
|
||||||
|
<symbol id="i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /> <circle cx="11" cy="11" r="8" /></symbol>
|
||||||
|
<symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /> <path d="M12 5v14" /></symbol>
|
||||||
|
<symbol id="i-chevron-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></symbol>
|
||||||
|
<symbol id="i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z" /></symbol>
|
||||||
|
<symbol id="i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="14" y="3" width="5" height="18" rx="1" /> <rect x="5" y="3" width="5" height="18" rx="1" /></symbol>
|
||||||
|
<symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16" /> <path d="M4 6h16" /> <path d="M4 18h16" /></symbol>
|
||||||
|
</svg>
|
||||||
|
<header class="mobile-topbar">
|
||||||
|
<a href="/" class="mobile-topbar-logo"><img src="/static/felhom-logo.svg?v=0.261.0" alt="Felhom.eu"></a>
|
||||||
|
<button type="button" class="nav-burger" aria-expanded="false" aria-controls="sidebar" aria-label="Menu">
|
||||||
|
<svg class="ico"><use href="#i-menu"/></svg>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<div class="nav-backdrop" hidden></div>
|
||||||
|
<nav class="sidebar" id="sidebar">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<img src="/static/felhom-logo.svg?v=0.261.0" alt="Felhom.eu" class="sidebar-logo">
|
||||||
|
</div>
|
||||||
|
<ul class="nav-links">
|
||||||
|
<li><a href="/launcher" class=""><svg class="ico"><use href="#i-rocket"/></svg>Launcher</a></li>
|
||||||
|
<li><a href="/dashboard" class=""><svg class="ico"><use href="#i-layout-grid"/></svg>Dashboard</a></li>
|
||||||
|
<li><a href="/stacks" class="active"><svg class="ico"><use href="#i-cloud"/></svg>Apps</a></li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-storage"><svg class="ico"><use href="#i-hard-drive"/></svg>Storage<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-storage" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/storage" class="">Drives</a></li>
|
||||||
|
<li><a href="/storage/network" class="">Network storage</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-backups"><svg class="ico"><use href="#i-shield"/></svg>Backup<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-backups" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/backups" class="">Overview</a></li>
|
||||||
|
<li><a href="/backups/remote" class="">Remote backup</a></li>
|
||||||
|
<li><a href="/backups/apps" class="">Apps</a></li>
|
||||||
|
<li><a href="/backups/restore" class="">Restore</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-sharing"><svg class="ico"><use href="#i-share"/></svg>Sharing<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-sharing" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/sharing" class="">Network sharing</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="/monitoring" class=""><svg class="ico"><use href="#i-cpu"/></svg>System monitor</a></li>
|
||||||
|
<li><a href="/debug" class=""><svg class="ico"><use href="#i-wrench"/></svg>Debug</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-bottom">
|
||||||
|
<div class="nav-group-label">Settings</div>
|
||||||
|
<ul class="nav-links nav-links-sub">
|
||||||
|
<li><a href="/settings" class=""><svg class="ico"><use href="#i-settings"/></svg>System</a></li>
|
||||||
|
<li><a href="/settings/notifications" class=""><svg class="ico"><use href="#i-bell"/></svg>Notifications</a></li>
|
||||||
|
<li><a href="/settings/security" class=""><svg class="ico"><use href="#i-lock"/></svg>Security and access</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<span class="version">0.261.0</span><details class="lang-globe">
|
||||||
|
<summary class="lang-globe-btn" aria-label="Language" title="Language"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10" /><path d="M2 12h20" /><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg></summary>
|
||||||
|
<ul class="lang-globe-menu">
|
||||||
|
<li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307"><input type="hidden" name="back" value="/apps/tandoor"><button type="submit" name="lang" value="hu" lang="hu" class="lang-globe-item">Magyar</button></form></li>
|
||||||
|
<li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307"><input type="hidden" name="back" value="/apps/tandoor"><button type="submit" name="lang" value="en" lang="en" class="lang-globe-item current" aria-current="true">English</button></form></li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
<a href="/logout" class="logout-link">Sign out ↗</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<main class="content">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="alerts-container">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="alert-banner alert-banner-warning">
|
||||||
|
<span class="alert-icon"><svg class="ico"><use href="#i-triangle-alert"/></svg></span>
|
||||||
|
<span class="alert-message">The hub connection is off — central monitoring is not running</span>
|
||||||
|
<a href="/monitoring" class="alert-link">System monitor →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<div style="display:flex;align-items:center;gap:1rem">
|
||||||
|
<a href="/stacks" class="btn btn-sm btn-outline">← Apps</a>
|
||||||
|
<h2>Tandoor Recipes</h2>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;align-items:center;gap:.5rem">
|
||||||
|
|
||||||
|
<span class="stack-state-badge state-warn">Not healthy</span>
|
||||||
|
|
||||||
|
|
||||||
|
<span class="tag tag-warn" title="A newer version of this app is available. Select the Update button to start it.">Update available — today</span>
|
||||||
|
<a href="https://recipes.enkisfelhom.hu" target="_blank" class="btn btn-sm btn-outline">Open ↗</a>
|
||||||
|
<a href="/stacks/tandoor/logs" class="btn btn-sm btn-outline">Log</a>
|
||||||
|
|
||||||
|
<a href="/stacks/tandoor/export" class="btn btn-sm btn-outline">Export</a>
|
||||||
|
<a href="/stacks/tandoor/deploy" class="btn btn-sm btn-outline">Settings</a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-hero">
|
||||||
|
<img class="app-info-logo" src="/static/assets/tandoor-logo.svg"
|
||||||
|
alt="Tandoor Recipes" data-fallback="/static/app-placeholder.svg"
|
||||||
|
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='\/static\/assets\/tandoor-logo.png';}else if(this.dataset.fallback&&this.dataset.step==='1'){this.dataset.step='2';this.src=this.dataset.fallback;}else{this.onerror=null;this.style.visibility='hidden';}">
|
||||||
|
<div class="app-info-hero-text">
|
||||||
|
|
||||||
|
<p class="app-info-tagline">A recipe manager and meal planner for the household</p>
|
||||||
|
|
||||||
|
<div class="stack-meta-badges">
|
||||||
|
<span class="meta-badge">~512M RAM</span>
|
||||||
|
<span class="meta-badge">home</span>
|
||||||
|
|
||||||
|
<span class="meta-badge meta-badge-ok">Runs on Pi</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-screenshots" id="screenshots">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-1.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-2.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-3.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card" style="margin-top:1rem">
|
||||||
|
<h3>Move to another storage</h3>
|
||||||
|
<p class="form-hint">You can move this app’s data to another connected storage. The app stops briefly during the move, and the data is deleted from the old place only after the check and a successful restart.</p>
|
||||||
|
<div style="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;margin-top:.5rem">
|
||||||
|
<select id="app-migrate-target" class="btn btn-sm btn-outline">
|
||||||
|
<option value="">Choose a target storage…</option>
|
||||||
|
<option value="/mnt/felhom-drives/scratch_hdd">SCRATCH HDD (/mnt/felhom-drives/scratch_hdd)</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-outline" onclick="appMigrate(this,'tandoor','Tandoor Recipes')">Move</button>
|
||||||
|
</div>
|
||||||
|
<div id="app-migrate-progress" style="display:none;margin-top:.75rem;padding:.75rem;border:1px solid var(--blue);border-radius:6px;background:rgba(0,136,204,0.06)"></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function appMigFmtGB(b){ return (Number(b||0)/1e9).toFixed(1)+' GB'; }
|
||||||
|
function appMigRender(job){
|
||||||
|
var names={stop:'Stopping',copy:'Copying data',verify:'Checking',flip:'Reinstalling',redeploy:'Reinstalling',cleanup:'Deleting old data'};
|
||||||
|
var s=names[job.phase]||job.phase;
|
||||||
|
if(job.phase==='copy'&&job.bytes_total>0){ s+=' ('+Math.floor(100*job.bytes_done/job.bytes_total)+'% — '+appMigFmtGB(job.bytes_done)+'/'+appMigFmtGB(job.bytes_total)+')'; }
|
||||||
|
return s+'…';
|
||||||
|
}
|
||||||
|
function appMigWatch(){
|
||||||
|
var panel=document.getElementById('app-migrate-progress');
|
||||||
|
if(panel) panel.style.display='block';
|
||||||
|
function tick(){
|
||||||
|
fetch('/api/storage/migrate/status').then(function(r){return r.json();}).then(function(d){
|
||||||
|
var job=d.data&&d.data.job;
|
||||||
|
if(!job){ if(panel) panel.textContent='No move in progress.'; return; }
|
||||||
|
if(panel) panel.innerHTML=appMigRender(job);
|
||||||
|
if(job.phase==='done'){ if(panel) panel.innerHTML+='<br><strong>Done</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||||
|
if(job.phase==='aborted'){ if(panel) panel.innerHTML+='<br><strong style="color:var(--danger,#c0392b)">Stopped: '+(job.error||'')+'</strong><br>The old data is untouched.'; return; }
|
||||||
|
setTimeout(tick,1500);
|
||||||
|
}).catch(function(){ setTimeout(tick,2000); });
|
||||||
|
}
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
function appMigrate(btn,app,label){
|
||||||
|
var sel=document.getElementById('app-migrate-target');
|
||||||
|
var target=sel?sel.value:'';
|
||||||
|
if(!target){ showAlert('Choose a target storage.'); return; }
|
||||||
|
felhomConfirm(btn,'Move the '+label+' data to: '+target+'? The app stops briefly. The old data is deleted only after a successful move.',function(){
|
||||||
|
fetch('/api/storage/migrate-app',{method:'POST',headers:Object.assign({'Content-Type':'application/json'},csrfHeaders()),body:JSON.stringify({app:app,target:target})})
|
||||||
|
.then(function(r){return r.json();}).then(function(d){ if(d.ok){ appMigWatch(); } else { showAlert('Error: '+(d.error||'unknown')); } })
|
||||||
|
.catch(function(e){ showAlert('Error: '+e); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(function(){ fetch('/api/storage/migrate/status').then(function(r){return r.json();}).then(function(d){ if(d.data&&d.data.job){ appMigWatch(); } }).catch(function(){}); })();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-grid">
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>What is it for?</h3>
|
||||||
|
<ul class="app-info-list">
|
||||||
|
<li>Keep all your recipes in one place</li><li>Import a recipe from a web page with one click</li><li>Plan the week's meals and get a shopping list out of it</li><li>Several people - the household can plan together</li><li>Share a recipe by link with family and friends</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>First steps</h3>
|
||||||
|
<ol class="app-info-list">
|
||||||
|
<li>Open recipes.DOMAIN in your browser</li><li>Create the admin account</li><li>Import your first recipe from a web page (Bookmarklet)</li><li>Try the meal planner</li><li>Invite the household</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>Documentation</h3>
|
||||||
|
<p><a href="https://docs.tandoor.dev/" target="_blank" class="app-info-link">Official documentation ↗</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var burger=document.querySelector('.nav-burger');
|
||||||
|
var sidebar=document.getElementById('sidebar');
|
||||||
|
var backdrop=document.querySelector('.nav-backdrop');
|
||||||
|
if(!burger||!sidebar||!backdrop)return;
|
||||||
|
function setOpen(open){
|
||||||
|
sidebar.classList.toggle('is-open',open);
|
||||||
|
document.body.classList.toggle('nav-open',open);
|
||||||
|
backdrop.hidden=!open;
|
||||||
|
burger.setAttribute('aria-expanded',open?'true':'false');
|
||||||
|
}
|
||||||
|
burger.addEventListener('click',function(){setOpen(!sidebar.classList.contains('is-open'));});
|
||||||
|
backdrop.addEventListener('click',function(){setOpen(false);});
|
||||||
|
document.addEventListener('keydown',function(e){
|
||||||
|
if(e.key==='Escape'&&sidebar.classList.contains('is-open'))setOpen(false);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
if (e.target.closest('a, button, .btn, input, select, textarea, .app-row-actions, .stack-detail-actions')) return;
|
||||||
|
var card = e.target.closest('[data-href]');
|
||||||
|
if (card) window.location.href = card.dataset.href;
|
||||||
|
});
|
||||||
|
async function checkBeforeDeploy(e, name) {
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name);
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok && data.data && data.data.deployed) {
|
||||||
|
e.preventDefault();
|
||||||
|
showAlert('This app is already installed.');
|
||||||
|
window.location.reload();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(err) {}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
async function syncTemplates() {
|
||||||
|
const btn = document.getElementById('sync-btn');
|
||||||
|
const toast = document.getElementById('sync-toast');
|
||||||
|
if (!btn) return;
|
||||||
|
const origText = btn.innerHTML;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.innerHTML = '↻ Refreshing...';
|
||||||
|
btn.classList.add('loading');
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/sync', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders())
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (toast) {
|
||||||
|
toast.textContent = data.ok ? (data.message || 'Templates refreshed') : ('Error: ' + (data.error || 'Unknown error'));
|
||||||
|
toast.className = 'sync-toast ' + (data.ok ? 'sync-toast-ok' : 'sync-toast-err');
|
||||||
|
toast.style.display = 'block';
|
||||||
|
setTimeout(function() { toast.style.display = 'none'; }, 5000);
|
||||||
|
}
|
||||||
|
if (data.ok && data.data && (data.data.new_apps && data.data.new_apps.length > 0 || data.data.updated && data.data.updated.length > 0)) {
|
||||||
|
setTimeout(function() { window.location.reload(); }, 1500);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (toast) {
|
||||||
|
toast.textContent = 'Network error: ' + err.message;
|
||||||
|
toast.className = 'sync-toast sync-toast-err';
|
||||||
|
toast.style.display = 'block';
|
||||||
|
setTimeout(function() { toast.style.display = 'none'; }, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btn.innerHTML = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
}
|
||||||
|
async function stackAction(event, name, action) {
|
||||||
|
const btn = event.currentTarget;
|
||||||
|
const origText = btn.textContent;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'In progress...';
|
||||||
|
btn.classList.add('loading');
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/stacks/' + name + '/' + action, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders())
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (!data.ok) {
|
||||||
|
showAlert('Error: ' + (data.error || 'Unknown error'));
|
||||||
|
btn.textContent = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (action === 'update') {
|
||||||
|
followUpdate(name, btn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.location.reload();
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Network error: ' + err.message);
|
||||||
|
btn.textContent = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function followUpdate(name, btn) {
|
||||||
|
var started = Date.now();
|
||||||
|
var timer = setInterval(async function() {
|
||||||
|
if (Date.now() - started > 30 * 60 * 1000) { clearInterval(timer); window.location.reload(); return; }
|
||||||
|
try {
|
||||||
|
var r = await fetch('/api/stacks/' + name);
|
||||||
|
var d = await r.json();
|
||||||
|
if (!d.ok || !d.data) return;
|
||||||
|
if (d.data.update_phase_label) btn.textContent = d.data.update_phase_label;
|
||||||
|
if (!d.data.updating) { clearInterval(timer); window.location.reload(); }
|
||||||
|
} catch (e) {}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
async function deleteOrphanStack(name) {
|
||||||
|
var modal = document.createElement('div');
|
||||||
|
modal.className = 'modal-overlay';
|
||||||
|
modal.id = 'delete-modal';
|
||||||
|
modal.innerHTML = '<div class="modal-card"><h3>Loading...</h3></div>';
|
||||||
|
modal.addEventListener('click', function(e) { if (e.target === modal) closeDeleteModal(); });
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name + '/hdd-data');
|
||||||
|
var data = await resp.json();
|
||||||
|
var hddInfo = '';
|
||||||
|
var checkboxHTML = '';
|
||||||
|
if (data.ok && data.data && data.data.has_hdd_data) {
|
||||||
|
hddInfo = '<div class="modal-hdd-info"><strong>Your data on the hard drive:</strong>';
|
||||||
|
data.data.hdd_paths.forEach(function(p) {
|
||||||
|
hddInfo += '<div class="modal-hdd-path">' + p.path + ' (' + (p.exists ? p.size_human : 'does not exist') + ')</div>';
|
||||||
|
});
|
||||||
|
hddInfo += '</div>';
|
||||||
|
checkboxHTML = '<label class="modal-checkbox"><input type="checkbox" id="delete-hdd-check"> Delete your data from the hard drive</label>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Delete app: ' + name + '</h3>' +
|
||||||
|
'<p style="color:var(--text-2);font-size:.9rem;margin-bottom:.75rem">This removes the containers, the volumes and the configuration files.</p>' +
|
||||||
|
'<div class="alert alert-warning" style="margin-bottom:.75rem">You cannot undo this!</div>' +
|
||||||
|
hddInfo + checkboxHTML +
|
||||||
|
'<div class="modal-actions">' +
|
||||||
|
'<button class="btn btn-outline" onclick="closeDeleteModal()">Cancel</button>' +
|
||||||
|
'<button class="btn btn-danger" id="confirm-delete-btn" onclick="confirmDelete(\'' + name + '\')">Delete</button>' +
|
||||||
|
'</div>';
|
||||||
|
} catch (err) {
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Error</h3><p style="color:var(--text-2)">Could not load the details: ' + err.message + '</p>' +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-outline" onclick="closeDeleteModal()">Close</button></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeDeleteModal() {
|
||||||
|
var modal = document.getElementById('delete-modal');
|
||||||
|
if (modal) modal.remove();
|
||||||
|
}
|
||||||
|
async function confirmDelete(name) {
|
||||||
|
var btn = document.getElementById('confirm-delete-btn');
|
||||||
|
var checkbox = document.getElementById('delete-hdd-check');
|
||||||
|
var removeHDD = checkbox ? checkbox.checked : false;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Deleting...';
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders()),
|
||||||
|
body: JSON.stringify({remove_hdd_data: removeHDD})
|
||||||
|
});
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok) {
|
||||||
|
var modal = document.getElementById('delete-modal');
|
||||||
|
var removedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_removed && data.data.hdd_paths_removed.length > 0) {
|
||||||
|
removedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Deleted data: ' + data.data.hdd_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
var preservedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_preserved && data.data.hdd_paths_preserved.length > 0) {
|
||||||
|
preservedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Kept data: ' + data.data.hdd_paths_preserved.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.hdd_note) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">' + data.data.hdd_note + '</p>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Deleted!</h3>' +
|
||||||
|
'<p style="color:var(--text-2)">The app (' + name + ') was deleted.</p>' +
|
||||||
|
removedInfo + preservedInfo +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-primary" onclick="window.location.href=\'/stacks\'">Close</button></div>';
|
||||||
|
} else {
|
||||||
|
showAlert('Error: ' + (data.error || 'Unknown error'));
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Delete';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Network error: ' + err.message);
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Delete';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function removeStack(name) {
|
||||||
|
var modal = document.createElement('div');
|
||||||
|
modal.className = 'modal-overlay';
|
||||||
|
modal.id = 'remove-modal';
|
||||||
|
modal.innerHTML = '<div class="modal-card"><h3>Loading...</h3></div>';
|
||||||
|
modal.addEventListener('click', function(e) { if (e.target === modal) closeRemoveModal(); });
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
try {
|
||||||
|
var [hddResp, backupResp] = await Promise.all([
|
||||||
|
fetch('/api/stacks/' + name + '/hdd-data').then(function(r) { return r.json(); }),
|
||||||
|
fetch('/api/stacks/' + name + '/backup-data').then(function(r) { return r.json(); })
|
||||||
|
]);
|
||||||
|
var sections = '';
|
||||||
|
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Always deleted:</strong>' +
|
||||||
|
'<ul style="margin:.25rem 0;padding-left:1.2rem;color:var(--text-2);font-size:.85rem">' +
|
||||||
|
'<li>Docker volumes (database, app configuration)</li>' +
|
||||||
|
'<li>Install configuration (app.yaml)</li>' +
|
||||||
|
'<li>Secondary backup schedule</li>' +
|
||||||
|
'</ul></div>';
|
||||||
|
|
||||||
|
var hddCheckbox = '';
|
||||||
|
if (hddResp.ok && hddResp.data && hddResp.data.has_hdd_data) {
|
||||||
|
var hddPaths = '';
|
||||||
|
hddResp.data.hdd_paths.forEach(function(p) {
|
||||||
|
hddPaths += '<div class="modal-hdd-path">' + p.path + ' (' + (p.exists ? p.size_human : 'does not exist') + ')</div>';
|
||||||
|
});
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Your data on the hard drive:</strong>' + hddPaths +
|
||||||
|
'<label class="modal-checkbox"><input type="checkbox" id="remove-hdd-check"> Delete your data</label>' +
|
||||||
|
'<div class="alert alert-info" style="margin-top:.5rem;font-size:.8rem" id="remove-hdd-keep-warning">' +
|
||||||
|
'If you reinstall the app, you need to import the data again, because the database is deleted. Data you keep is NOT backed up automatically any more.' +
|
||||||
|
'</div></div>';
|
||||||
|
hddCheckbox = '\x3Cscript>document.getElementById("remove-hdd-check").addEventListener("change",function(){document.getElementById("remove-hdd-keep-warning").style.display=this.checked?"none":"";});<\/script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
var backupCheckbox = '';
|
||||||
|
if (backupResp.ok && backupResp.data && backupResp.data.has_backups) {
|
||||||
|
var bkPaths = '';
|
||||||
|
backupResp.data.backup_paths.forEach(function(p) {
|
||||||
|
if (p.exists) bkPaths += '<div class="modal-hdd-path">' + p.path + ' (' + p.size_human + ')</div>';
|
||||||
|
});
|
||||||
|
if (bkPaths) {
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Backup data:</strong>' + bkPaths +
|
||||||
|
'<label class="modal-checkbox"><input type="checkbox" id="remove-backup-check"> Delete backup data</label>' +
|
||||||
|
'<div class="alert alert-info" style="margin-top:.5rem;font-size:.8rem">' +
|
||||||
|
'The nightly restic snapshots cannot be deleted one by one — they expire automatically under the retention rules.' +
|
||||||
|
'</div></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Remove app: ' + name + '</h3>' +
|
||||||
|
'<p style="color:var(--text-2);font-size:.9rem;margin-bottom:.75rem">The app goes back to "Not installed". The template stays, and you can install it again.</p>' +
|
||||||
|
'<div class="alert alert-warning" style="margin-bottom:.75rem">You cannot undo this!</div>' +
|
||||||
|
sections +
|
||||||
|
'<div class="modal-actions">' +
|
||||||
|
'<button class="btn btn-outline" onclick="closeRemoveModal()">Cancel</button>' +
|
||||||
|
'<button class="btn btn-danger" id="confirm-remove-btn" onclick="confirmRemoveStack(\'' + name + '\')">Remove</button>' +
|
||||||
|
'</div>' + hddCheckbox;
|
||||||
|
} catch (err) {
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Error</h3><p style="color:var(--text-2)">Could not load the details: ' + err.message + '</p>' +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-outline" onclick="closeRemoveModal()">Close</button></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeRemoveModal() {
|
||||||
|
var modal = document.getElementById('remove-modal');
|
||||||
|
if (modal) modal.remove();
|
||||||
|
}
|
||||||
|
async function confirmRemoveStack(name) {
|
||||||
|
var btn = document.getElementById('confirm-remove-btn');
|
||||||
|
var hddCheck = document.getElementById('remove-hdd-check');
|
||||||
|
var backupCheck = document.getElementById('remove-backup-check');
|
||||||
|
var removeHDD = hddCheck ? hddCheck.checked : false;
|
||||||
|
var removeBackups = backupCheck ? backupCheck.checked : false;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Removing...';
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name + '/remove', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders()),
|
||||||
|
body: JSON.stringify({remove_hdd_data: removeHDD, remove_backups: removeBackups})
|
||||||
|
});
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok) {
|
||||||
|
var modal = document.getElementById('remove-modal');
|
||||||
|
var removedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_removed && data.data.hdd_paths_removed.length > 0) {
|
||||||
|
removedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Deleted data: ' + data.data.hdd_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.backup_paths_removed && data.data.backup_paths_removed.length > 0) {
|
||||||
|
removedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Deleted backups: ' + data.data.backup_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
var preservedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_preserved && data.data.hdd_paths_preserved.length > 0) {
|
||||||
|
preservedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Kept data: ' + data.data.hdd_paths_preserved.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.hdd_note) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">' + data.data.hdd_note + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.backup_paths_refused && data.data.backup_paths_refused.length > 0) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Backups not deleted: ' + data.data.backup_paths_refused.join('; ') + '</p>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Removed!</h3>' +
|
||||||
|
'<p style="color:var(--text-2)">The app (' + name + ') was removed. You can install it again with the Install button.</p>' +
|
||||||
|
removedInfo + preservedInfo +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-primary" onclick="window.location.href=\'/stacks\'">Close</button></div>';
|
||||||
|
} else {
|
||||||
|
showAlert('Error: ' + (data.error || 'Unknown error'));
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Remove';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Network error: ' + err.message);
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Remove';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
+654
@@ -0,0 +1,654 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="hu" class="no-js">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tandoor Recipes — Felhom.eu</title>
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg?v=0.261.0">
|
||||||
|
<link rel="stylesheet" href="/static/style.css?v=0.261.0">
|
||||||
|
<meta name="csrf-token" content="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307">
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
document.documentElement.className=document.documentElement.className.replace('no-js','js');
|
||||||
|
function csrfHeaders(){var el=document.querySelector('meta[name="csrf-token"]');return el?{'X-CSRF-Token':el.content}:{};}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function felhomConfirm(el,question,onYes){
|
||||||
|
if(!el||el.dataset.fcOpen)return;
|
||||||
|
el.dataset.fcOpen='1';
|
||||||
|
var wrap=document.createElement('span');wrap.className='inline-confirm';
|
||||||
|
var q=document.createElement('span');q.className='inline-confirm-q';q.textContent=question;
|
||||||
|
var yes=document.createElement('button');yes.type='button';yes.className='btn btn-xs btn-danger';yes.textContent='Igen';
|
||||||
|
var no=document.createElement('button');no.type='button';no.className='btn btn-xs btn-outline';no.textContent='Mégse';
|
||||||
|
wrap.appendChild(q);wrap.appendChild(yes);wrap.appendChild(no);
|
||||||
|
el.style.display='none';el.parentNode.insertBefore(wrap,el.nextSibling);
|
||||||
|
function close(){wrap.remove();el.style.display='';delete el.dataset.fcOpen;}
|
||||||
|
no.addEventListener('click',close);
|
||||||
|
yes.addEventListener('click',function(){close();onYes();});
|
||||||
|
}
|
||||||
|
document.addEventListener('click',function(e){
|
||||||
|
var btn=e.target.closest?e.target.closest('[data-confirm]'):null;
|
||||||
|
if(!btn)return;
|
||||||
|
e.preventDefault();
|
||||||
|
felhomConfirm(btn,btn.getAttribute('data-confirm'),function(){
|
||||||
|
var form=btn.closest('form');
|
||||||
|
if(form){if(form.requestSubmit)form.requestSubmit(btn);else form.submit();}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('click',function(e){
|
||||||
|
var btn=e.target.closest?e.target.closest('.nav-group-toggle'):null;
|
||||||
|
if(!btn)return;
|
||||||
|
var group=btn.closest('.nav-group');
|
||||||
|
if(!group)return;
|
||||||
|
var willOpen=!group.classList.contains('is-open');
|
||||||
|
document.querySelectorAll('.nav-group.is-open').forEach(function(g){
|
||||||
|
g.classList.remove('is-open');
|
||||||
|
var t=g.querySelector('.nav-group-toggle');
|
||||||
|
if(t)t.setAttribute('aria-expanded','false');
|
||||||
|
});
|
||||||
|
if(willOpen){group.classList.add('is-open');btn.setAttribute('aria-expanded','true');}
|
||||||
|
});
|
||||||
|
function showAlert(msg){var o=document.createElement('div');o.className='modal-overlay';o.id='alert-modal';o.addEventListener('click',function(e){if(e.target===o)o.remove();});var c=document.createElement('div');c.className='modal-card';c.innerHTML='<h3>Üzenet</h3><pre style="white-space:pre-wrap;word-break:break-word;background:var(--bg-2);padding:.75rem;border-radius:.375rem;font-size:.85rem;max-height:60vh;overflow-y:auto;user-select:text;cursor:text">'+msg.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')+'</pre><div class="modal-actions"><button class="btn btn-primary" onclick="document.getElementById(\'alert-modal\').remove()">OK</button></div>';o.appendChild(c);document.body.appendChild(o);}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">
|
||||||
|
<symbol id="i-hard-drive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 16h.01" /> <path d="M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /> <path d="M21.946 12.013H2.054" /> <path d="M6 16h.01" /></symbol>
|
||||||
|
<symbol id="i-cpu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20v2" /> <path d="M12 2v2" /> <path d="M17 20v2" /> <path d="M17 2v2" /> <path d="M2 12h2" /> <path d="M2 17h2" /> <path d="M2 7h2" /> <path d="M20 12h2" /> <path d="M20 17h2" /> <path d="M20 7h2" /> <path d="M7 20v2" /> <path d="M7 2v2" /> <rect x="4" y="4" width="16" height="16" rx="2" /> <rect x="8" y="8" width="8" height="8" rx="1" /></symbol>
|
||||||
|
<symbol id="i-memory-stick" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 12v-2" /> <path d="M12 18v-2" /> <path d="M16 12v-2" /> <path d="M16 18v-2" /> <path d="M2 11h1.5" /> <path d="M20 18v-2" /> <path d="M20.5 11H22" /> <path d="M4 18v-2" /> <path d="M8 12v-2" /> <path d="M8 18v-2" /> <rect x="2" y="6" width="20" height="10" rx="2" /></symbol>
|
||||||
|
<symbol id="i-thermometer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z" /></symbol>
|
||||||
|
<symbol id="i-triangle-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" /></symbol>
|
||||||
|
<symbol id="i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2" /> <path d="M7 11V7a5 5 0 0 1 10 0v4" /></symbol>
|
||||||
|
<symbol id="i-cloud" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /></symbol>
|
||||||
|
<symbol id="i-square" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" /></symbol>
|
||||||
|
<symbol id="i-rotate-cw" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" /> <path d="M21 3v5h-5" /></symbol>
|
||||||
|
<symbol id="i-file-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" /> <path d="M14 2v5a1 1 0 0 0 1 1h5" /> <path d="M10 9H8" /> <path d="M16 13H8" /> <path d="M16 17H8" /></symbol>
|
||||||
|
<symbol id="i-external-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6" /> <path d="M10 14 21 3" /> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" /></symbol>
|
||||||
|
<symbol id="i-shield" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /></symbol>
|
||||||
|
<symbol id="i-server" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="8" x="2" y="2" rx="2" ry="2" /> <rect width="20" height="8" x="2" y="14" rx="2" ry="2" /> <line x1="6" x2="6.01" y1="6" y2="6" /> <line x1="6" x2="6.01" y1="18" y2="18" /></symbol>
|
||||||
|
<symbol id="i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3" /> <circle cx="6" cy="12" r="3" /> <circle cx="18" cy="19" r="3" /> <line x1="8.59" x2="15.42" y1="13.51" y2="17.49" /> <line x1="15.41" x2="8.59" y1="6.51" y2="10.49" /></symbol>
|
||||||
|
<symbol id="i-layout-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="7" height="7" x="3" y="3" rx="1" /> <rect width="7" height="7" x="14" y="3" rx="1" /> <rect width="7" height="7" x="14" y="14" rx="1" /> <rect width="7" height="7" x="3" y="14" rx="1" /></symbol>
|
||||||
|
<symbol id="i-rocket" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91 0z" /> <path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" /> <path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" /> <path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" /></symbol>
|
||||||
|
<symbol id="i-settings" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /> <circle cx="12" cy="12" r="3" /></symbol>
|
||||||
|
<symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0" /> <path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></symbol>
|
||||||
|
<symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18" /> <path d="m6 6 12 12" /></symbol>
|
||||||
|
<symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></symbol>
|
||||||
|
<symbol id="i-pencil" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" /> <path d="m15 5 4 4" /></symbol>
|
||||||
|
<symbol id="i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /> <path d="M12 16v-4" /> <path d="M12 8h.01" /></symbol>
|
||||||
|
<symbol id="i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15V3" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="m7 10 5 5 5-5" /></symbol>
|
||||||
|
<symbol id="i-upload" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12" /> <path d="m17 8-5-5-5 5" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /></symbol>
|
||||||
|
<symbol id="i-trash-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6" /> <path d="M14 11v6" /> <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /> <path d="M3 6h18" /> <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /></symbol>
|
||||||
|
<symbol id="i-wrench" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z" /></symbol>
|
||||||
|
<symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /> <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /></symbol>
|
||||||
|
<symbol id="i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34" /> <circle cx="11" cy="11" r="8" /></symbol>
|
||||||
|
<symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14" /> <path d="M12 5v14" /></symbol>
|
||||||
|
<symbol id="i-chevron-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></symbol>
|
||||||
|
<symbol id="i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z" /></symbol>
|
||||||
|
<symbol id="i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="14" y="3" width="5" height="18" rx="1" /> <rect x="5" y="3" width="5" height="18" rx="1" /></symbol>
|
||||||
|
<symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16" /> <path d="M4 6h16" /> <path d="M4 18h16" /></symbol>
|
||||||
|
</svg>
|
||||||
|
<header class="mobile-topbar">
|
||||||
|
<a href="/" class="mobile-topbar-logo"><img src="/static/felhom-logo.svg?v=0.261.0" alt="Felhom.eu"></a>
|
||||||
|
<button type="button" class="nav-burger" aria-expanded="false" aria-controls="sidebar" aria-label="Menü">
|
||||||
|
<svg class="ico"><use href="#i-menu"/></svg>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<div class="nav-backdrop" hidden></div>
|
||||||
|
<nav class="sidebar" id="sidebar">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<img src="/static/felhom-logo.svg?v=0.261.0" alt="Felhom.eu" class="sidebar-logo">
|
||||||
|
</div>
|
||||||
|
<ul class="nav-links">
|
||||||
|
<li><a href="/launcher" class=""><svg class="ico"><use href="#i-rocket"/></svg>Indítópult</a></li>
|
||||||
|
<li><a href="/dashboard" class=""><svg class="ico"><use href="#i-layout-grid"/></svg>Vezérlőpult</a></li>
|
||||||
|
<li><a href="/stacks" class="active"><svg class="ico"><use href="#i-cloud"/></svg>Alkalmazások</a></li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-storage"><svg class="ico"><use href="#i-hard-drive"/></svg>Tárhely<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-storage" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/storage" class="">Meghajtók</a></li>
|
||||||
|
<li><a href="/storage/network" class="">Hálózati tárhely</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-backups"><svg class="ico"><use href="#i-shield"/></svg>Biztonsági mentés<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-backups" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/backups" class="">Áttekintés</a></li>
|
||||||
|
<li><a href="/backups/remote" class="">Távoli mentés</a></li>
|
||||||
|
<li><a href="/backups/apps" class="">Alkalmazások</a></li>
|
||||||
|
<li><a href="/backups/restore" class="">Visszaállítás</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-group">
|
||||||
|
<button type="button" class="nav-group-toggle" aria-expanded="false" aria-controls="nav-group-sharing"><svg class="ico"><use href="#i-share"/></svg>Megosztás<svg class="ico nav-chevron"><use href="#i-chevron-down"/></svg></button>
|
||||||
|
<ul id="nav-group-sharing" class="nav-links nav-links-sub nav-links-nested">
|
||||||
|
<li><a href="/sharing" class="">Hálózati megosztás</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="/monitoring" class=""><svg class="ico"><use href="#i-cpu"/></svg>Rendszermonitor</a></li>
|
||||||
|
<li><a href="/debug" class=""><svg class="ico"><use href="#i-wrench"/></svg>Debug</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-bottom">
|
||||||
|
<div class="nav-group-label">Beállítások</div>
|
||||||
|
<ul class="nav-links nav-links-sub">
|
||||||
|
<li><a href="/settings" class=""><svg class="ico"><use href="#i-settings"/></svg>Rendszer</a></li>
|
||||||
|
<li><a href="/settings/notifications" class=""><svg class="ico"><use href="#i-bell"/></svg>Értesítések</a></li>
|
||||||
|
<li><a href="/settings/security" class=""><svg class="ico"><use href="#i-lock"/></svg>Biztonság és hozzáférés</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<span class="version">0.261.0</span><details class="lang-globe">
|
||||||
|
<summary class="lang-globe-btn" aria-label="Nyelv" title="Nyelv"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10" /><path d="M2 12h20" /><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg></summary>
|
||||||
|
<ul class="lang-globe-menu">
|
||||||
|
<li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307"><input type="hidden" name="back" value="/apps/tandoor"><button type="submit" name="lang" value="hu" lang="hu" class="lang-globe-item current" aria-current="true">Magyar</button></form></li>
|
||||||
|
<li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="b0f2927caee41c5a97de77202486f9d0a2d3bb97124581393b77751acb8f4307"><input type="hidden" name="back" value="/apps/tandoor"><button type="submit" name="lang" value="en" lang="en" class="lang-globe-item">English</button></form></li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
<a href="/logout" class="logout-link">Kijelentkezés ↗</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<main class="content">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="alerts-container">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="alert-banner alert-banner-warning">
|
||||||
|
<span class="alert-icon"><svg class="ico"><use href="#i-triangle-alert"/></svg></span>
|
||||||
|
<span class="alert-message">Hub kapcsolat kikapcsolva — a központi monitoring nem aktív</span>
|
||||||
|
<a href="/monitoring" class="alert-link">Rendszermonitor →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<div style="display:flex;align-items:center;gap:1rem">
|
||||||
|
<a href="/stacks" class="btn btn-sm btn-outline">← Alkalmazások</a>
|
||||||
|
<h2>Tandoor Recipes</h2>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;align-items:center;gap:.5rem">
|
||||||
|
|
||||||
|
<span class="stack-state-badge state-warn">Nem egészséges</span>
|
||||||
|
|
||||||
|
|
||||||
|
<span class="tag tag-warn" title="Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.">Frissítés elérhető — ma</span>
|
||||||
|
<a href="https://recipes.enkisfelhom.hu" target="_blank" class="btn btn-sm btn-outline">Megnyitás ↗</a>
|
||||||
|
<a href="/stacks/tandoor/logs" class="btn btn-sm btn-outline">Napló</a>
|
||||||
|
|
||||||
|
<a href="/stacks/tandoor/export" class="btn btn-sm btn-outline">Exportálás</a>
|
||||||
|
<a href="/stacks/tandoor/deploy" class="btn btn-sm btn-outline">Beállítások</a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-hero">
|
||||||
|
<img class="app-info-logo" src="/static/assets/tandoor-logo.svg"
|
||||||
|
alt="Tandoor Recipes" data-fallback="/static/app-placeholder.svg"
|
||||||
|
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='\/static\/assets\/tandoor-logo.png';}else if(this.dataset.fallback&&this.dataset.step==='1'){this.dataset.step='2';this.src=this.dataset.fallback;}else{this.onerror=null;this.style.visibility='hidden';}">
|
||||||
|
<div class="app-info-hero-text">
|
||||||
|
|
||||||
|
<p class="app-info-tagline">Receptkezelő és étkezés tervező a családnak</p>
|
||||||
|
|
||||||
|
<div class="stack-meta-badges">
|
||||||
|
<span class="meta-badge">~512M RAM</span>
|
||||||
|
<span class="meta-badge">home</span>
|
||||||
|
|
||||||
|
<span class="meta-badge meta-badge-ok">Pi kompatibilis</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-screenshots" id="screenshots">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-1.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-2.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
<img src="/static/assets/tandoor-screenshot-3.webp" alt="" class="app-screenshot"
|
||||||
|
onerror="this.style.display='none'">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card" style="margin-top:1rem">
|
||||||
|
<h3>Áthelyezés másik tárhelyre</h3>
|
||||||
|
<p class="form-hint">Ennek az alkalmazásnak az adatait másik csatlakoztatott tárhelyre helyezheted át. Az alkalmazás az áthelyezés alatt rövid időre leáll, az adatok pedig csak az ellenőrzés és a sikeres újraindítás után törlődnek a régi helyről.</p>
|
||||||
|
<div style="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;margin-top:.5rem">
|
||||||
|
<select id="app-migrate-target" class="btn btn-sm btn-outline">
|
||||||
|
<option value="">Válassz céltárhelyet…</option>
|
||||||
|
<option value="/mnt/felhom-drives/scratch_hdd">SCRATCH HDD (/mnt/felhom-drives/scratch_hdd)</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-outline" onclick="appMigrate(this,'tandoor','Tandoor Recipes')">Áthelyezés</button>
|
||||||
|
</div>
|
||||||
|
<div id="app-migrate-progress" style="display:none;margin-top:.75rem;padding:.75rem;border:1px solid var(--blue);border-radius:6px;background:rgba(0,136,204,0.06)"></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function appMigFmtGB(b){ return (Number(b||0)/1e9).toFixed(1)+' GB'; }
|
||||||
|
function appMigRender(job){
|
||||||
|
var names={stop:'Leállítás',copy:'Adatok másolása',verify:'Ellenőrzés',flip:'Újratelepítés',redeploy:'Újratelepítés',cleanup:'Régi adatok törlése'};
|
||||||
|
var s=names[job.phase]||job.phase;
|
||||||
|
if(job.phase==='copy'&&job.bytes_total>0){ s+=' ('+Math.floor(100*job.bytes_done/job.bytes_total)+'% — '+appMigFmtGB(job.bytes_done)+'/'+appMigFmtGB(job.bytes_total)+')'; }
|
||||||
|
return s+'…';
|
||||||
|
}
|
||||||
|
function appMigWatch(){
|
||||||
|
var panel=document.getElementById('app-migrate-progress');
|
||||||
|
if(panel) panel.style.display='block';
|
||||||
|
function tick(){
|
||||||
|
fetch('/api/storage/migrate/status').then(function(r){return r.json();}).then(function(d){
|
||||||
|
var job=d.data&&d.data.job;
|
||||||
|
if(!job){ if(panel) panel.textContent='Nincs folyamatban áthelyezés.'; return; }
|
||||||
|
if(panel) panel.innerHTML=appMigRender(job);
|
||||||
|
if(job.phase==='done'){ if(panel) panel.innerHTML+='<br><strong>Kész</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||||
|
if(job.phase==='aborted'){ if(panel) panel.innerHTML+='<br><strong style="color:var(--danger,#c0392b)">Megszakadt: '+(job.error||'')+'</strong><br>A régi adatok érintetlenek.'; return; }
|
||||||
|
setTimeout(tick,1500);
|
||||||
|
}).catch(function(){ setTimeout(tick,2000); });
|
||||||
|
}
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
function appMigrate(btn,app,label){
|
||||||
|
var sel=document.getElementById('app-migrate-target');
|
||||||
|
var target=sel?sel.value:'';
|
||||||
|
if(!target){ showAlert('Válassz céltárhelyet.'); return; }
|
||||||
|
felhomConfirm(btn,'Áthelyezed a(z) '+label+' adatait ide: '+target+'? Az alkalmazás rövid időre leáll. A régi adatok csak sikeres áthelyezés után törlődnek.',function(){
|
||||||
|
fetch('/api/storage/migrate-app',{method:'POST',headers:Object.assign({'Content-Type':'application/json'},csrfHeaders()),body:JSON.stringify({app:app,target:target})})
|
||||||
|
.then(function(r){return r.json();}).then(function(d){ if(d.ok){ appMigWatch(); } else { showAlert('Hiba: '+(d.error||'ismeretlen')); } })
|
||||||
|
.catch(function(e){ showAlert('Hiba: '+e); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(function(){ fetch('/api/storage/migrate/status').then(function(r){return r.json();}).then(function(d){ if(d.data&&d.data.job){ appMigWatch(); } }).catch(function(){}); })();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-grid">
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>Mire használható?</h3>
|
||||||
|
<ul class="app-info-list">
|
||||||
|
<li>Receptek gyűjtése és rendszerezése egy helyen</li><li>Receptek importálása weboldalakról egy kattintással</li><li>Heti étkezés tervezés és bevásárlólista generálás</li><li>Több felhasználó - a család együtt tervezhet</li><li>Receptek megosztása linkkel családtagokkal, barátokkal</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>Első lépések</h3>
|
||||||
|
<ol class="app-info-list">
|
||||||
|
<li>Nyisd meg a recipes.DOMAIN címet a böngészőben</li><li>Hozd létre az admin fiókot</li><li>Importáld az első receptet egy weboldalról (Bookmarklet)</li><li>Próbáld ki az étkezés tervezőt</li><li>Hívd meg a családtagokat</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-info-card">
|
||||||
|
<h3>Dokumentáció</h3>
|
||||||
|
<p><a href="https://docs.tandoor.dev/" target="_blank" class="app-info-link">Hivatalos dokumentáció ↗</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var burger=document.querySelector('.nav-burger');
|
||||||
|
var sidebar=document.getElementById('sidebar');
|
||||||
|
var backdrop=document.querySelector('.nav-backdrop');
|
||||||
|
if(!burger||!sidebar||!backdrop)return;
|
||||||
|
function setOpen(open){
|
||||||
|
sidebar.classList.toggle('is-open',open);
|
||||||
|
document.body.classList.toggle('nav-open',open);
|
||||||
|
backdrop.hidden=!open;
|
||||||
|
burger.setAttribute('aria-expanded',open?'true':'false');
|
||||||
|
}
|
||||||
|
burger.addEventListener('click',function(){setOpen(!sidebar.classList.contains('is-open'));});
|
||||||
|
backdrop.addEventListener('click',function(){setOpen(false);});
|
||||||
|
document.addEventListener('keydown',function(e){
|
||||||
|
if(e.key==='Escape'&&sidebar.classList.contains('is-open'))setOpen(false);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
if (e.target.closest('a, button, .btn, input, select, textarea, .app-row-actions, .stack-detail-actions')) return;
|
||||||
|
var card = e.target.closest('[data-href]');
|
||||||
|
if (card) window.location.href = card.dataset.href;
|
||||||
|
});
|
||||||
|
async function checkBeforeDeploy(e, name) {
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name);
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok && data.data && data.data.deployed) {
|
||||||
|
e.preventDefault();
|
||||||
|
showAlert('Ez az alkalmazás már telepítve van.');
|
||||||
|
window.location.reload();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(err) {}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
async function syncTemplates() {
|
||||||
|
const btn = document.getElementById('sync-btn');
|
||||||
|
const toast = document.getElementById('sync-toast');
|
||||||
|
if (!btn) return;
|
||||||
|
const origText = btn.innerHTML;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.innerHTML = '↻ Frissítés...';
|
||||||
|
btn.classList.add('loading');
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/sync', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders())
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (toast) {
|
||||||
|
toast.textContent = data.ok ? (data.message || 'Sablonok frissítve') : ('Hiba: ' + (data.error || 'Ismeretlen hiba'));
|
||||||
|
toast.className = 'sync-toast ' + (data.ok ? 'sync-toast-ok' : 'sync-toast-err');
|
||||||
|
toast.style.display = 'block';
|
||||||
|
setTimeout(function() { toast.style.display = 'none'; }, 5000);
|
||||||
|
}
|
||||||
|
if (data.ok && data.data && (data.data.new_apps && data.data.new_apps.length > 0 || data.data.updated && data.data.updated.length > 0)) {
|
||||||
|
setTimeout(function() { window.location.reload(); }, 1500);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (toast) {
|
||||||
|
toast.textContent = 'Hálózati hiba: ' + err.message;
|
||||||
|
toast.className = 'sync-toast sync-toast-err';
|
||||||
|
toast.style.display = 'block';
|
||||||
|
setTimeout(function() { toast.style.display = 'none'; }, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btn.innerHTML = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
}
|
||||||
|
async function stackAction(event, name, action) {
|
||||||
|
const btn = event.currentTarget;
|
||||||
|
const origText = btn.textContent;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Folyamatban...';
|
||||||
|
btn.classList.add('loading');
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/stacks/' + name + '/' + action, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders())
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (!data.ok) {
|
||||||
|
showAlert('Hiba: ' + (data.error || 'Ismeretlen hiba'));
|
||||||
|
btn.textContent = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (action === 'update') {
|
||||||
|
followUpdate(name, btn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.location.reload();
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Hálózati hiba: ' + err.message);
|
||||||
|
btn.textContent = origText;
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.classList.remove('loading');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function followUpdate(name, btn) {
|
||||||
|
var started = Date.now();
|
||||||
|
var timer = setInterval(async function() {
|
||||||
|
if (Date.now() - started > 30 * 60 * 1000) { clearInterval(timer); window.location.reload(); return; }
|
||||||
|
try {
|
||||||
|
var r = await fetch('/api/stacks/' + name);
|
||||||
|
var d = await r.json();
|
||||||
|
if (!d.ok || !d.data) return;
|
||||||
|
if (d.data.update_phase_label) btn.textContent = d.data.update_phase_label;
|
||||||
|
if (!d.data.updating) { clearInterval(timer); window.location.reload(); }
|
||||||
|
} catch (e) {}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
async function deleteOrphanStack(name) {
|
||||||
|
var modal = document.createElement('div');
|
||||||
|
modal.className = 'modal-overlay';
|
||||||
|
modal.id = 'delete-modal';
|
||||||
|
modal.innerHTML = '<div class="modal-card"><h3>Betöltés...</h3></div>';
|
||||||
|
modal.addEventListener('click', function(e) { if (e.target === modal) closeDeleteModal(); });
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name + '/hdd-data');
|
||||||
|
var data = await resp.json();
|
||||||
|
var hddInfo = '';
|
||||||
|
var checkboxHTML = '';
|
||||||
|
if (data.ok && data.data && data.data.has_hdd_data) {
|
||||||
|
hddInfo = '<div class="modal-hdd-info"><strong>Felhasználói adatok a merevlemezen:</strong>';
|
||||||
|
data.data.hdd_paths.forEach(function(p) {
|
||||||
|
hddInfo += '<div class="modal-hdd-path">' + p.path + ' (' + (p.exists ? p.size_human : 'nem létezik') + ')</div>';
|
||||||
|
});
|
||||||
|
hddInfo += '</div>';
|
||||||
|
checkboxHTML = '<label class="modal-checkbox"><input type="checkbox" id="delete-hdd-check"> Felhasználói adatok törlése a merevlemezről</label>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Alkalmazás törlése: ' + name + '</h3>' +
|
||||||
|
'<p style="color:var(--text-2);font-size:.9rem;margin-bottom:.75rem">Ez a művelet eltávolítja a konténereket, a köteteket és a konfigurációs fájlokat.</p>' +
|
||||||
|
'<div class="alert alert-warning" style="margin-bottom:.75rem">Ez a művelet nem visszavonható!</div>' +
|
||||||
|
hddInfo + checkboxHTML +
|
||||||
|
'<div class="modal-actions">' +
|
||||||
|
'<button class="btn btn-outline" onclick="closeDeleteModal()">Mégsem</button>' +
|
||||||
|
'<button class="btn btn-danger" id="confirm-delete-btn" onclick="confirmDelete(\'' + name + '\')">Törlés</button>' +
|
||||||
|
'</div>';
|
||||||
|
} catch (err) {
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Hiba</h3><p style="color:var(--text-2)">Nem sikerült lekérni az adatokat: ' + err.message + '</p>' +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-outline" onclick="closeDeleteModal()">Bezárás</button></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeDeleteModal() {
|
||||||
|
var modal = document.getElementById('delete-modal');
|
||||||
|
if (modal) modal.remove();
|
||||||
|
}
|
||||||
|
async function confirmDelete(name) {
|
||||||
|
var btn = document.getElementById('confirm-delete-btn');
|
||||||
|
var checkbox = document.getElementById('delete-hdd-check');
|
||||||
|
var removeHDD = checkbox ? checkbox.checked : false;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Törlés folyamatban...';
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders()),
|
||||||
|
body: JSON.stringify({remove_hdd_data: removeHDD})
|
||||||
|
});
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok) {
|
||||||
|
var modal = document.getElementById('delete-modal');
|
||||||
|
var removedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_removed && data.data.hdd_paths_removed.length > 0) {
|
||||||
|
removedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Törölt adatok: ' + data.data.hdd_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
var preservedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_preserved && data.data.hdd_paths_preserved.length > 0) {
|
||||||
|
preservedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Megőrzött adatok: ' + data.data.hdd_paths_preserved.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.hdd_note) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">' + data.data.hdd_note + '</p>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Sikeresen törölve!</h3>' +
|
||||||
|
'<p style="color:var(--text-2)">Az alkalmazás (' + name + ') törölve lett.</p>' +
|
||||||
|
removedInfo + preservedInfo +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-primary" onclick="window.location.href=\'/stacks\'">Bezárás</button></div>';
|
||||||
|
} else {
|
||||||
|
showAlert('Hiba: ' + (data.error || 'Ismeretlen hiba'));
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Törlés';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Hálózati hiba: ' + err.message);
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Törlés';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function removeStack(name) {
|
||||||
|
var modal = document.createElement('div');
|
||||||
|
modal.className = 'modal-overlay';
|
||||||
|
modal.id = 'remove-modal';
|
||||||
|
modal.innerHTML = '<div class="modal-card"><h3>Betöltés...</h3></div>';
|
||||||
|
modal.addEventListener('click', function(e) { if (e.target === modal) closeRemoveModal(); });
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
try {
|
||||||
|
var [hddResp, backupResp] = await Promise.all([
|
||||||
|
fetch('/api/stacks/' + name + '/hdd-data').then(function(r) { return r.json(); }),
|
||||||
|
fetch('/api/stacks/' + name + '/backup-data').then(function(r) { return r.json(); })
|
||||||
|
]);
|
||||||
|
var sections = '';
|
||||||
|
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Mindig törlődik:</strong>' +
|
||||||
|
'<ul style="margin:.25rem 0;padding-left:1.2rem;color:var(--text-2);font-size:.85rem">' +
|
||||||
|
'<li>Docker kötetek (adatbázis, alkalmazás konfiguráció)</li>' +
|
||||||
|
'<li>Telepítési konfiguráció (app.yaml)</li>' +
|
||||||
|
'<li>Másodlagos mentés ütemezése</li>' +
|
||||||
|
'</ul></div>';
|
||||||
|
|
||||||
|
var hddCheckbox = '';
|
||||||
|
if (hddResp.ok && hddResp.data && hddResp.data.has_hdd_data) {
|
||||||
|
var hddPaths = '';
|
||||||
|
hddResp.data.hdd_paths.forEach(function(p) {
|
||||||
|
hddPaths += '<div class="modal-hdd-path">' + p.path + ' (' + (p.exists ? p.size_human : 'nem létezik') + ')</div>';
|
||||||
|
});
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Felhasználói adatok a merevlemezen:</strong>' + hddPaths +
|
||||||
|
'<label class="modal-checkbox"><input type="checkbox" id="remove-hdd-check"> Felhasználói adatok törlése</label>' +
|
||||||
|
'<div class="alert alert-info" style="margin-top:.5rem;font-size:.8rem" id="remove-hdd-keep-warning">' +
|
||||||
|
'Ha újratelepíti az alkalmazást, az adatokat újra importálnia kell, mivel az adatbázis törlődik. A megtartott adatok a továbbiakban NEM lesznek automatikusan mentve.' +
|
||||||
|
'</div></div>';
|
||||||
|
hddCheckbox = '\x3Cscript>document.getElementById("remove-hdd-check").addEventListener("change",function(){document.getElementById("remove-hdd-keep-warning").style.display=this.checked?"none":"";});<\/script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
var backupCheckbox = '';
|
||||||
|
if (backupResp.ok && backupResp.data && backupResp.data.has_backups) {
|
||||||
|
var bkPaths = '';
|
||||||
|
backupResp.data.backup_paths.forEach(function(p) {
|
||||||
|
if (p.exists) bkPaths += '<div class="modal-hdd-path">' + p.path + ' (' + p.size_human + ')</div>';
|
||||||
|
});
|
||||||
|
if (bkPaths) {
|
||||||
|
sections += '<div class="modal-section">' +
|
||||||
|
'<strong>Mentési adatok:</strong>' + bkPaths +
|
||||||
|
'<label class="modal-checkbox"><input type="checkbox" id="remove-backup-check"> Mentési adatok törlése</label>' +
|
||||||
|
'<div class="alert alert-info" style="margin-top:.5rem;font-size:.8rem">' +
|
||||||
|
'Az éjszakai restic pillanatképek nem törölhetők egyenként — a megőrzési szabályok szerint automatikusan elavulnak.' +
|
||||||
|
'</div></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Alkalmazás eltávolítása: ' + name + '</h3>' +
|
||||||
|
'<p style="color:var(--text-2);font-size:.9rem;margin-bottom:.75rem">Az alkalmazás visszaáll "Nincs telepítve" állapotba. A sablon megmarad, újratelepíthető.</p>' +
|
||||||
|
'<div class="alert alert-warning" style="margin-bottom:.75rem">Ez a művelet nem visszavonható!</div>' +
|
||||||
|
sections +
|
||||||
|
'<div class="modal-actions">' +
|
||||||
|
'<button class="btn btn-outline" onclick="closeRemoveModal()">Mégsem</button>' +
|
||||||
|
'<button class="btn btn-danger" id="confirm-remove-btn" onclick="confirmRemoveStack(\'' + name + '\')">Eltávolítás</button>' +
|
||||||
|
'</div>' + hddCheckbox;
|
||||||
|
} catch (err) {
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Hiba</h3><p style="color:var(--text-2)">Nem sikerült lekérni az adatokat: ' + err.message + '</p>' +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-outline" onclick="closeRemoveModal()">Bezárás</button></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeRemoveModal() {
|
||||||
|
var modal = document.getElementById('remove-modal');
|
||||||
|
if (modal) modal.remove();
|
||||||
|
}
|
||||||
|
async function confirmRemoveStack(name) {
|
||||||
|
var btn = document.getElementById('confirm-remove-btn');
|
||||||
|
var hddCheck = document.getElementById('remove-hdd-check');
|
||||||
|
var backupCheck = document.getElementById('remove-backup-check');
|
||||||
|
var removeHDD = hddCheck ? hddCheck.checked : false;
|
||||||
|
var removeBackups = backupCheck ? backupCheck.checked : false;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Eltávolítás folyamatban...';
|
||||||
|
try {
|
||||||
|
var resp = await fetch('/api/stacks/' + name + '/remove', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: Object.assign({'Content-Type': 'application/json'}, csrfHeaders()),
|
||||||
|
body: JSON.stringify({remove_hdd_data: removeHDD, remove_backups: removeBackups})
|
||||||
|
});
|
||||||
|
var data = await resp.json();
|
||||||
|
if (data.ok) {
|
||||||
|
var modal = document.getElementById('remove-modal');
|
||||||
|
var removedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_removed && data.data.hdd_paths_removed.length > 0) {
|
||||||
|
removedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Törölt adatok: ' + data.data.hdd_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.backup_paths_removed && data.data.backup_paths_removed.length > 0) {
|
||||||
|
removedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Törölt mentések: ' + data.data.backup_paths_removed.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
var preservedInfo = '';
|
||||||
|
if (data.data && data.data.hdd_paths_preserved && data.data.hdd_paths_preserved.length > 0) {
|
||||||
|
preservedInfo = '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Megőrzött adatok: ' + data.data.hdd_paths_preserved.join(', ') + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.hdd_note) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">' + data.data.hdd_note + '</p>';
|
||||||
|
}
|
||||||
|
if (data.data && data.data.backup_paths_refused && data.data.backup_paths_refused.length > 0) {
|
||||||
|
preservedInfo += '<p style="color:var(--text-2);font-size:.85rem;margin-top:.5rem">Nem törölt mentések: ' + data.data.backup_paths_refused.join('; ') + '</p>';
|
||||||
|
}
|
||||||
|
modal.querySelector('.modal-card').innerHTML =
|
||||||
|
'<h3>Sikeresen eltávolítva!</h3>' +
|
||||||
|
'<p style="color:var(--text-2)">Az alkalmazás (' + name + ') eltávolítva. Újratelepíthető a Telepítés gombbal.</p>' +
|
||||||
|
removedInfo + preservedInfo +
|
||||||
|
'<div class="modal-actions"><button class="btn btn-primary" onclick="window.location.href=\'/stacks\'">Bezárás</button></div>';
|
||||||
|
} else {
|
||||||
|
showAlert('Hiba: ' + (data.error || 'Ismeretlen hiba'));
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Eltávolítás';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showAlert('Hálózati hiba: ' + err.message);
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Eltávolítás';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
21:15:25 ==== tandoor: ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (sub=recipes, class=db-postgres)
|
||||||
|
21:15:25 [1] tandoor already deployed — reusing
|
||||||
|
21:15:27 [2] seeding through the app's own front door
|
||||||
|
21:15:37 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||||
|
21:15:40 tandoor: seeded superuser drill316903
|
||||||
|
21:15:40 [3] control C1 — reading the seed back BEFORE the update
|
||||||
|
21:15:46 tandoor: readback of the seeded account found=True
|
||||||
|
21:15:46 [4] „Mentés most" -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||||
|
21:16:42 [4] backup idle; last=None
|
||||||
|
21:16:43 [5] drill commit c7477d1fb921: tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (push rc=0)
|
||||||
|
21:16:47 [5] badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
|
21:16:47 [5] badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
|
21:16:47 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||||
|
21:16:47 + 0.0s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||||
|
21:16:48 + 1.0s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||||
|
21:17:42 + 54.3s phase=starting label=Indítás az új verzióval… err=None hold=None
|
||||||
|
21:17:46 + 58.4s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||||
|
21:22:49 + 361.9s phase=failed label=A frissítés nem sikerült err=A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza. hold=A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.
|
||||||
|
21:22:49 [7] reading the seed back AFTER the update
|
||||||
|
21:22:52 tandoor: READBACK UNUSABLE — a username that cannot exist did not read as absent (None) :: Error response from daemon: No such container: tandoor
|
||||||
|
21:22:54 [8] pinned = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
21:22:54 [8] installed = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.13', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
|
21:22:54 [8] compose = ['image: ghcr.io/tandoorrecipes/recipes:2.6.15', 'image: postgres:16-alpine']
|
||||||
|
21:22:54 [8] inspect = []
|
||||||
|
21:22:54 [9] verdict failed -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/update-night-2026-09-21/apps/tandoor/verdict.json
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"before": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": []
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"accepted": true,
|
||||||
|
"http": "202",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"t": 0.0,
|
||||||
|
"phase": "safety-dump",
|
||||||
|
"label": "Adatbázis pillanatkép…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 1.0,
|
||||||
|
"phase": "pulling",
|
||||||
|
"label": "Új verzió letöltése…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 54.3,
|
||||||
|
"phase": "starting",
|
||||||
|
"label": "Indítás az új verzióval…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 58.4,
|
||||||
|
"phase": "verifying",
|
||||||
|
"label": "Működés ellenőrzése…",
|
||||||
|
"updating": true,
|
||||||
|
"error": null,
|
||||||
|
"hold": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 361.9,
|
||||||
|
"phase": "failed",
|
||||||
|
"label": "A frissítés nem sikerült",
|
||||||
|
"updating": false,
|
||||||
|
"error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"hold": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"duration_s": 361.9,
|
||||||
|
"final_phase": "failed",
|
||||||
|
"update_error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"hold_reason": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"state": "stopped"
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"harness_version": 1,
|
||||||
|
"app": "tandoor",
|
||||||
|
"venue": "guest 9202 demo-hp-scratch, controller 0.261.0",
|
||||||
|
"class": "db-postgres",
|
||||||
|
"from": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"verdict": "failed",
|
||||||
|
"seed_read_before": true,
|
||||||
|
"seed_read_after": false,
|
||||||
|
"healthy_after": false,
|
||||||
|
"migration_observed": null,
|
||||||
|
"abort": "not-attempted",
|
||||||
|
"abort_detail": null,
|
||||||
|
"duration_s": 361.9,
|
||||||
|
"measured_at": "2026-09-21T19:15:25.308811+00:00",
|
||||||
|
"evidence": "apps/tandoor/",
|
||||||
|
"notes": [
|
||||||
|
"the edge ended HELD or failed — this is a RESULT, not an error of the run"
|
||||||
|
],
|
||||||
|
"observables_after": {
|
||||||
|
"pinned_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"installed_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"catalog_images": {
|
||||||
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
|
},
|
||||||
|
"live_compose_image_lines": [
|
||||||
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
|
"image: postgres:16-alpine"
|
||||||
|
],
|
||||||
|
"docker_inspect": []
|
||||||
|
},
|
||||||
|
"final_phase": "failed",
|
||||||
|
"hold_reason": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
||||||
|
"update_error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza."
|
||||||
|
}
|
||||||
@@ -0,0 +1,509 @@
|
|||||||
|
tandoor-postgres |
|
||||||
|
tandoor-postgres | PostgreSQL Database directory appears to contain a database; Skipping initialization
|
||||||
|
tandoor-postgres |
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: starting PostgreSQL 16.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.859 CEST [1] LOG: listening on IPv6 address "::", port 5432
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.867 CEST [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.880 CEST [29] LOG: database system was shut down at 2026-09-22 10:53:09 CEST
|
||||||
|
tandoor-postgres | 2026-09-22 10:53:18.895 CEST [1] LOG: database system is ready to accept connections
|
||||||
|
tandoor | Deleting 'vue3/assets/pt_BR-tNFhL9ci.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.3796d8a521cf.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealTypeEditor-DAAKjxZB.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/sl-Nkic6vBb.c6ce1eb24108.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/nl-DIqabTrY.fcf6d7b2df13.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitEditor-54HrDOhT.9040eae92234.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FoodEditor-BR-tK8Pr.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/forwardRefs-DVyU53sF.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ca-C5QQCa9o.ff6e54a70768.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/KeywordsBar-BwJ0lEDV.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.c46924a2b9d5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-CKBxglwy.b98729efffd0.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/goto-DubWlX_o.0c25d7a8f5fa.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-CKBxglwy.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lv-BUrQRxBI.8efc7d113546.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.4d7347e87897.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Djsboh2v.92774fc66b84.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditor-DK6Qeffb.864b139cbb79.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelDeletePage-C4id8-tu.1ed7ee64e600.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/da-DHqdZ4yZ.197be8016aca.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ro-CG_JGo0i.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ExportDataSettings-BlFk8Tn-.6ccf02326ec4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.16f243b74d54.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeImportPage-DBKJ6DXr.a23aec8a9383.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.08d7c47f5d2b.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BY3ErEFj.457b3d77074e.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.b663eac25ee4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTimePicker-DNtQ2GaY.658bf461867a.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.d7c2e31a63b7.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.4ed293ceaca9.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.aa9eb5c590ab.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryLocationEditor-DIxi9S-h.5de878ee0a17.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/StartPage-0ugVot93.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-Brwft-8t.d570ceeec9ef.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.7c8b48842426.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccountSettings-BHfX12gt.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/lt-SI6E7sY1.2560d8a9d387.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/de-5mnKTxw2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-B1X0PDnA.068ca2b316db.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditor-DK6Qeffb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-CcFlDNPw.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.6b450d3cfcd0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.fe7085369993.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VStepper-lk6OG_fY.23af7e185e38.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.2642c051884b.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.e4b532c48301.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt-CXzOqbUC.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BooksPage-Dh8_wlv_.cb4aba43024a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelListPage-xoBv_A6i.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FdcSearchDialog-BvpKKey4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.7195d47ccd52.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/model_utils-a_hMB_Qu.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/useFileApi-BD_kCiAS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/he-DxNGVUQd.79ff03f4063a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/zh_Hant-CERwsE1Q.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchPage-BQ1P-4y8.ba1f4c8767b9.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryLocationEditor-DIxi9S-h.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fi-BLW_HATq.078772422941.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/nn-CkCilbi1.ccb3acb89917.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/useFileApi-BD_kCiAS.37a20e72aad4.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hu-DlZ4REsp.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt-CXzOqbUC.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTimePicker-BwPSjcxJ.a223b07c705e.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/pt_BR-tNFhL9ci.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CustomFilterEditor-Dc0piaF0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ko-ADlXHFgo.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDataTableServer-BYvhcs5d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-rFOjfrXe.df1b89399b11.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketCategoryEditor-rlIgT3uE.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.0308c579b183.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-CcFlDNPw.c63cac250b70.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-BJkOxCgW.8d4a4e6f7431.woff2'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-B5jLcokm.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-DYNiWd3v.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/brand_logo-DHt4CyHb.svg'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.3ba9fc624e34.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/OpenDataImportSettings-Ds1SQcSg.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertiesEditor-DCxEsAZO.16f243b74d54.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VFileUpload-ByFVW7Fp.931d5a48009e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DatabaseModelCol-rKX1F7Em.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.5e0dd3a66e81.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lt-SI6E7sY1.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/DatabasePage-CY4BXH8T.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-C0_akhap.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/HierarchyEditor-wADOsT_-.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-B1X0PDnA.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/it-DJ2I6vOs.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/bg-_Ardqm8i.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.4a7617f1519d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/logo_color-CXE3OqOR.svg.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/WelcomePage-zPtXSDjc.4dfacc5c8da0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitEditor-54HrDOhT.9040eae92234.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/hr-CMRkObu_.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-j0TpvUy_.42df5f015009.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/OpenDataImportSettings-Ds1SQcSg.f895a746d306.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.d617fa524f97.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-DYNiWd3v.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ApiSettings-CzWgpe8R.82be1325ed18.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.eot'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-DL25Fkt0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryEntryLogDialog-Dv6Omj68.d4f65e984493.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.4a7617f1519d.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.26d1fdd28765.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdEditor-D5JQGcsU.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-DzUjbg1Y.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BatchDeleteDialog-C9gKVWYX.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientEditorPage-DF3k1tNH.aa9eb5c590ab.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/nn-CkCilbi1.ccb3acb89917.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryEntryLogDialog-Dv6Omj68.d4f65e984493.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.727c640d6c8d.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ApiSettings-CzWgpe8R.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-BG9pNfzF.9465c6dc1d2f.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AiProviderEditor-C4TWtCwO.e6d60050b025.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.3796d8a521cf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-BeM1gRhl.727c640d6c8d.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.4ed293ceaca9.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelListPage-xoBv_A6i.4681a991ae27.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/uk-BClnjIfW.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.f2cae0d44a21.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.94016f72f4cb.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-Brwft-8t.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/de-5mnKTxw2.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VFileUpload-7CWUohzn.d182bb8e4f03.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.ffd6a13b9ab5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAvatar-_OUjgGcO.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-PPD1ymuo.7195d47ccd52.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/brand_logo-DHt4CyHb.fa64319ab35b.svg.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ConnectorConfigEditor-D06JOZDX.5e0dd3a66e81.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fileFilter-JaX38xV6.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealTypeEditor-DAAKjxZB.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/pl-B7dc5eNY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-BnHJd-1b.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/framework-CKkm3ZT1.0da2482ae88a.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-Bc1o5piM.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.7d9049ae96b5.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CookLogEditor-wf-1cNFJ.ef3a04991a05.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingSettings-DBfLsRlj.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AddToShoppingDialog-CS_S-d2g.eb5504799c65.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-CTAAxXor.4a6591ab5460.woff2'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.2f9dbd605868.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AiProviderEditor-BYnKvCw_.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/uk-BClnjIfW.b429b8ed5096.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/BookViewPage-CHarlNiQ.bdf998b08053.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdPage-BsKZpym2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fi-BLW_HATq.078772422941.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.e73a0647198c.eot.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/InviteLinkEditor-BZ7NMcrL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.4de7c0a8c2e3.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VRating-BAibLkoF.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-WpOvMnND.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.08d7c47f5d2b.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/AutomationEditor-C6fYAtLL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-CnWxryRb.e73a0647198c.eot'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.085aaed48fa0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-Dgh1luaN.73de85b4e4df.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-CFEp5VcY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-BG9pNfzF.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/integration_utils-D8RSOVmp.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/nb_NO-CdS1Hktt.294979d98dcb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.8dc9d3e18964.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-BnHJd-1b.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ja-Cqm3qbrP.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-DL25Fkt0.5373fcf8fbc3.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchPage-BQ1P-4y8.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/StartPage-0ugVot93.1c72303e8853.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fdc-Byjxh21q.6a8962cb2f19.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.7d9049ae96b5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PropertyEditorPage-Ti9vpeer.e4b532c48301.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceEditor-CIrx7Wew.44bd56e30e62.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.0916b5adcb73.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B_U4Berv.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.5c0bb4b51390.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AccessTokenEditor-BqYrLuQE.4d7347e87897.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VColorPicker-DoVATq5z.26d1fdd28765.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/AddToShoppingDialog-BXt5jKLm.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ru-BXmxlY4u.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hu-DlZ4REsp.c1bc941c31dc.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VList-edQgt9_l.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/UnitConversionEditor-BUHvM5Eh.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextarea-zkkSnzux.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B_U4Berv.7dc258e43ccf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.6b450d3cfcd0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanEditor-DqGGZRzo.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Cs5DQi32.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.0b75aa57bbeb.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/dimensions-B5x3TxJs.5c0bb4b51390.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/main-nTFEtOSD.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserFileEditor-DKOcBuK-.cc1baa1c02f3.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/StorageEditor-Up4uWQb6.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-DTdW4rEh.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/he-DxNGVUQd.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.8dc9d3e18964.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextarea-dHE66AZf.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/intersect-siLrmRQw.cc9e340f1351.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/framework-CKkm3ZT1.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ca-C5QQCa9o.ff6e54a70768.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-D0aA9rwL.ttf'
|
||||||
|
tandoor | Deleting 'vue3/assets/VListItemAction-CXKY8J-P.ffd6a13b9ab5.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/main-nTFEtOSD.4273b900f1bf.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListEditor-vKmfFTZN.4f5dd4c981a5.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-CeGB3d9x.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ClosableHelpAlert-BoN8dDrm.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/position-D7bmUCsu.f212789ebec5.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListView-C0_akhap.1b6d4259ca8e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/hy-HqufUZnw.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/InventoryBookingPage-orELmDxm.45c2c2f7531a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-DzUjbg1Y.fa06924ae72f.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/form-CDdumt48.5fcbf914ae94.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdPage-BsKZpym2.a5566a4564d6.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/forwardRefs-DVyU53sF.64171d66d1df.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/integration_utils-D8RSOVmp.8006123d3084.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceSettings-BPOt7vl3.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditorBase-CZWlxxIQ.cf852babb62d.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelEditPage-B5oBrkJw.0c31f8b7052c.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VAutocomplete-CFEp5VcY.2a4e88a23ede.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FdcSearchDialog-BvpKKey4.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/transitions-BVkpOt9D.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ro-CG_JGo0i.c856bd470eef.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/IngredientsTable-DZblS1P-.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeCard-C2Hjv7vL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-i2TDHCpS.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VBtn-rFOjfrXe.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/FoodEditor-BR-tK8Pr.24df4c5c0e7e.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/cs-DUZpBKTY.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.0b75aa57bbeb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fdc-Byjxh21q.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/CookLogEditor-wf-1cNFJ.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HouseholdEditor-D5JQGcsU.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDivider-rMXvH15P.085aaed48fa0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-Byn3Fc0w.3ad96cecfca7.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.a85f6556b6a2.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fr-D1J9AIHe.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VStepper-lk6OG_fY.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ko-ADlXHFgo.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/WelcomePage-zPtXSDjc.4dfacc5c8da0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-D7GkfSeA.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/SpaceSetupPage-BSv2ZmPb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/zh_Hant-CERwsE1Q.8534ecee0fb0.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ShoppingListPage-Cg_SrILL.f2cae0d44a21.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/UserSpaceEditor-BiMFbwI_.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VOverlay-BSdT-t2A.1f4f586d7141.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeImportPage-DBKJ6DXr.a23aec8a9383.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VDataTableServer-BYvhcs5d.d5a7cfdcf126.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/ar-Ct4DpnJT.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VRating-Qn4Hz2ci.119bbc89c24a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/number_utils-DFmVVcK0.cfc3e206a4c1.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HelpPage-C-xlKPtR.fa54da2fd1cf.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/HierarchyEditor-wADOsT_-.885aa06e77cd.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ripple-Byn3Fc0w.3ad96cecfca7.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VChip-Hpg9IuyM.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BZECYYUo.94016f72f4cb.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/PrivateRecipeBadge-BVOXRXwb.dcd01dd00de0.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/SearchSettings-CBkFhMns.b9bc4a1f032c.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fontello-BEgLts9b.a782baa8633b.woff'
|
||||||
|
tandoor | Deleting 'vue3/assets/nl-DIqabTrY.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/et-zY9CrDMt.1761c6eb5f48.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.b663eac25ee4.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeEditor-Cu9LLPvL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeBookEditor-Bha-wuB-.e3586751a38a.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/goto-DubWlX_o.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ModelMergeDialog-BCXJZjTO.4753553f721f.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/AutomationEditor-C6fYAtLL.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTextField-j0TpvUy_.42df5f015009.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/SupermarketEditor-L_B5nyx2.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/el-DNs6HoDL.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/lv-BUrQRxBI.8efc7d113546.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/MealPlanSettings-BU5yRyFO.2f9dbd605868.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/NumberScalerDialog-DoOvxgjM.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-solid-900-D0aA9rwL.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/intersect-siLrmRQw.cc9e340f1351.js'
|
||||||
|
tandoor | Deleting 'vue3/assets/VTabs-Bz9gKX-q.27a6a10279b7.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-regular-400-DZaxPHgR.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/fa-v4compatibility-CCth-dXg.ttf.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/tr-OeJMQhAK.2c406e95c585.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/CosmeticSettings-DTudQs61.css'
|
||||||
|
tandoor | Deleting 'vue3/assets/RecipeViewPage-BY3ErEFj.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/VSwitch-Djsboh2v.css.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/TestPage-CPX2qaEd.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/model_utils-a_hMB_Qu.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/ar-Ct4DpnJT.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/DeleteConfirmDialog-C1xQIJsS.js.gz'
|
||||||
|
tandoor | Deleting 'vue3/assets/BooksPage-Dh8_wlv_.js.gz'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.c659e2604ad6.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_black.dc487b18028c.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.ad2e3aa263da.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_192.c9b9177ff941.png'
|
||||||
|
tandoor | Deleting 'assets/logo_black.svg'
|
||||||
|
tandoor | Deleting 'assets/header.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_144.f09537dbf142.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_128.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.ad2e3aa263da.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.4ccbb336af9d.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/spinner.168a09fd2600.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_144.22c6c7678fdb.png'
|
||||||
|
tandoor | Deleting 'assets/spinner.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_512.png'
|
||||||
|
tandoor | Deleting 'assets/logo_black.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.d7c2e31a63b7.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.c659e2604ad6.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_32.b7d9707eac91.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_512.0a28df8511e3.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_black.dc487b18028c.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.fd1e81a4dcab.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/header.48e8ad9e7540.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_512.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_512.6b2e69402327.png'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_128.a90db52449d9.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_512.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_32.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.fd1e81a4dcab.svg'
|
||||||
|
tandoor | Deleting 'assets/header.48e8ad9e7540.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.d43daa47dca3.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/logo_color_180.0fcae5e85a72.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_180.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_144.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.svg'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.d43daa47dca3.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan.4ccbb336af9d.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_plan_512.028b9bcca1eb.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping.svg'
|
||||||
|
tandoor | Deleting 'assets/recipe_no_image.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/header.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.svg.gz'
|
||||||
|
tandoor | Deleting 'assets/spinner.168a09fd2600.svg'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.6ebe02bf6707.png'
|
||||||
|
tandoor | Deleting 'assets/spinner.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_svg.d7c2e31a63b7.svg'
|
||||||
|
tandoor | Deleting 'assets/logo_color_shopping_144.6c05e01d07b2.png'
|
||||||
|
tandoor | Deleting 'assets/logo_color_192.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo.png'
|
||||||
|
tandoor | Deleting 'assets/brand_logo_white.svg'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.6a3183313556.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.6a3183313556.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.88878ff60271.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.88878ff60271.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.js.gz'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn-json.js'
|
||||||
|
tandoor | Deleting 'mfa/js/webauthn.js'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.e62f1984b5e4.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor.min.e62f1984b5e4.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.3bdb00cbb58c.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.css'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.css.gz'
|
||||||
|
tandoor | Deleting 'themes/tandoor_dark.min.3bdb00cbb58c.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.22de6a06ad0b.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.css'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.css.gz'
|
||||||
|
tandoor | Deleting 'custom/css/markdown_blockquote.22de6a06ad0b.css.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.8e4a6dcc692b.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.c2801fb415f0.svg'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.c5e0f14f88a8.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c4f508e7c4f0.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_500.d214b888d895.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_500.fd9b8290076b.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.a9c4bb7348f4.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_400.9ed361bba848.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.8e4a6dcc692b.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.cccc9d29470e.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.0bff33a5fd7e.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.f5f2566b93e8.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c1a866ec0e04.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_700.b9f2c13fc361.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.06147b6cd88c.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.svg'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.eot'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_400.d5e78c53cb07.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.c2801fb415f0.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_400.4d1490f32451.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_700.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.7b9568e6389b.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.c1a866ec0e04.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.a9c4bb7348f4.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.5063b105c764.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.7b9568e6389b.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.woff'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.44d537ab79f9.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.svg.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.svg'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_500.84780596e268.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.06147b6cd88c.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.333bae208dc3.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_400.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.65b286af947c.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-brands-400.5063b105c764.eot'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_ext_700.62d7a4c78fc2.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.woff'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_devanagari_500.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.0bff33a5fd7e.ttf.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.eot.gz'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/fa-regular-400.65b286af947c.ttf'
|
||||||
|
tandoor | Deleting 'webfonts/poppins_latin_700.f4f17fd53c7d.woff2'
|
||||||
|
tandoor | Deleting 'webfonts/fa-solid-900.ttf'
|
||||||
|
tandoor | 2026/09/22 10:54:37 [crit] 16#16: *9 connect() to unix:/tmp/tandoor.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /accounts/login/ HTTP/1.1", upstream: "http://unix:/tmp/tandoor.sock:/accounts/login/", host: "127.0.0.1:80"
|
||||||
|
tandoor | 127.0.0.1 - - [22/Sep/2026:10:54:37 +0200] "GET /accounts/login/ HTTP/1.1" 502 150 "-" "Wget" "-"
|
||||||
|
tandoor |
|
||||||
|
tandoor | 894 static files copied to '/opt/recipes/staticfiles', 2464 post-processed.
|
||||||
|
tandoor | Done
|
||||||
|
tandoor | Starting gunicorn
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Starting gunicorn 26.2.0
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Listening at: unix:/tmp/tandoor.sock (7)
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [7] [INFO] Using worker: gthread
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [66] [INFO] Booting worker with pid: 66
|
||||||
|
tandoor | [2026-09-22 10:54:37 +0200] [67] [INFO] Booting worker with pid: 67
|
||||||
|
tandoor | [2026-09-22 10:54:38 +0200] [68] [INFO] Booting worker with pid: 68
|
||||||
|
tandoor | [2026-09-22 10:54:38 +0200] [7] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | Running django-vite in production mode (no HMR)
|
||||||
|
tandoor | 127.0.0.1 - - [22/Sep/2026:10:54:45 +0200] "GET /accounts/login/ HTTP/1.1" 200 4981 "-" "Wget" "-"
|
||||||
|
tandoor | - - [22/Sep/2026:10:54:45 +0200] "GET /accounts/login/ HTTP/1.0" 200 4981 "-" "Wget"
|
||||||
|
tandoor | ThreadPoolExecutor-0_0 ERROR 2026-09-22 10:54:47,243 django.security.DisallowedHost Invalid HTTP_HOST header: 'tandoor:80'. You may need to add 'tandoor' to ALLOWED_HOSTS.
|
||||||
|
tandoor | Traceback (most recent call last):
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||||||
|
tandoor | response = get_response(request)
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 119, in __call__
|
||||||
|
tandoor | response = self.process_request(request)
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/middleware/common.py", line 48, in process_request
|
||||||
|
tandoor | host = request.get_host()
|
||||||
|
tandoor | File "/opt/recipes/venv/lib/python3.13/site-packages/django/http/request.py", line 203, in get_host
|
||||||
|
tandoor | raise DisallowedHost(msg)
|
||||||
|
tandoor | django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'tandoor:80'. You may need to add 'tandoor' to ALLOWED_HOSTS.
|
||||||
|
tandoor | - - [22/Sep/2026:10:54:47 +0200] "GET /accounts/login/ HTTP/1.0" 400 143 "-" "Go-http-client/1.1"
|
||||||
|
tandoor | 172.18.0.2 - - [22/Sep/2026:10:54:47 +0200] "GET /accounts/login/ HTTP/1.1" 400 154 "-" "Go-http-client/1.1" "-"
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
{
|
{
|
||||||
"before": {
|
"before": {
|
||||||
"hu": [
|
"hu": [],
|
||||||
{
|
"en": []
|
||||||
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
|
|
||||||
"text": "Naprakész"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"en": [
|
|
||||||
{
|
|
||||||
"title": "This app is running the newest version available.",
|
|
||||||
"text": "Up to date"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"after": {
|
"after": {
|
||||||
"hu": [
|
"hu": [
|
||||||
@@ -27,5 +17,5 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"drill_commit": "c7477d1fb921"
|
"drill_commit": "654a28192b38"
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
21:15:25 ==== tandoor: ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (sub=recipes, class=db-postgres)
|
10:52:42 ==== tandoor: ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (sub=recipes, class=db)
|
||||||
21:15:25 [1] tandoor already deployed — reusing
|
10:52:42 [1] tandoor already deployed — reusing
|
||||||
21:15:27 [2] seeding through the app's own front door
|
10:52:45 [2] seeding through the app's own front door
|
||||||
21:15:37 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
10:52:55 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||||
21:15:40 tandoor: seeded superuser drill316903
|
10:52:59 tandoor: seeded superuser drill1d392f
|
||||||
21:15:40 [3] control C1 — reading the seed back BEFORE the update
|
10:52:59 [3] control C1 — reading the seed back BEFORE the update
|
||||||
21:15:46 tandoor: readback of the seeded account found=True
|
10:53:05 tandoor: readback of the seeded account found=True
|
||||||
21:15:46 [4] „Mentés most" -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
10:53:05 [4] „Mentés most" -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||||
21:16:42 [4] backup idle; last=None
|
10:54:00 [4] backup idle; last=None
|
||||||
21:16:43 [5] drill commit c7477d1fb921: tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (push rc=0)
|
10:54:01 [5] drill commit 654a28192b38: tandoor ghcr.io/tandoorrecipes/recipes:2.6.13 -> ghcr.io/tandoorrecipes/recipes:2.6.15 (push rc=0)
|
||||||
21:16:47 [5] badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
10:54:06 [5] badge HU: [{'title': 'Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.', 'text': 'Frissítés elérhető — ma'}]
|
||||||
21:16:47 [5] badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
10:54:06 [5] badge EN: [{'title': 'A newer version of this app is available. Select the Update button to start it.', 'text': 'Update available — today'}]
|
||||||
21:16:47 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
10:54:06 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||||
21:16:47 + 0.0s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
10:54:06 + 0.0s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||||
21:16:48 + 1.0s phase=pulling label=Új verzió letöltése… err=None hold=None
|
10:54:07 + 1.0s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||||
21:17:42 + 54.3s phase=starting label=Indítás az új verzióval… err=None hold=None
|
10:54:08 + 2.1s phase=starting label=Indítás az új verzióval… err=None hold=None
|
||||||
21:17:46 + 58.4s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
10:54:11 + 5.2s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||||
21:22:49 + 361.9s phase=failed label=A frissítés nem sikerült err=A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza. hold=A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.
|
10:54:47 + 41.1s phase=done label=Frissítve err=None hold=None
|
||||||
21:22:49 [7] reading the seed back AFTER the update
|
10:54:47 [7] reading the seed back AFTER the update
|
||||||
21:22:52 tandoor: READBACK UNUSABLE — a username that cannot exist did not read as absent (None) :: Error response from daemon: No such container: tandoor
|
10:54:54 tandoor: readback of the seeded account found=True
|
||||||
21:22:54 [8] pinned = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
10:54:56 [8] pinned = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
21:22:54 [8] installed = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.13', 'tandoor-postgres': 'postgres:16-alpine'}
|
10:54:56 [8] installed = {'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:16-alpine'}
|
||||||
21:22:54 [8] compose = ['image: ghcr.io/tandoorrecipes/recipes:2.6.15', 'image: postgres:16-alpine']
|
10:54:56 [8] compose = ['image: ghcr.io/tandoorrecipes/recipes:2.6.15', 'image: postgres:16-alpine']
|
||||||
21:22:54 [8] inspect = []
|
10:54:56 [8] inspect = ['tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0', 'tandoor-postgres postgres:16-alpine running=true restarts=0']
|
||||||
21:22:54 [9] verdict failed -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/update-night-2026-09-21/apps/tandoor/verdict.json
|
10:54:56 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/update-night-2026-09-21/apps/tandoor/verdict.json
|
||||||
|
|||||||
@@ -7,10 +7,7 @@
|
|||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"catalog_images": {
|
"catalog_images": null,
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
|
||||||
},
|
|
||||||
"live_compose_image_lines": [
|
"live_compose_image_lines": [
|
||||||
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
"image: postgres:16-alpine"
|
"image: postgres:16-alpine"
|
||||||
|
|||||||
@@ -8,10 +8,7 @@
|
|||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"catalog_images": {
|
"catalog_images": null,
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
|
||||||
},
|
|
||||||
"live_compose_image_lines": [
|
"live_compose_image_lines": [
|
||||||
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
"image: postgres:16-alpine"
|
"image: postgres:16-alpine"
|
||||||
@@ -27,7 +24,7 @@
|
|||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"installed_images": {
|
"installed_images": {
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"catalog_images": {
|
"catalog_images": {
|
||||||
@@ -38,6 +35,9 @@
|
|||||||
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"image: postgres:16-alpine"
|
"image: postgres:16-alpine"
|
||||||
],
|
],
|
||||||
"docker_inspect": []
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"hold": null
|
"hold": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"t": 54.3,
|
"t": 2.1,
|
||||||
"phase": "starting",
|
"phase": "starting",
|
||||||
"label": "Indítás az új verzióval…",
|
"label": "Indítás az új verzióval…",
|
||||||
"updating": true,
|
"updating": true,
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"hold": null
|
"hold": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"t": 58.4,
|
"t": 5.2,
|
||||||
"phase": "verifying",
|
"phase": "verifying",
|
||||||
"label": "Működés ellenőrzése…",
|
"label": "Működés ellenőrzése…",
|
||||||
"updating": true,
|
"updating": true,
|
||||||
@@ -35,17 +35,17 @@
|
|||||||
"hold": null
|
"hold": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"t": 361.9,
|
"t": 41.1,
|
||||||
"phase": "failed",
|
"phase": "done",
|
||||||
"label": "A frissítés nem sikerült",
|
"label": "Frissítve",
|
||||||
"updating": false,
|
"updating": false,
|
||||||
"error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
"error": null,
|
||||||
"hold": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza."
|
"hold": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"duration_s": 361.9,
|
"duration_s": 41.1,
|
||||||
"final_phase": "failed",
|
"final_phase": "done",
|
||||||
"update_error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
"update_error": null,
|
||||||
"hold_reason": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
"hold_reason": null,
|
||||||
"state": "stopped"
|
"state": "running"
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"harness_version": 1,
|
"harness_version": 1,
|
||||||
"app": "tandoor",
|
"app": "tandoor",
|
||||||
"venue": "guest 9202 demo-hp-scratch, controller 0.261.0",
|
"venue": "guest 9202 demo-hp-scratch, controller 0.261.0",
|
||||||
"class": "db-postgres",
|
"class": "db",
|
||||||
"from": {
|
"from": {
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
@@ -11,26 +11,25 @@
|
|||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"verdict": "failed",
|
"verdict": "proven",
|
||||||
"seed_read_before": true,
|
"seed_read_before": true,
|
||||||
"seed_read_after": false,
|
"seed_read_after": true,
|
||||||
"healthy_after": false,
|
"healthy_after": true,
|
||||||
"migration_observed": null,
|
"migration_observed": null,
|
||||||
"abort": "not-attempted",
|
"abort": "not-attempted",
|
||||||
"abort_detail": null,
|
"abort_detail": null,
|
||||||
"duration_s": 361.9,
|
"duration_s": 41.1,
|
||||||
"measured_at": "2026-09-21T19:15:25.308811+00:00",
|
"measured_at": "2026-09-22T08:52:42.724401+00:00",
|
||||||
"evidence": "apps/tandoor/",
|
"evidence": "apps/tandoor/",
|
||||||
"notes": [
|
"notes": [],
|
||||||
"the edge ended HELD or failed — this is a RESULT, not an error of the run"
|
"badge_catchup_seconds": 4.5,
|
||||||
],
|
|
||||||
"observables_after": {
|
"observables_after": {
|
||||||
"pinned_images": {
|
"pinned_images": {
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"installed_images": {
|
"installed_images": {
|
||||||
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.13",
|
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"tandoor-postgres": "postgres:16-alpine"
|
"tandoor-postgres": "postgres:16-alpine"
|
||||||
},
|
},
|
||||||
"catalog_images": {
|
"catalog_images": {
|
||||||
@@ -41,9 +40,12 @@
|
|||||||
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
"image: ghcr.io/tandoorrecipes/recipes:2.6.15",
|
||||||
"image: postgres:16-alpine"
|
"image: postgres:16-alpine"
|
||||||
],
|
],
|
||||||
"docker_inspect": []
|
"docker_inspect": [
|
||||||
|
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 running=true restarts=0",
|
||||||
|
"tandoor-postgres postgres:16-alpine running=true restarts=0"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"final_phase": "failed",
|
"final_phase": "done",
|
||||||
"hold_reason": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza.",
|
"hold_reason": null,
|
||||||
"update_error": "A(z) tandoor frissítése 2026-09-21 21:22-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a Mentések oldalon ebből a biztonsági mentésből: saját meghajtó, 2026-09-21 21:15 — ez a másolat a beállításokat, az adatbázist és az adatköteteket tartalmazza."
|
"update_error": null
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Red-proof for R-618, live on 9202 through the product.
|
||||||
|
|
||||||
|
The claim: three templates name a health probe the app does not answer. The proof must show BOTH
|
||||||
|
halves at the same moment, or it shows nothing:
|
||||||
|
(a) the PRODUCT says the app is unhealthy — the controller's state, and the app page's badge;
|
||||||
|
(b) the APP is fine — its own front door answers 200, and docker's healthcheck reads healthy.
|
||||||
|
A reading of (a) alone is equally consistent with "the app really is broken", which is exactly the
|
||||||
|
mistake this whole exercise exists to stop making.
|
||||||
|
"""
|
||||||
|
import json, re, sys, time
|
||||||
|
sys.path.insert(0, '.')
|
||||||
|
import walk as w
|
||||||
|
|
||||||
|
OUT = "../probe-fix-2026-09-22"
|
||||||
|
APPS = [("tandoor", "tandoor", "/accounts/login/"),
|
||||||
|
("zipline", "zipline", "/"),
|
||||||
|
("wger", "wger", "/")]
|
||||||
|
|
||||||
|
|
||||||
|
def observe(name, sub, path, tag):
|
||||||
|
st = w.stack(name)
|
||||||
|
ac = st.get("app_config") or {}
|
||||||
|
rc, code, body = w.app_curl(sub, path)
|
||||||
|
dk = w.guest(f"docker inspect --format '{{{{.State.Health.Status}}}}' "
|
||||||
|
f"$(docker ps -q --filter name={name}) 2>&1 | head -3").strip()
|
||||||
|
bg = w.badges(name)
|
||||||
|
# The health word the HOUSEHOLD reads, in both languages — the version badge is a different
|
||||||
|
# element and quoting it instead would prove nothing about health (it says "Naprakesz" either
|
||||||
|
# way). Taken from the rendered page, scripts and styles stripped first: a `<script>` block on
|
||||||
|
# this page contains the same words and an unstripped scan picks them up (measured 2026-09-21).
|
||||||
|
health = {}
|
||||||
|
for lang, suffix in (("hu", ""), ("en", "?lang=en")):
|
||||||
|
h = w.page(f"/apps/{name}{suffix}")
|
||||||
|
h = re.sub(r"<script.*?</script>|<style.*?</style>", "", h, flags=re.S)
|
||||||
|
txt = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", h))
|
||||||
|
m = re.search(r"\u2190 Alkalmaz\u00e1sok .{0,80}?\s(Nem eg\u00e9szs\u00e9ges|Eg\u00e9szs\u00e9ges|Fut|Le\u00e1ll\u00edtva|Indul|Hib\u00e1s)\s", txt) or \
|
||||||
|
re.search(r"\u2190 (?:Apps|Alkalmaz\u00e1sok) .{0,80}?\s(Not healthy|Healthy|Running|Stopped|Starting|Failed)\s", txt)
|
||||||
|
health[lang] = m.group(1) if m else None
|
||||||
|
health[lang + "_context"] = txt[txt.find("\u2190"):txt.find("\u2190") + 220] if "\u2190" in txt else None
|
||||||
|
rec = {"when": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tag": tag, "app": name,
|
||||||
|
"controller_state": st.get("state"), "deployed": st.get("deployed"),
|
||||||
|
"pinned_images": ac.get("pinned_images"), "installed_images": ac.get("installed_images"),
|
||||||
|
"front_door_rc": rc, "front_door_code": code, "front_door_bytes": len(body),
|
||||||
|
"docker_health": dk, "version_badge": bg, "health_word": health}
|
||||||
|
print(json.dumps(rec, ensure_ascii=False, indent=2))
|
||||||
|
return rec
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
w.login()
|
||||||
|
tag = sys.argv[1] if len(sys.argv) > 1 else "before"
|
||||||
|
only = sys.argv[2:] or [a[0] for a in APPS]
|
||||||
|
recs = []
|
||||||
|
for name, sub, path in APPS:
|
||||||
|
if name not in only:
|
||||||
|
continue
|
||||||
|
print(f"\n=== {name} ({tag})")
|
||||||
|
if tag == "before":
|
||||||
|
ok = w.deploy(name, sub)
|
||||||
|
print(f" deploy ok={ok}")
|
||||||
|
w.wait_app(sub, path)
|
||||||
|
recs.append(observe(name, sub, path, tag))
|
||||||
|
open(f"{OUT}/probe-{tag}.json", "w").write(json.dumps(recs, ensure_ascii=False, indent=2))
|
||||||
|
print(f"\nwritten {OUT}/probe-{tag}.json")
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Point guest 9202 at the drill catalog, or back at the live one (09 §6.5, R-615).
|
||||||
|
|
||||||
|
`git.repo_url` alone is INERT: `Syncer.gitCloneOrPull` clones only when the cache has no `.git`,
|
||||||
|
otherwise it fetches from the remote the existing clone stores. The cache directory must be removed
|
||||||
|
too, or the box goes on following the live catalog AND REPORTS SUCCESS. That is R-615, and it is why
|
||||||
|
step 3 exists.
|
||||||
|
"""
|
||||||
|
import re, sys, io
|
||||||
|
sys.path.insert(0, '.')
|
||||||
|
import walk as w
|
||||||
|
|
||||||
|
VOL = "/var/lib/docker/volumes/felhom-controller-data/_data"
|
||||||
|
LIVE = "https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git"
|
||||||
|
DRILL_REPO = "https://gitea.dooplex.hu/admin/app-catalog-drill.git"
|
||||||
|
|
||||||
|
|
||||||
|
def creds():
|
||||||
|
for l in io.open("/home/kisfenyo/.git-credentials").read().strip().split("\n"):
|
||||||
|
m = re.match(r'https://(admin):([^@]+)@gitea\.dooplex\.hu', l)
|
||||||
|
if m:
|
||||||
|
return m.group(1), m.group(2)
|
||||||
|
raise SystemExit("no admin credential for gitea.dooplex.hu")
|
||||||
|
|
||||||
|
|
||||||
|
def repoint(to_drill):
|
||||||
|
u, t = creds() if to_drill else ("", "")
|
||||||
|
url = DRILL_REPO if to_drill else LIVE
|
||||||
|
script = f"""
|
||||||
|
set -e
|
||||||
|
test -f {VOL}/controller.yaml.pre-update-night || cp {VOL}/controller.yaml {VOL}/controller.yaml.pre-update-night
|
||||||
|
python3 - <<'EOF'
|
||||||
|
import re
|
||||||
|
p = "{VOL}/controller.yaml"
|
||||||
|
s = open(p).read()
|
||||||
|
s = re.sub(r'(^\\s+repo_url: ).*$', r'\\g<1>{url}', s, count=1, flags=re.M)
|
||||||
|
s = re.sub(r'(^\\s+token: ).*$', r'\\g<1>"{t}"', s, count=1, flags=re.M)
|
||||||
|
s = re.sub(r'(^\\s+username: ).*$', r'\\g<1>"{u}"', s, count=1, flags=re.M)
|
||||||
|
open(p, "w").write(s)
|
||||||
|
EOF
|
||||||
|
# R-615: the cache is the thing that actually decides which remote is fetched.
|
||||||
|
rm -rf {VOL}/catalog-cache {VOL}/data/catalog-cache
|
||||||
|
docker restart felhom-controller >/dev/null
|
||||||
|
sleep 12
|
||||||
|
grep -A6 '^git:' {VOL}/controller.yaml | sed 's/token:.*/token: <redacted>/'
|
||||||
|
"""
|
||||||
|
print(w.guest(script))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
repoint(sys.argv[1] == "drill")
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user