acme-proxy-admin 0.6.1

The operation layer and web admin panel of acme-proxy (internal crate, no semver promise)
Documentation
{#-
  The page chrome every full page extends.

  Only ever rendered for a *full* page. An htmx request gets the bare partial
  instead, chosen by the handler off the `HX-Request` header -- which is why no
  partial in this tree extends anything.
-#}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{ title }} — acme-proxy admin</title>
    {#-
      Both settings are load-bearing, and both are documented at length in
      `static/README.md`:

      - `includeIndicatorStyles` false, because htmx would otherwise inject an
        inline <style> element that this listener's `style-src 'self'` blocks.
        The rules it would have injected are in admin.css instead.
      - `responseHandling`, because htmx does not swap a non-2xx response by
        default -- without it a 409 `already_revoked` would fail silently
        rather than showing the operator the error banner it returned.
      - `defaultSwapStyle` outerHTML, because every fragment in this tree
        carries its swap target's `id` on its own root element. htmx's default
        `innerHTML` put that root *inside* the target, so each filter change,
        page step and mutation left two elements with one id.
    -#}
    <meta name="htmx-config"
          content='{"includeIndicatorStyles":false,"defaultSwapStyle":"outerHTML","responseHandling":[{"code":"[45]..","swap":true},{"code":"[23]..","swap":true}]}'>
    <link rel="stylesheet" href="/ui/static/admin.css">
    <script src="/ui/static/htmx.min.js" defer></script>
  </head>
  {#-
    The CSRF token every mutating request needs, attached once here rather than
    on each control. `AuthenticatedWrite` reads it from this header and nowhere
    else, so a page that loses this attribute loses every write at once -- which
    is the intended failure mode.
  -#}
  <body hx-headers='{"X-CSRF-Token": "{{ csrf_token }}"}'>
    <a class="skip-link" href="#content">Skip to content</a>
    <header class="top">
      <span class="brand">acme-proxy</span>
      {#- Grouped by what an operator came to do -- the certificates, the
          machinery behind them, and oversight of both -- rather than one flat
          row of eleven that wraps wherever the window happens to end. The
          separators are presentation only. `aria-current` says which page this
          is to a screen reader, which the underline alone does not. -#}
      <nav>
        <a href="/ui/" {% if nav == "index" %}class="active" aria-current="page"{% endif %}>Overview</a>
        <span class="nav-sep" aria-hidden="true"></span>
        <a href="/ui/accounts" {% if nav == "accounts" %}class="active" aria-current="page"{% endif %}>Accounts</a>
        <a href="/ui/orders" {% if nav == "orders" %}class="active" aria-current="page"{% endif %}>Orders</a>
        <a href="/ui/expiring" {% if nav == "expiring" %}class="active" aria-current="page"{% endif %}>Expiring</a>
        <a href="/ui/eab" {% if nav == "eab" %}class="active" aria-current="page"{% endif %}>EAB</a>
        <span class="nav-sep" aria-hidden="true"></span>
        <a href="/ui/jobs" {% if nav == "jobs" %}class="active" aria-current="page"{% endif %}>Jobs</a>
        <a href="/ui/upstream-orders" {% if nav == "upstream_orders" %}class="active" aria-current="page"{% endif %}>Upstream</a>
        <a href="/ui/nonces" {% if nav == "nonces" %}class="active" aria-current="page"{% endif %}>Nonces</a>
        <a href="/ui/profiles" {% if nav == "profiles" %}class="active" aria-current="page"{% endif %}>Profiles</a>
        <span class="nav-sep" aria-hidden="true"></span>
        <a href="/ui/audit" {% if nav == "audit" %}class="active" aria-current="page"{% endif %}>Audit</a>
        {#- Admins only, because the page is: `/ui/operators` takes
            `PageAdminRead` and every control on it takes `PageAdminWrite`, so
            for a lower tier this link only ever leads to a 403. A nav entry
            that always refuses is a worse answer than no entry. -#}
        {% if user.role == "admin" %}
        <a href="/ui/operators" {% if nav == "operators" %}class="active" aria-current="page"{% endif %}>Operators</a>
        {% endif %}
      </nav>
      <span class="whoami">
        {#- Not one more entry in the nav above: that lists resources of the
            server, and "my second factor" is not one. -#}
        <a href="/ui/account" {% if nav == "account" %}class="active" aria-current="page"{% endif %}>{{ user.username }}</a>
        <button hx-post="/ui/logout" hx-swap="none">Sign out</button>
      </span>
    </header>

    <main id="content">
      {% block content %}{% endblock %}
    </main>
  </body>
</html>