ui: P2R-12 hook editor — source-group form + host-default Repo section

Source-group edit form gains pre/post hook textareas with a service-
user warning banner; bodies AEAD-encrypted on save (per-group AD).
Repo page adds a 'Host-default hooks' panel above the danger zone
with the same shape; saved via POST /hosts/{id}/repo/hooks.
This commit is contained in:
2026-05-04 11:00:28 +01:00
parent 7b1990cf11
commit a5a2cb91d0
6 changed files with 133 additions and 1 deletions
@@ -95,6 +95,27 @@
Each retry doubles the wait. <strong>Manual run-now ignores this</strong> — it just fails immediately if the agent is offline.
</div>
<h3 class="text-[11.5px] font-semibold uppercase tracking-[0.08em] text-ink-mute mb-3.5 mt-7 pt-4 border-t border-line-soft">
Hooks
<span class="text-ink-fade font-medium normal-case tracking-[0.01em] ml-2">backup jobs only</span>
</h3>
<div class="text-[12px] text-warn leading-[1.55] mb-3"
style="background: color-mix(in oklch, var(--warn), transparent 92%); border: 1px solid color-mix(in oklch, var(--warn), transparent 75%); padding: 8px 10px; border-radius: 5px;">
Hooks run as the agent service user — root on Linux, LocalSystem on Windows. Treat them like any other root cron entry.
</div>
<div class="mb-3">
<label class="field-label" for="pre_hook">Pre-backup hook</label>
<textarea id="pre_hook" name="pre_hook" class="field mono" rows="3" style="resize: vertical;"
placeholder="# e.g. systemctl stop myapp">{{$f.PreHook}}</textarea>
<div class="field-help mt-1">Non-zero exit aborts the backup. Stored AEAD-encrypted.</div>
</div>
<div class="mb-3">
<label class="field-label" for="post_hook">Post-backup hook</label>
<textarea id="post_hook" name="post_hook" class="field mono" rows="3" style="resize: vertical;"
placeholder="# RM_JOB_STATUS={succeeded|failed} is in env">{{$f.PostHook}}</textarea>
<div class="field-help mt-1">Always runs. <span class="mono">RM_JOB_STATUS</span> is set to the backup's outcome. Stored AEAD-encrypted.</div>
</div>
<div class="mt-8 pt-4 border-t border-line-soft flex gap-2">
<button type="submit" class="btn btn-primary btn-lg">{{if $page.IsNew}}Create group{{else}}Save changes{{end}}</button>
<a href="/hosts/{{$host.ID}}/sources" class="btn btn-lg">Cancel</a>