# Audit log and Discord logging

> Search audit activity in the dashboard and send selected events to Discord channels

The audit feature has two parts:

- The dashboard keeps the searchable audit ledger for the server.
- Discord routes send selected activity to one or more staff channels.

An event can appear in the dashboard without being sent to Discord. A route is
only a delivery rule. It does not create an event by itself.

<DocCallout type="note" title="This is not Discord's native audit log">
	The Aethor audit log records Aethor actions such as suggestion changes and
	server configuration updates. It does not read Discord's native audit-log
	history.
</DocCallout>

## Open the audit log

In the dashboard, choose a server and open **Audit log**. The page shows recent
events and the outbound Discord routes below the ledger.

![The Aethor audit log filters and first activity rows](../../../../static/screenshots/dashboard/audit-log.png)

The activity list is captured separately so the event rows stay readable on
smaller screens:

![The Aethor audit activity list](../../../../static/screenshots/dashboard/audit-activity.png)

The page currently shows up to 90 days of available events. The list is the
server's central history, even when no Discord route matches an event.

### What an event contains

Each row identifies the following information when it is available:

| Field | What it tells you |
| --- | --- |
| Action | The canonical operation, such as `Suggestion state changed`. |
| Target | The resource affected, such as Suggestion 17 or a member. |
| Actor | The person or system that performed the action. |
| Outcome | `Succeeded`, `Denied` or `Failed`. |
| Source | Where the action started: Dashboard, Discord command, Discord message, Discord button or Discord slash submit. |
| Authentication | The authentication method. This stays separate from the source. |
| Session | The dashboard session, when the event came from the dashboard. |
| Correlation | A request or trace ID for incident work. |

Safe before and after values appear in the event detail panel. The dashboard
redacts credentials, OAuth values, tokens, request bodies and message-content
fields. Ordinary fields such as `action`, `fromState`, `toState` and `deleted`
remain visible so the change is understandable.

## Search the ledger

Use **Apply filters** after changing any filter. The available filters are:

1. **Actor** searches the member directory.
2. **Action** uses the event catalog instead of requiring an internal operation key.
3. **Outcome** narrows the result to succeeded, denied or failed actions.
4. **Source** separates dashboard actions from Discord messages, buttons, slash submits and commands.
5. **Target type** and **Target ID** find the affected resource. Selecting a member target changes the ID field into a member picker.
6. **Session** selects one dashboard session.
7. **Correlation ID** performs an exact search against the request ID or trace ID.
8. **From** and **Until** limit the time range.

Click an event row to open its details. The detail panel shows the actor,
target, source, session, correlation value, event ID and resource revision when
those values exist. The change summary is a field table with before and after
values. A changed field is marked directly in the table.

## Send activity to Discord

The dashboard keeps the ledger even when Discord delivery is disabled. To add a
Discord destination:

1. Open **Audit log** for the server.
2. Scroll to **Send audit activity to Discord**.
3. Select **Manage destinations** or use **New route** in **Outbound audit routes**.
4. Enter a route name, such as `Suggestion activity` or `Moderation review`.
5. Choose one destination channel.
6. Select one or more activity categories, or choose specific actions.
7. Optionally select the outcomes that should be delivered.
8. Save the route.

![The outbound audit route editor with a channel picker, categories and specific actions](../../../../static/screenshots/dashboard/audit-route-editor.png)

The route list is also available as its own crop:

![The outbound audit route list](../../../../static/screenshots/dashboard/audit-routes.png)

### Categories and actions

The available broad categories are:

- Suggestions
- Moderation
- Roles
- Configuration
- Security
- System

Category selection is broad. For example, a route with **Suggestions** receives
all matching suggestion activity. A route with no category and only
`suggestion.state.transition` receives only state changes.

Specific action selections add to category selections. They do not subtract
actions from a selected category. Leave categories empty when a route should
only receive the actions you picked.

The outcome filter is separate. Leave it empty to allow succeeded, denied and
failed events. Select **Denied** and **Failed** on a moderation route when staff
only need exceptions.

### Multiple routes

Each route sends to exactly one Discord channel. You can create several routes,
for example:

| Route | Channel | Selection |
| --- | --- | --- |
| Suggestion activity | `#suggestion-log` | Suggestions |
| Moderation review | `#staff-log` | Moderation, denied and failed outcomes |
| Role changes | `#role-log` | Roles |
| Configuration changes | `#server-changes` | Configuration |

One event can match more than one route and be sent to more than one channel.
An event that matches no route remains in the dashboard ledger.

<DocCallout type="warning" title="Give routes a staff-only destination">
	Suggestion cards include a short content preview and identify the author and
	acting moderator. Use a private staff channel and grant Aethor View Channel
	and Send Messages there.
</DocCallout>

## Manage routes in Discord

Run this command in the server:

<Cmd cmd="/audit" />

Aethor replies privately with the same route collection used by the dashboard.
From that view, managers can add, edit, refresh and delete destinations. The
Discord editor accepts comma-separated categories, action keys and outcomes.
It does not search the central ledger. Use the dashboard for event history and
filters.

Changing a route in Discord changes what the dashboard shows, and changing it
in the dashboard changes the `/audit` view. There is no separate Discord-only
configuration.

## What the Discord card looks like

