snapshot: preserve reliability hardening and Workdock identity pass

This commit is contained in:
Md Bayazid Bostame
2026-03-27 00:28:34 +01:00
parent 811bcd8745
commit 8553482ddd
39 changed files with 1393 additions and 320 deletions

View File

@@ -14,6 +14,32 @@
{% include 'workflows/includes/messages.html' %}
<section class="card">
<div class="toolbar">
<div>
<h2 style="margin:0;">{% trans "Backup-Status" %}</h2>
<div class="hint">{{ backup_health.summary }}</div>
</div>
<div class="actions">
{% if backup_health.status == 'healthy' %}
<span class="badge sent">{{ backup_health.label }}</span>
{% elif backup_health.status == 'stale' %}
<span class="badge failed">{{ backup_health.label }}</span>
{% elif backup_health.status == 'unverified' %}
<span class="badge paused">{{ backup_health.label }}</span>
{% else %}
<span class="badge cancelled">{{ backup_health.label }}</span>
{% endif %}
{% if backup_health.bundle_name %}
<span class="badge scheduled"><code>{{ backup_health.bundle_name }}</code></span>
{% endif %}
{% if backup_health.verified_at %}
<span class="hint">{% trans "Zuletzt verifiziert:" %} {{ backup_health.verified_at|slice:":16"|cut:"T" }}</span>
{% endif %}
</div>
</div>
</section>
<section class="card">
<div class="toolbar">
<div>
@@ -27,6 +53,12 @@
</div>
</section>
<section class="card">
<h2>{% trans "Automation" %}</h2>
<div class="hint">{% trans "Für einen geplanten Verify-Run außerhalb der UI:" %}</div>
<pre><code>docker compose exec -T web python manage.py verify_latest_backup --create-if-missing</code></pre>
</section>
<section class="card">
<h2>{% trans "Verfügbare Backup-Bundles" %}</h2>
{% if rows %}

View File

@@ -163,7 +163,7 @@
</section>
</div>
<div class="toolbar" style="margin-top:1.25rem;">
<div class="hint">{% trans "TUBCO bleibt als Standard erhalten, bis hier Werte geändert oder Dateien hochgeladen werden." %}</div>
<div class="hint">{% trans "Die aktuell gesetzte Deployment-Branding bleibt erhalten, bis hier Werte geändert oder Dateien hochgeladen werden." %}</div>
<button class="btn btn-primary" type="submit">{% trans "Branding speichern" %}</button>
</div>
</form>

View File

@@ -254,6 +254,10 @@ make backup-verify BACKUP_DIR=backups/backup_YYYYmmdd_HHMMSS</code></pre>
<li>Remote backup target configuration is managed in <code>Integrationen → Backup-Ziel</code>.</li>
<li>Current remote target support: <code>nextcloud</code> implemented, <code>s3</code> and <code>nfs</code> config-ready but not yet implemented.</li>
<li>Verification is non-destructive: it restores into a temporary verification database and extracts media into a temporary directory.</li>
<li>For scheduled operational hygiene, verify the newest bundle directly from the app container:
<pre><code>docker compose exec -T web python manage.py verify_latest_backup --create-if-missing</code></pre>
</li>
<li>The Backup &amp; Recovery page now shows whether the latest verification is current, stale, missing, or still unverified.</li>
<li>Real restore is explicit and destructive by design:
<pre><code>./scripts/backup_restore.sh --yes-restore backend/backups/backup_YYYYmmdd_HHMMSS</code></pre>
</li>

View File

