# `Logistiki.Audit`
[🔗](https://github.com/thanos/logistiki/blob/v0.1.0/lib/logistiki/audit/context.ex#L1)

The context for audit evidence.

Every important action in the accounting pipeline records an audit event so
that the full chain — business event, rules, policy, template, journal,
postings, ledger result — can be explained later.

# `list_audit_events`
*since 0.1.0* 

```elixir
@spec list_audit_events(keyword()) :: [Logistiki.Audit.AuditEvent.t()]
```

Lists audit events, optionally filtered.

## Arguments

  * `opts` — `keyword()` of options:
      * `:event_id` — `String.t` — filter by event id
      * `:journal_id` — `integer()` — filter by journal id
      * `:action` — `String.t` — filter by action (e.g. `"journal_posted"`)

## Returns

  * `[AuditEvent.t()]` — ordered by `inserted_at` descending.

## Examples

    iex> Logistiki.Audit.list_audit_events(event_id: "evt_001")
    [%AuditEvent{action: "business_event_received", ...}, ...]

    iex> Logistiki.Audit.list_audit_events(action: "journal_posted")
    [%AuditEvent{action: "journal_posted", ...}]

# `record`
*since 0.1.0* 

```elixir
@spec record(map()) ::
  {:ok, Logistiki.Audit.AuditEvent.t()} | {:error, Ecto.Changeset.t()}
```

Records a single audit event.

## Arguments

  * `attrs` — `map()` of audit event attributes:
      * `:action` — `String.t` — **required** (e.g. `"journal_posted"`)
      * `:event_id` — `String.t` — the originating event id
      * `:journal_id` — `integer()` — the related journal id
      * `:resource_type` — `String.t`
      * `:resource_id` — `String.t`
      * `:explanation` — `map()`
      * `:metadata` — `map()`

## Returns

  * `{:ok, %AuditEvent{}}` — the persisted audit event.
  * `{:error, %Ecto.Changeset{}}` — validation failed.

## Examples

    iex> {:ok, event} = Logistiki.Audit.record(%{action: "journal_posted", event_id: "evt_1"})
    iex> event.action
    "journal_posted"

# `record_evidence`
*since 0.1.0* 

```elixir
@spec record_evidence(Logistiki.Audit.Evidence.t()) :: :ok
```

Records every stage in an `Evidence` struct as an audit event.

## Arguments

  * `evidence` — `%Logistiki.Audit.Evidence{}` — with `stages`, `event_id`,
    `journal_id`.

## Returns

  * `:ok` — all stages were recorded.

## Examples

    iex> evidence = Logistiki.Audit.Evidence.build("evt_1", journal_id, stages, %{})
    iex> Logistiki.Audit.record_evidence(evidence)
    :ok

# `trail_for_event`
*since 0.1.0* 

```elixir
@spec trail_for_event(String.t() | atom()) :: [Logistiki.Audit.AuditEvent.t()]
```

Returns the full audit trail for a business event.

## Arguments

  * `event_id` — `String.t() | atom()` — the event id.

## Returns

  * `[AuditEvent.t()]` — ordered by `inserted_at` ascending, showing the
    full pipeline trace.

## Examples

    iex> trail = Logistiki.Audit.trail_for_event("evt_001")
    iex> Enum.map(trail, & &1.action)
    ["event_normalized", "business_event_received", "facts_generated", ...]

# `trail_for_journal`
*since 0.1.0* 

```elixir
@spec trail_for_journal(integer()) :: [Logistiki.Audit.AuditEvent.t()]
```

Returns the full audit trail for a journal.

## Arguments

  * `journal_id` — `integer()` — the journal id.

## Returns

  * `[AuditEvent.t()]` — ordered by `inserted_at` ascending.

## Examples

    iex> trail = Logistiki.Audit.trail_for_journal(1)
    iex> Enum.map(trail, & &1.action)
    ["journal_built", "invariant_validation_succeeded", "journal_posted", ...]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
