The main sweep — ~260 call sites across ~100 files move from string
concatenation on a single root to appDir/storageAppDirs/storageAppConfigs.
On a single-root install the resolved paths are identical, so this is a
no-op until a location is registered.
Enumerators were the interesting half. `for d in "$containers_dir"/*/`
appears in the menus, the registry/artifact scanners and the DNS setup —
and a shell glob cannot list a rootless 751 tree at all, which is the
same bug config_find_file.sh already documents in a comment. Routing them
through storageAppDirs (which enumerates as the owning user) fixes that
alongside the multi-root work.
Three places needed judgement rather than substitution:
db_app_scan.sh deletes database rows and port allocations for apps whose
folder is missing, and reaps "empty" app dirs. With a storage location
unmounted, every app on it looks exactly like that. Each of those
branches now gates on appStorageAvailable first — an app on an unplugged
drive is skipped with a notice, never deleted.
instance_create.sh rewrites cloned hooks so an instance touches its own
directory instead of the base app's. Its sed matched ${containers_dir}<type>,
which this sweep just replaced with $(appDir <type>) — so it would have
silently stopped redirecting, and an instance would have written to the
original's files (the adguard auth adapter case its own comment warns
about). Now matches both appDir forms, verified against bare, quoted,
unrelated-app, legacy and prose cases.
peer_shell/peer_pull streamed and extracted relative to the primary root.
Both now use the app's own root, and peer_shell keeps a single-root
fallback since it runs as a restricted SSH shell with no LibrePortal env.
Also fixes a pre-existing bug found on the way: webui_app_config.sh
tested "$containers_dir/frontend/data/last_update", one level short of the
real tree under the libreportal app dir, so the WebUI refresh trigger
after a config update has never once fired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tool descriptions were leaking internal vocabulary (Django superuser,
Postgres bcrypt update, htpasswd in protectionauth.yml, gitea admin
user change-password CLI, trusted_domains list, …) and repeating the
label as a full sentence. Beginners don't care, and even experienced
users don't need the CLI name to know what a button does.
Rewrites every tool description to a single short sentence plain
enough that a first-time installer can read it without context.
Conventions applied across the board:
- One sentence, sentence-case
- Plain English: "Set a new password", "Add a new user",
"Permanently remove a user", "List every user"
- "Leave blank to generate one" only where it's actually useful
(password fields), and matches the field placeholder text
- No CLI names, no schema field names, no internal file paths
- Destructive actions stop saying "permanently" twice (the action
label + the confirm modal already cover that)
- Field placeholders harmonised: "Leave blank for random" /
"Leave blank to generate" → consistently "Leave blank to generate"
Touched files (descriptions only — no logic, no fields removed):
containers/adguard/tools/adguard.tools.json
containers/bookstack/tools/bookstack.tools.json
containers/dashy/tools/dashy.tools.json
containers/focalboard/tools/focalboard.tools.json
containers/gitea/tools/gitea.tools.json
containers/gluetun/tools/gluetun.tools.json
containers/invidious/tools/invidious.tools.json
containers/linkding/tools/linkding.tools.json
containers/nextcloud/tools/nextcloud.tools.json
containers/pihole/tools/pihole.tools.json
containers/traefik/tools/traefik.tools.json
Signed-off-by: librelad <librelad@digitalangels.vip>
Each app now carries everything under containers/<app>/: Tools-tab actions in
tools/ (declaration <app>.tools.json + function <app>_<tool_id>.sh) and logic
helpers in scripts/ (e.g. <app>_auth.sh). The container scan live-sources every
.sh under the app (maxdepth 3, prunes only resources/) and webui_tools.sh
auto-merges the .tools.json, so an app is a true drop-in — no central edit, no
array regen.
- Empty the central webui_tools.sh heredoc; all 34 tools across 11 apps now
come from per-app declarations (verified byte-identical to the old output).
- Retire the orphaned mattermost tool scripts to scripts/unused (there is no
containers/mattermost; its install fn already lived in unused).
- Update the dispatch comment/error path, the auth-adapter doc, and
DEVELOPMENT.md to the new convention.
- Regenerate static arrays (files_app.sh no longer lists app/containers/*).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>