{# Recovery-mode wizard. Rendered standalone (does NOT extend ``_layout.html``) because the layout assumes a working DB + normal-mode navigation; recovery is a single-purpose page with none of those affordances. Styling reuses the vendored Bootstrap so the look is consistent with the rest of /ui. #} Recovery -- bty-web
{% if recovered %} {# Operator's polling browser raced ahead of systemd's restart window and hit the OLD recovery-mode process AFTER the wipe landed. The DB is now OK; auto-redirect with a clear status so they don't think they need to do anything else. #}

Recovery complete

{{ reason }}

Go to the dashboard if the redirect doesn't fire in a few seconds.

{% else %} {# ===== Banner: what happened + why this page exists ===== #}

state.db needs operator attention

{{ reason }}

bty-web won't accept the existing {{ state_path }} and is serving this recovery wizard instead. Pick a recovery path below; bty-web executes it, then restarts itself into normal mode.

{% endif %} {% if not recovered %} {# ===== Step 1: What we found ===== #}

1. State detected

DB path
{{ state_path }}
DB state
{{ db_state }}
Stored bty version
{% if stored_version %}{{ stored_version }}{% else %}(pre-versioning DB; no marker row){% endif %}
Running bty version
{{ running_version }}
At risk
{{ at_risk.machines }} machines, {{ at_risk.catalog_entries }} catalog entries, {{ at_risk.events }} audit events
{# ===== Step 2: Choose a recovery strategy ===== #}

2. Choose a recovery strategy

{# Strategy A: wipe + start fresh #}

A. Wipe state.db and start fresh

Discards all bty-web operator state (machine bindings, catalog entries, settings, audit log). Files under {{ state_path.rsplit('/', 1)[0] if '/' in state_path else state_path }}/images/ and boot/ are untouched. Operator re-binds machines + re-imports the catalog after restart.

{# Strategy B: wipe + import a backup #}

B. Wipe and import from a backup bundle

Same wipe as A, then loads a previously-exported bundle: hardware inventory (mac + lshw + known_disks) + all files from the bundle's files/ subdir come back. Operator still re-binds machines (boot_mode + image_ref + target_disk_serial), but the hardware identity survives.

{% if backups %}
{% else %}

No backup bundles found under {{ state_path.rsplit('/', 1)[0] if '/' in state_path else state_path }}/backups/. To get one, run bty-web export <dir> on the OLD release before upgrading next time -- see operations.md.

{% endif %}
{# Strategy C: do nothing -- manual recovery #}
C. I want to do this myself from a shell

SSH into the appliance and run:

sudo systemctl stop bty-web
sudo rm {{ state_path }}
sudo systemctl start bty-web

Loses the same state as button A. If you have a v2 bundle on disk, you can also restore it via sudo bty-web import <dir> after the wipe.

{# ===== Step 3: Restart + verify (auto-progressed) ===== #}

3. bty-web restarts with a clean DB

Waiting for an operator action above.

4. Verify

bty-web will redirect you to the dashboard when normal mode is up.

{% endif %}{# not recovered #}