{# Single row in the API keys list. Receives ``row`` (see ``_row_context``). #}

{{ row.name }}

{# Status chip. #} {% if row.status == "active" %} Active {% elif row.status == "revoked" %} Revoked {% else %} Expired {% endif %}
Workspace: {{ row.workspace_name }} {% if row.last_used_at %} Last used {{ row.last_used_at|timesince }} ago {% else %} Never used {% endif %} {% if row.issued_by %} Issued by {{ row.issued_by.name|default:row.issued_by.email }} {% endif %}
{% if row.accounts %}
{% for sa in row.accounts %} {{ sa.platform }} · {{ sa.account_name }} {% endfor %}
{% endif %} {% if row.permissions %}
{% for perm in row.permissions %} {{ perm }} {% endfor %}
{% endif %}
{% if row.status == "active" %}
{% comment %} Edit flow. Same CSP-safe pattern as Revoke (Alpine directives only, no inline on* handlers), but built on the issuance modal's scrollable shell since it carries three sections. A plain POST + redirect — not HTMX — so we sidestep the teleport/HTMX interplay and reuse the flash messages. {% endcomment %}
{% comment %} Revoke flow. The trigger opens an Alpine-driven confirmation modal instead of the native confirm() dialog — same look as the issuance modal, and CSP-safe: only Alpine directives and simple state toggles, no inline on* handlers and no eval-heavy expressions. Must be a comment/endcomment block (not a hash-style template comment): the hash form is single-line only, so a multi-line one leaks as literal text — and as a stray flex child here it squeezed the content column, forcing the account/permission chips to wrap one per line. {% endcomment %}
{% endif %}