From eea5b41e68f7b9ba0070f69b591e1e542724c9c6 Mon Sep 17 00:00:00 2001 From: librelad Date: Sun, 24 May 2026 17:55:07 +0100 Subject: [PATCH] fix(rootless): tagsManager in-place edit via runFileOp/runInstallOp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tagsManagerUpdateUniversalTag did a bare 'sed -i "$file_path"' — works only because start.sh runs as root today; under Model-A-as-manager the manager can't create sed's temp file in the dockerinstall-owned containers dir (permission denied). Make the in-place edit run AS the file's owner: classify by path (containers/ -> runFileOp, manager configs/templates -> runInstallOp), like createTouch. The awk read stays unescalated (config/compose are world-readable). Unblocks running the whole app as the manager for tag ops. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- scripts/config/tags/manager/tags_manager_update.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/config/tags/manager/tags_manager_update.sh b/scripts/config/tags/manager/tags_manager_update.sh index 107a670..aa047ab 100755 --- a/scripts/config/tags/manager/tags_manager_update.sh +++ b/scripts/config/tags/manager/tags_manager_update.sh @@ -45,9 +45,12 @@ tagsManagerUpdateUniversalTag() esc_placeholder=$(printf '%s' "$current_placeholder" | sed 's/[][\\.*^$/|]/\\&/g') esc_new=$(printf '%s' "$new_content" | sed 's/[\\&|]/\\&/g') - # Single-pass substitution, scoped to lines carrying this tag's - # annotation. The annotation's default-value field and any matching - # placeholder in the body of the same line both update together - # (they start identical and stay identical after each call). - sed -i "/#LIBREPORTAL|${tag_name}|/s|${esc_placeholder}|${esc_new}|g" "$file_path" + # Single-pass substitution, scoped to lines carrying this tag's annotation. + # The in-place edit runs AS the file's owner (no root): under + # /docker/containers/ that's the docker install user (runFileOp); the + # manager-owned configs/ + install templates use runInstallOp. The read + # (awk above) needs no escalation — config/compose files are world-readable. + local op="runInstallOp" + [[ "$file_path" == "$containers_dir"* || "$file_path" == /docker/containers/* ]] && op="runFileOp" + $op sed -i "/#LIBREPORTAL|${tag_name}|/s|${esc_placeholder}|${esc_new}|g" "$file_path" }