{% extends 'layout.twig' %} {% block title %}Audit — IRDB{% endblock %} {% macro action_pill(action) %} {%- set bucket = action|split('.')[0]|default('') -%} {%- set classes = { 'reporter': 'bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100', 'consumer': 'bg-cyan-100 text-cyan-900 dark:bg-cyan-900 dark:text-cyan-100', 'token': 'bg-purple-100 text-purple-900 dark:bg-purple-900 dark:text-purple-100', 'policy': 'bg-indigo-100 text-indigo-900 dark:bg-indigo-900 dark:text-indigo-100', 'category': 'bg-violet-100 text-violet-900 dark:bg-violet-900 dark:text-violet-100', 'manual_block': 'bg-amber-100 text-amber-900 dark:bg-amber-900 dark:text-amber-100', 'allowlist': 'bg-emerald-100 text-emerald-900 dark:bg-emerald-900 dark:text-emerald-100', 'job': 'bg-slate-200 text-slate-800 dark:bg-slate-700 dark:text-slate-100', } -%} {{ action }} {% endmacro %} {% block content %} {% import _self as h %} {% import 'partials/sort.twig' as sort %}

Audit log

{% if list %} {{ list.total }} total {% endif %}
{% if error %}
{{ error }}
{% endif %} {% if filters.subject_kind and filters.subject_id %}
Filtering events for {{ filters.subject_kind }} #{{ filters.subject_id }} — both events about it and events emitted by it. clear
{% endif %}
{# Subject filter is set by per-entity links (reporter/consumer detail) and preserved across re-submits of this form so a manual filter change doesn't silently widen the result. Form has no UI control for it. #} {% if filters.subject_kind %}{% endif %} {% if filters.subject_id %}{% endif %}
Reset
{# Datetime-local ⇄ ISO round-tripping for the filter form lives in app.js (initAuditFilterForm) so this page has no inline JS. #} {% if list %}
{{ sort.th('When', 'when', 'date') }} {{ sort.th('Actor', 'actor') }} {{ sort.th('Action', 'action') }} {{ sort.th('Entity', 'entity') }} {{ sort.th('Source IP', 'source_ip') }} {% for ev in list.items %} {% if ev.details %} {% endif %} {% else %} {% endfor %}
Payload
{{ ev.actor_kind }} {% if ev.actor_id %}#{{ ev.actor_id }}{% endif %} {{ h.action_pill(ev.action) }} {{ ev.entity_type|default('—') }} {% if ev.entity_label %} {{ ev.entity_label }} {% if ev.entity_id %}#{{ ev.entity_id }}{% endif %} {% elseif ev.entity_id %} #{{ ev.entity_id }} {% endif %} {{ ev.source_ip|default('—') }} {% if ev.details %} {% else %} {% endif %}
{% if ev.details.changes is defined and ev.details.changes is iterable and ev.details.changes|length > 0 %}
Changes
{% for field, change in ev.details.changes %} {% endfor %}
Field Before After
{{ field }} {% if change.from is null %} {% elseif change.from is iterable %}
{{ change.from|json_encode(constant('JSON_PRETTY_PRINT')) }}
{% else %} {{ change.from }} {% endif %}
{% if change.to is null %} {% elseif change.to is iterable %}
{{ change.to|json_encode(constant('JSON_PRETTY_PRINT')) }}
{% else %} {{ change.to }} {% endif %}
{% endif %}
Raw payload
{{ ev.details|json_encode(constant('JSON_PRETTY_PRINT')) }}
No events match these filters.
{% if list.total > list.page_size %} {% set total_pages = (list.total // list.page_size) + (list.total % list.page_size > 0 ? 1 : 0) %} {% endif %} {% endif %}
{% endblock %}