@@ -0,0 +1,73 @@
{% extends 'workflows/base_shell.html' %}
{% load static i18n %}
{% block title %}{% trans "Job Monitor" %}{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'workflows/css/admin_tools.css' %}" />
{% endblock %}
{% block shell_body %}
{% include 'workflows/includes/app_header.html' with header_show_home=1 header_show_lang=1 header_inside_shell=1 %}
<h1>{% trans "Job Monitor" %}</h1>
<p class="sub">{% trans "Asynchrone Aufgaben, Fehler und letzte Worker-Läufe zentral prüfen." %}</p>
{% include 'workflows/includes/messages.html' %}
<section class="card">
<form method="get" class="app-registry-filters">
<div class="field">
<label for="task-filter">{% trans "Task" %}</label>
<select id="task-filter" name="task">
<option value="">{% trans "Alle" %}</option>
{% for task_name in task_names %}
<option value="{{ task_name }}" {% if task_filter == task_name %}selected{% endif %}>{{ task_name }}</option>
{% endfor %}
</select>
</div>
<div class="field">
<label for="status-filter">{% trans "Status" %}</label>
<select id="status-filter" name="status">
<option value="">{% trans "Alle" %}</option>
{% for key, label in status_choices %}
<option value="{{ key }}" {% if status_filter == key %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div class="field actions" style="align-items:end;">
<button class="btn btn-secondary" type="submit">{% trans "Filtern" %}</button>
</div>
</form>
</section>
<section class="card">
<div class="table-wrap">
<table>
<thead>
<tr>
<th>{% trans "Start" %}</th>
<th>{% trans "Task" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Ziel" %}</th>
<th>{% trans "Task ID" %}</th>
<th>{% trans "Fehler" %}</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td>{{ log.started_at|date:"d.m.Y H:i:s" }}</td>
<td>{{ log.task_name }}</td>
<td><span class="badge {% if log.status == 'failed' %}failed{% elif log.status == 'succeeded' %}sent{% else %}scheduled{% endif %}">{{ log.get_status_display }}</span></td>
<td>{{ log.target_label|default:log.target_type }}</td>
<td><code>{{ log.task_id|default:"-" }}</code></td>
<td>{% if log.error_message %}<code>{{ log.error_message|truncatechars:180 }}</code>{% else %}-{% endif %}</td>
</tr>
{% empty %}
<tr><td colspan="6">{% trans "Noch keine Task-Läufe vorhanden." %}</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endblock %}

View File

@@ -207,9 +207,13 @@
<li>Backup standard: create DB+media bundles under <code>backups/</code> and verify them with a temporary restore before using a real restore.</li>
<li>Staff UI shortcut: Admin Apps → <code>Backup &amp; Recovery</code> for create, verify, and delete actions.</li>
<li>Each backup row shows both local bundle availability and remote backup state.</li>
<li>The backup page also shows whether the latest verification is current, stale, missing, or still pending.</li>
<li>Remote backup target configuration lives under Admin Apps → <code>Integrationen</code><code>Backup-Ziel</code>.</li>
<li>Nextcloud remote backups must use a separate backup directory, not the normal onboarding/offboarding document directory.</li>
<li>Longer-running admin actions such as backup create/verify and integration tests use the same shared progress overlay after confirmation.</li>
<li>For scheduled verification outside the browser, run:
<pre><code>docker compose exec -T web python manage.py verify_latest_backup --create-if-missing</code></pre>
</li>
<li>Brand assets such as logo and PDF letterhead are managed separately under Admin Apps → <code>Branding</code>.</li>
<li>Trial deployments can force safe integration behavior: Nextcloud is treated as disabled and email remains in test mode while the trial restriction is active.</li>
<li>Expired trials should be cleaned with the dedicated command, not from the browser:

View File

@@ -40,9 +40,15 @@ docker compose up -d --build web worker</code></pre>
<li>{% trans "Run tests or a targeted verification command for the changed area." %}</li>
<li>{% trans "Compile translations after UI/content changes." %}</li>
<li>{% trans "If dependencies changed, verify imports do not emit warnings." %}</li>
<li>{% trans "Verify the latest backup bundle before release if operational tooling, storage, or restore behavior changed." %}</li>
<li>{% trans "Prefer the single local release gate command so local validation matches CI." %}</li>
</ul>
<pre><code>docker compose exec -T web python manage.py check
<pre><code>make release-validate
# individual commands if needed:
docker compose exec -T web python manage.py check
docker compose exec -T web python manage.py test
docker compose exec -T web python manage.py verify_latest_backup --create-if-missing
make i18n-compile
docker compose exec -T web python -c "import requests"</code></pre>
</section>