Suggestion activity currently uses a staff-facing Components V2 card. It has a
colored accent, an action title, the suggestion or review number, a shortened
suggestion preview and an audit section. Depending on the event, it can also
show the author, acting member, review ID, state transition, vote counts,
origin, media count, reason, comment and before/after content.

The wiki renders a representative card below. The exact text, accent color and
buttons depend on the action and the guild's configured suggestion labels and
emojis.

<discord-messages class="not-prose">
	<discord-message profile="aethor">
		<discord-embed slot="embeds" data-bot-emoji-title="accept" embed-title="Suggestion created" color="#41ebf4" thumbnail="/logo-round.webp">
			<discord-embed-description slot="description"><small>Suggestion #17 • just now</small><br /><br /><strong>Suggestion</strong><br />Add a channel for release notes.<br /><br /><strong>Audit</strong><br />Author: @member<br />Actor: @member<br />Source: Discord message<br />Origin: Message</discord-embed-description>
		</discord-embed>
		<discord-action-row slot="components">
			<discord-button type="secondary"><BotEmoji name="open" /> Open suggestion</discord-button>
			<discord-button type="primary"><BotEmoji name="shield" /> Manage</discord-button>
		</discord-action-row>
	</discord-message>
</discord-messages>

The controls are checked again when someone clicks them. Seeing a historical
card does not grant permission to open or manage the suggestion.

Logging is best effort. If Aethor cannot send to one route, the completed
suggestion action is not rolled back and other matching routes can still
receive the card.

## Suggestion log migration

Older guilds may have a single `suggest_logs` or `audit_log_channel` value. The
current route system migrates that setting automatically into a stable
`Suggestion activity` route. The route keeps the old channel and selects the
suggestion actions only.

Migration happens the first time the route collection is read, when `/audit` is
opened, or when a suggestion log is sent. Moderators do not need to copy the
channel into the new editor. The old fields remain as compatibility mirrors
while older bot versions are still supported.

Deleting the migrated route clears those old mirror values, so the route is not
created again on the next read. Existing Discord messages are not moved, and
the migration does not invent audit events for past activity.

The old suggestion setup **logs channel** control now edits this same route.
Use the route manager when you want different channels for suggestions,
moderation, roles or other event categories.

## Current Discord coverage

The central dashboard ledger covers more operations than the current Discord
projection path. Suggestion-log actions have the staff card shown above. Route
selectors can accept known and future action keys, but a route only sends when a
real producer emits the selected event.

For example, selecting a future `spool` action does not make Aethor send a
message until a producer for that action exists. Unmatched or dashboard-only
events remain searchable in the central ledger.

## Permissions and troubleshooting

Viewing the dashboard audit log uses the server's administrator audit-read
capability. Creating or changing routes uses the administrator configuration
capability. The `/audit` command also requires the configuration capability.
See [Permissions and capabilities](/docs/permissions) if the page or command
is unavailable.

If no card arrives in Discord, check these in order:

1. Confirm that the event actually occurred and appears in the dashboard ledger.
2. Check that the event action or category matches the route.
3. Check the route's outcome filter.
4. Confirm that the route is enabled and points to the intended channel.
5. Give Aethor View Channel and Send Messages in that channel.
6. Check that the destination channel still exists and that the bot can see it.

If the event is in the dashboard but not in Discord, the problem is in route
selection or delivery. If the event is absent from both, the action may not
have a producer yet or the action may have been denied before an audit row was
written.

## Debug audit activity with OTEL

Audit activity is connected to the bot's OTEL trace. When a dashboard or
Discord action writes an audit event, the active trace ID is stored with the
event. Authorized operators can copy that value from the event detail and use
it to find the trace in Light/VictoriaTraces.

The useful spans are:

1. `audit.read` shows the dashboard list or detail query.
2. `application.audit.append` or `audit.event` shows the central ledger write.
3. `audit.route.list` and `audit.route.migrate_legacy` show route loading and
   automatic migration.
4. `audit.route.delivery` shows each Discord channel attempt, including the
   child Discord REST call.

Filter spans by `aethor.audit.operation`, then inspect
`aethor.audit.category`, `aethor.audit.source`, `aethor.audit.target_type`,
`aethor.audit.delivery_outcome` or `aethor.audit.migration_outcome`. The spans
record routing facts, not suggestion text. Message bodies, credentials, OAuth
values and request bodies are excluded.

For rate and latency views, use the bot metrics
`bot_audit_event`, `bot_audit_route_match`, `bot_audit_route_delivery`,
`bot_audit_route_delivery_duration`, `bot_audit_route_mutation` and
`bot_audit_route_migration`. Metrics use bounded category, source and outcome
labels. Use a trace for one event or channel; use a metric for trends and
failure rates.

## Related guides

<div class="not-prose doc-link-card-grid">
	<DocLinkCard
		href="/docs/dashboard"
		eyebrow="Dashboard"
		title="Use the dashboard"
		description="Learn how to sign in, choose a server and move between dashboard pages."
	/>
	<DocLinkCard
		href="/docs/suggestions/operations"
		eyebrow="Suggestions"
		title="Run suggestion operations"
		description="Search, export and maintain the suggestion workflow."
	/>
	<DocLinkCard
		href="/docs/permissions"
		eyebrow="Access"
		title="Configure permissions"
		description="Delegate Aethor actions to Discord roles and test access."
	/>
</div>
