diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a74e6..a00d703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## calibre-web: the admin login name is generated at install (2026-10-01, late afternoon) + +- **`09` §3 decision 61** (operator ruling, R-752 option A): a new deploy field `ADMIN_USER` (`type: secret`, + `generate: "hex:5"` — ten lowercase letters/digits, shown on the app page behind „Megjelenítés", `locked_after_deploy`). + `after_install` (as `abc`) renames `admin` in `app.db` to it (Calibre-Web has no rename command — `cps/cli.py` offers + only `-s user:password`; its admin page renames by setting `user.name`, `admin.py:2789`, `ub.py:264`), sets the password + with Calibre-Web's own `cps.py -s`, and PROVES it (the new name's hash takes the password, no `admin` left) before the + success line. Both values are their own arguments. Copy (hu + en) updated; the Hungarian freeze re-captured for these + five strings only. Proven on 9202: name + password sign in (form and OPDS), `admin` refused, 40 wrong tries on `admin` + and the household still in at once; the install hold covered the window (0 of 31 stranger tries). The lock itself stays. + An installed calibre-web is NOT renamed by this (its template is frozen until an Update, and `after_install` runs only + after a fresh install): demo-hp's was renamed by hand. + ## Strangers cannot lock a whole household out of wger; three other apps measured (2026-10-01, afternoon) - **wger** `82fff32` (R-752; `09` §3 decision 58, decided by CC unattended — operator may reverse): diff --git a/FIRST-ADMIN.md b/FIRST-ADMIN.md index df80bb3..848bd69 100644 --- a/FIRST-ADMIN.md +++ b/FIRST-ADMIN.md @@ -38,7 +38,7 @@ asks the probe first where there is one. Open sign-up is closed by the box after | bentopdf | 5 | browser-only PDF tool, no accounts | – | fine | R | | **bookstack** | 3 | `admin@admin.com / password` | (b) `artisan bookstack:create-admin --initial` | **FIXED** — catalog, decision 45 | **M 9202**: default fails, generated works; **M demo-hp**: default still works on the installed app (unchanged, page warns) | | **calcom** | 4 | first visitor becomes admin (`/api/auth/setup`) | **setup gate**, opened by the household's press („Kész, beállítottam", confirm first); sign-up closed by the box after the setup: `/signup`, `/auth/signup`, `/api/auth/signup` | **GATED** — catalog, 2026-09-29 (decisions 46–47) | **M 9202**: stranger → gate page / 401; household reached the first-setup screen; gate opened after the setup; the app answered after (`felhom.eu/documentation/audits/gate-rollout-2026-09-29/`) | -| **calibre-web** | 3 | `admin / admin123` | (b) `cps.py -p /config/app.db -s admin:` as `abc`; `generate: password:24:special` (controller ≥ 0.280.0) | **FIXED** — catalog, 2026-09-29 | **M 9202**: fresh install — default refused, generated signs in (302), wrong refused; **M demo-hp**: the installed app's password changed by the operator's ruling (Part A) | +| **calibre-web** | 3 | `admin / admin123` | (b) as `abc`: rename `admin` in `app.db` to the generated `ADMIN_USER` (`secret`, `hex:5`), then `cps.py -p /config/app.db -s :`, then prove the hash and that no `admin` is left; `generate: password:24:special` (controller ≥ 0.280.0) | **FIXED** — catalog, 2026-09-29; **the name generated too** 2026-10-01 (`09` §3 decision 61, R-752: Calibre-Web locks a NAME for a day after 40 wrong tries) | **M 9202** (2026-10-01): fresh install — the generated name + password sign in (form and OPDS), `admin` refused, 40 wrong tries on `admin` and the household still in at once; **M demo-hp**: the installed app renamed by hand the same way, the name in the operator's credentials file | | **claper** | 3 (+ open sign-up) | seeds `admin@claper.co / claper` | (b) `bin/claper rpc … update_user_password` | **FIXED** — catalog, decision 45 | **M 9202**: default fails, generated works, a restore keeps it | | code-server | 1 | `PASSWORD` generated, applied every start | – | fine | R | | crafty-controller | 1 | `CRAFTY_PASSWORD` → default.json | – | fine | R | diff --git a/scripts/copy_freeze/hu.json b/scripts/copy_freeze/hu.json index 1bd0156..a1d9188 100644 --- a/scripts/copy_freeze/hu.json +++ b/scripts/copy_freeze/hu.json @@ -128,7 +128,7 @@ "calibre-web": { "app_info.default_creds": "admin / admin123", "app_info.first_steps[0]": "Nyisd meg a books.DOMAIN címet a böngészőben", - "app_info.first_steps[1]": "Jelentkezz be: admin és a Beállítások oldalon látható első jelszó", + "app_info.first_steps[1]": "Jelentkezz be a Beállítások oldalon látható felhasználónévvel és első jelszóval", "app_info.first_steps[2]": "Dobj egy könyvet a Fájlkezelőben (FileBrowser) az import/calibre mappába — automatikusan feldolgozza és a media/books könyvtárba helyezi", "app_info.prerequisites[0]": "Külső HDD szükséges az e-könyvek tárolásához", "app_info.prerequisites[1]": "x86 processzor szükséges (a CWA tartalmazza a Calibre binárist)", @@ -141,8 +141,10 @@ "app_info.use_cases[4]": "KOReader szinkronizáció (olvasási pozíció, könyvjelzők)", "data_paths[calibre].label": "Beolvasandó e-könyvek", "data_paths[media/books].label": "E-könyvtár", - "deploy_fields[ADMIN_PASSWORD].description": "Az első bejelentkezéshez: admin és ez a jelszó. Kell benne kis- és nagybetű, szám és egy különleges karakter.", - "deploy_fields[ADMIN_PASSWORD].label": "Admin jelszó (admin)", + "deploy_fields[ADMIN_PASSWORD].description": "Az első bejelentkezéshez: a fenti felhasználónév és ez a jelszó. Kell benne kis- és nagybetű, szám és egy különleges karakter.", + "deploy_fields[ADMIN_PASSWORD].label": "Admin jelszó", + "deploy_fields[ADMIN_USER].description": "Az első bejelentkezéshez ez a felhasználónév kell (nem az admin). A telepítéskor készül, csak te látod.", + "deploy_fields[ADMIN_USER].label": "Admin felhasználónév", "deploy_fields[DOMAIN].description": "A szerver domain neve", "deploy_fields[DOMAIN].label": "Domain", "deploy_fields[HDD_PATH].description": "A külső merevlemez elérési útja, ahol a Calibre könyvtár található", diff --git a/templates/calibre-web/.felhom.yml b/templates/calibre-web/.felhom.yml index e4a5e7d..94a6751 100644 --- a/templates/calibre-web/.felhom.yml +++ b/templates/calibre-web/.felhom.yml @@ -63,14 +63,24 @@ deploy_fields: description: "A külső merevlemez elérési útja, ahol a Calibre könyvtár található" locked_after_deploy: true + # `09` §3 decision 61 (R-752): Calibre-Web locks a login NAME for a day after 40 wrong tries (cps/web.py:2218), and + # its default name `admin` is public — a stranger could lock the household out. The box makes the name at install + # (lowercase letters and digits, so nobody mistypes a special character) and after_install renames `admin` to it. + - env_var: ADMIN_USER + label: "Admin felhasználónév" + type: secret + generate: "hex:5" + description: "Az első bejelentkezéshez ez a felhasználónév kell (nem az admin). A telepítéskor készül, csak te látod." + locked_after_deploy: true + # `09` §3 decision 45: Calibre-Web starts with admin / admin123. The box replaces that password with this # generated one right after the install (after_install below). Its password policy demands a special character, # hence `:special` (controller >= 0.280.0). - env_var: ADMIN_PASSWORD - label: "Admin jelszó (admin)" + label: "Admin jelszó" type: password generate: "password:24:special" - description: "Az első bejelentkezéshez: admin és ez a jelszó. Kell benne kis- és nagybetű, szám és egy különleges karakter." + description: "Az első bejelentkezéshez: a fenti felhasználónév és ez a jelszó. Kell benne kis- és nagybetű, szám és egy különleges karakter." locked_after_deploy: true # --- App info (info page content) --- @@ -88,7 +98,7 @@ app_info: first_steps: - 'Nyisd meg a books.DOMAIN címet a böngészőben' - - 'Jelentkezz be: admin és a Beállítások oldalon látható első jelszó' + - 'Jelentkezz be a Beállítások oldalon látható felhasználónévvel és első jelszóval' - 'Dobj egy könyvet a Fájlkezelőben (FileBrowser) az import/calibre mappába — automatikusan feldolgozza és a media/books könyvtárba helyezi' prerequisites: @@ -96,15 +106,18 @@ app_info: - 'x86 processzor szükséges (a CWA tartalmazza a Calibre binárist)' - 'Legalább 768 MB szabad RAM ajánlott' -# --- After a fresh install (controller >= 0.280.0, decision 45) --- -# Calibre-Web's OWN `cps.py -s user:password`, as the app user. Measured on 9202 2026-09-29: afterwards admin123 no -# longer signs in, the new one does; a password without a special character is refused by its policy. +# --- After a fresh install (controller >= 0.280.0; decisions 45, 61) --- +# Calibre-Web has no command that renames a user (cps/cli.py: only `-s user:password`); its admin page renames by setting +# the user table's `name` (admin.py:2789, ub.py:264 — unique). So, as the app user: rename `admin` in app.db to the +# generated name (skipped when already done — the box retries), then Calibre-Web's OWN `cps.py -s name:password` +# (its password policy applies), then PROVE it: the new name's stored hash takes the new password and no `admin` is +# left. Only then the success line. Both values are their own arguments (sys.argv), never pasted into the code. after_install: service: calibre-web user: abc - env: [ADMIN_PASSWORD] - command: ["python3", "/app/calibre-web-automated/cps.py", "-p", "/config/app.db", "-s", "admin:${ADMIN_PASSWORD}"] - success: "Password for user 'admin' changed" + env: [ADMIN_USER, ADMIN_PASSWORD] + command: ["python3", "-c", "import sqlite3, subprocess, sys\nfrom werkzeug.security import check_password_hash\nname, pw, db = sys.argv[1], sys.argv[2], '/config/app.db'\nc = sqlite3.connect(db)\nrow = c.execute(\"SELECT id FROM user WHERE lower(name) = 'admin'\").fetchone()\nif row:\n c.execute('UPDATE user SET name = ? WHERE id = ?', (name, row[0]))\n c.commit()\nc.close()\nr = subprocess.run(['python3', '/app/calibre-web-automated/cps.py', '-p', db, '-s', name + ':' + pw], capture_output=True, text=True)\nprint(r.stdout.strip()[-120:])\nc = sqlite3.connect(db)\nh = c.execute('SELECT password FROM user WHERE name = ?', (name,)).fetchone()\nleft = c.execute(\"SELECT count(*) FROM user WHERE lower(name) = 'admin'\").fetchone()[0]\nif h and check_password_hash(h[0], pw) and left == 0:\n print('FELHOM_AFTER_INSTALL_OK')\n", "${ADMIN_USER}", "${ADMIN_PASSWORD}"] + success: "FELHOM_AFTER_INSTALL_OK" # --- Controller-side health probe --- healthcheck: @@ -129,7 +142,7 @@ i18n: - 'KOReader sync (reading position, bookmarks)' first_steps: - 'Open books.DOMAIN in your browser' - - 'Sign in: admin and the first password shown on the settings page' + - 'Sign in with the user name and the first password shown on the settings page' - 'Drop a book into the import/calibre folder in the File manager (FileBrowser) - it is processed and filed under media/books on its own' prerequisites: - 'An external hard drive is needed to keep the e-books on' @@ -146,9 +159,12 @@ i18n: label: 'E-book library path' description: 'The path to the external hard drive where the Calibre library lives' placeholder: '/mnt/felhom-drives/hdd_1' + - env_var: ADMIN_USER + label: 'Admin user name' + description: 'You need this user name for the first sign-in (not admin). It is made at install, and only you see it.' - env_var: ADMIN_PASSWORD - label: 'Admin password (admin)' - description: 'For the first sign-in: admin and this password. It needs a lower and an upper case letter, a digit and a special character.' + label: 'Admin password' + description: 'For the first sign-in: the user name above and this password. It needs a lower and an upper case letter, a digit and a special character.' data_paths: - path: 'calibre' label: 'E-books to read in'