{# 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 %}
Revoke API key
This can't be undone.
Revoke {{ row.name }}?
Agents using it will immediately start receiving 401 Unauthorized.