{# Cooperative control panel. POSTs write the control_state row; the monitor obeys it within ~3s. All actions carry the X-Avai-Token header (injected from localStorage by dashboard.html); the server fails closed without it. Swapped into #control on load/poll and after every action. #} {% from "partials/_macros.html" import btn %} {% set disabled = (ctrl.disabled_collectors.split(',') if ctrl and ctrl.disabled_collectors else []) %} {% set paused = ctrl and ctrl.paused %}

monitor control

{% if alive %} {{ ctrl.status or "running" }}{% if ctrl and ctrl.pid %} · pid {{ ctrl.pid }}{% endif %} {% else %} {# Offline is a critical state (data is stale) — surface it as a clear red badge, not a muted grey dot that blends into the chrome. #} monitor offline {% endif %}
{% if not control_enabled %}
Control is disabled. Set AVAI_CONTROL_TOKEN on the dashboard process to enable it, then paste the token below.
{% endif %} {# Two columns on wide screens so the panel fills its width instead of leaving the right half empty: left = operate now, right = manage. #}
{# ===== left column: operate ===== #}
{# Token lives only in the browser (localStorage), never server-rendered. #}
{# pause / resume + scan now. resume = success (positive), pause = secondary (quieter), scan now = primary (the prominent immediate action). #}
{% if paused %} {{ btn('▶ resume', 'success', extra='hx-post="/control/resume" hx-target="#control" hx-swap="innerHTML"') }} {% else %} {{ btn('⏸ pause', 'secondary', extra='hx-post="/control/pause" hx-target="#control" hx-swap="innerHTML"') }} {% endif %} {{ btn('⟳ scan now', 'primary', extra='hx-post="/control/scan-now" hx-target="#control" hx-swap="innerHTML"') }} {% if paused %}scanning paused{% endif %}
{# live settings — `apply` is the primary action that commits this form. #}
{{ btn('apply', 'primary', type='submit') }}
{# /left column #} {# ===== right column: manage ===== #}
{# per-collector enable/disable — each is a state toggle (aria-pressed reflects on/off so screen readers announce the current state). #}
scanners ({{ collectors|length - disabled|length }}/{{ collectors|length }} on)
{% for name in collectors %} {% set off = name in disabled %} {% endfor %}
{# maintenance one-shots. Routine actions are secondary; the two consequential ones read as warning (recoverable) / danger (irreversible). #}
maintenance
{{ btn('prune to size', 'secondary', extra='hx-post="/control/maintenance/prune" hx-target="#control" hx-swap="innerHTML"') }} {{ btn('re-judge', 'secondary', extra='hx-post="/control/maintenance/rejudge" hx-target="#control" hx-swap="innerHTML"') }} {{ btn('re-narrate', 'secondary', extra='hx-post="/control/maintenance/renarrate" hx-target="#control" hx-swap="innerHTML"') }} {{ btn('reset baseline', 'warning', extra='hx-post="/control/maintenance/reset_baseline" hx-target="#control" hx-swap="innerHTML" hx-confirm="Reset the host baseline? Run history is dropped and novelty re-learns over the next runs."') }} {{ btn('clear data', 'danger', extra='hx-post="/control/maintenance/clear" hx-target="#control" hx-swap="innerHTML" hx-confirm="Wipe ALL collected telemetry, runs, verdicts, narratives and risk scores? This cannot be undone."') }}
{% if ctrl and ctrl.command_result %}
last action: {{ ctrl.command_result }}
{% endif %}
{# /right column #}
{# /two-column grid #}