LibrePortal/scripts/cli/commands/app/cli_app_header.sh
librelad 4a1aa43083 feat(artifact): app bundle applier + libreportal app add — the marketplace verb
Opens the two designed seams (roadmap §8.4): _artifactResolve accepts
type:"app" (slug validated, the installed-app gate skipped — presence is
the collision policy's call), and payload.kind:"bundle" gets its own APPLY
flow. The download core (sha256 pin vs the signed index + minisig +
refuse-unsigned) is factored into _artifactDownloadVerified, shared by ops
and bundle payloads.

A bundle add: fetch → quarantine-validate → place in the definition tree
(staging + one rename, manager funnel) → lpRegenWebui → verify the app
surfaced in apps.json → applied-record with a precise undo → History.
The validator is fail-closed (traversal/absolute paths, links/devices,
single top-level dir == slug, charset, size/entry caps, set-id strip,
config TITLE+CATEGORY + compose present, bash -n every .sh) because the
definition tree is live-sourced on every CLI start — nothing lands there
before trust + quarantine pass. Collision policy: installed-live refused,
local definitions win, registry-owned re-add = reversible definition
update (prior tree packed into the undo). Revert removes/restores the
definition (refused while installed) and regens. Apps never auto-apply
(type filter kept + publisher forces auto:false).

New verb: libreportal app add <slug|artifact-id> (app_add task; resolves
by slug via appAddFromRegistry, ambiguity refused).

Also fixes the second half of the sigstate-propagation bug class:
artifactApply captured $(_artifactResolve) in a subshell, stranding
_ART_INDEX/_ART_APP/_ART_SCOPE AND the LP_INDEX_SIGSTATE the apply gate
enforces — on a signed box every apply would have refused as unsigned.
Resolve now assigns globals (_ART_JSON) and is called directly.

Source-and-mock harness: 46/46 (resolve gates, 14 validator refusals,
happy add, collision matrix, definition-update round-trip, revert
semantics, postcheck + record-failure rollbacks, apply-auto exclusion,
app add verb).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-07-03 21:14:14 +01:00

44 lines
2.8 KiB
Bash
Executable File

#!/bin/bash
# App Commands Header
# Shows available app commands and help information
cliShowAppHelp()
{
echo ""
echo "Available App Commands (* is required):"
echo ""
echo " libreportal app list [type*] - Display a list of applications"
echo " available - Show available apps to install"
echo " installed - Show installed apps"
echo ""
echo " libreportal app install [name*] [config] [--reset-network]"
echo " - Install / reinstall the specified app."
echo " On reinstall, IPs and ports are preserved by default."
echo " Pass --reset-network to re-randomize them."
echo " libreportal app add [name*] - Add an app definition from the signed registry"
echo " catalog (marketplace). It then installs like any"
echo " other app. Browse: libreportal artifact index"
echo " libreportal app uninstall [name*] - Uninstall the specified app"
echo ""
echo " libreportal app start [name*] - Start the specified app (Must be installed)"
echo " libreportal app stop [name*] - Stop the specified app (Must be installed)"
echo " libreportal app restart [name*] [service] - Restart the specified app, or just one of its"
echo " compose services when [service] is given"
echo ""
echo " libreportal app up [name*] - Docker-Compose up (Rebuild app)"
echo " libreportal app down [name*] - Docker-Compose up (Uninstall app)"
echo " libreportal app reload [name*] - Docker-Compose up & down (Reinstall app)"
echo ""
echo " libreportal app backup [name*] [password] - Backup the specified app (password optional)"
echo " libreportal app restore [name*] [file|--latest] [password] - Restore from local/remote, prefers local"
echo " libreportal app restore [name*] [local|remote1|remote2] [file] [password]"
echo " - Restore from a specific location"
echo " libreportal app status [name*] - Show status of specified app"
echo " libreportal app tool [name*] [tool*] [args]"
echo " - Run a per-app tool (Tools tab actions)."
echo " [args] is pipe-encoded: key=value|key=value"
echo " libreportal app tool list [name] - List available tools (all apps, or just [name])"
echo ""
}