Webapp: Updates pages, image page tabs with review-before-save, BPRT sync

Updates group:
- Dell drivers and BIOS: check Dell's catalogs against all three driver maps
  and models.txt, download with a shared speed cap, repack, preview, apply
  with backups and rollback.
- iPXE boot files: check GitHub for the signed Secure Boot set, verify the
  sha256 and each file's signer, install atomically, roll back. Includes the
  by-hand procedure.
- Blancco: upload a release, stage it, test-boot it from the menu, activate,
  roll back.
- BPRT sync: validate a batch uploaded from the MediaCreator Lite cache
  (scripts/windows/Sync-BPRT.ps1 or a zip), show the diff, swap with the site
  overlay files kept.

Images: one sidebar entry per image with Overview, Drivers, Unattend and OS and
Packages tabs. Every save shows a diff first, keeps the file's format, makes a
backup and can be undone. Driver lint runs inline.

Enrollment: upload standard/engineer MCL packages, one per tenant/purpose,
with archive and restore. Hardware coverage counts engineer as Win11.
This commit is contained in:
cproudlock
2026-10-13 16:58:55 -04:00
parent ddf0a2fdf2
commit 397063f987
39 changed files with 15109 additions and 1106 deletions

View File

@@ -102,19 +102,45 @@
</li>
</ul>
<div class="nav-section">GE Aerospace Images</div>
<div class="nav-section">Updates</div>
<ul class="sidebar-nav nav flex-column">
{% for it in all_image_types if it.startswith('gea-') %}
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'unattend_editor' and image_type is defined and image_type == it %}active{% endif %}"
href="{{ url_for('unattend_editor', image_type=it) }}">
<i class="bi bi-windows"></i> {{ all_friendly_names[it] }}
<a class="nav-link {% if request.endpoint and request.endpoint.startswith('dell_updates.') %}active{% endif %}"
href="{{ url_for('dell_updates.page') }}">
<i class="bi bi-motherboard"></i> Dell Drivers and BIOS
</a>
</li>
<li class="nav-item">
<a class="nav-link nav-sublink {% if request.endpoint == 'image_config' and image_type is defined and image_type == it %}active{% endif %}"
href="{{ url_for('image_config', image_type=it) }}">
<i class="bi bi-gear"></i> Configuration
<a class="nav-link {% if request.endpoint and request.endpoint.startswith('ipxe.') %}active{% endif %}"
href="{{ url_for('ipxe.page') }}">
<i class="bi bi-shield-lock"></i> iPXE Boot Files
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint and request.endpoint.startswith('blancco_update.') %}active{% endif %}"
href="{{ url_for('blancco_update.page') }}">
<i class="bi bi-eraser"></i> Blancco Updates
</a>
</li>
<li class="nav-item">
{# Plain href: the page still renders if views.bprt_sync is not registered yet. #}
<a class="nav-link {% if request.endpoint and request.endpoint.startswith('bprt_sync.') %}active{% endif %}"
href="/updates/bprt/">
<i class="bi bi-arrow-left-right"></i> BPRT Sync
</a>
</li>
</ul>
<div class="nav-section">GE Aerospace Images</div>
<ul class="sidebar-nav nav flex-column">
{% for it in all_image_types if it.startswith('gea-') %}
{# One entry per image; active on any of its tabs (see _image_header.html). #}
{% set _on_image = image_type is defined and image_type == it
and ((active_tab is defined and active_tab) or image_tab_for_endpoint(request.endpoint)) %}
<li class="nav-item">
<a class="nav-link {% if _on_image %}active{% endif %}"
href="{{ image_tab_url(it, 'overview') }}">
<i class="bi bi-windows"></i> {{ all_friendly_names[it] }}
</a>
</li>
{% endfor %}