# `Pkcs11ex.Audit.Storage`
[🔗](https://github.com/utaladriz/pkcs11ex/blob/v0.1.0/lib/pkcs11ex/audit/storage.ex#L1)

Pluggable storage backend for `Pkcs11ex.Audit`.

Audit entries can be persisted anywhere — Postgres, SQLite, S3 with
Object Lock, append-only files, etc. The library ships
`Pkcs11ex.Audit.Storage.InMemory` for tests and dev; production
deployments implement this behaviour against their own durable store.

## Concurrency contract

Implementations MUST guarantee that `append/2` is atomic with respect
to `head/1` reads — `Pkcs11ex.Audit.append/3` reads `head` to compute
the next sequence + prev_hash, then calls `append`. If two processes
race that pattern, the storage must serialize them (via a process,
database transaction, etc.) to keep sequence numbers contiguous.

The InMemory adapter uses a single `Agent` to serialize naturally.

# `storage_handle`

```elixir
@type storage_handle() :: term()
```

# `all`

```elixir
@callback all(storage_handle()) :: Enumerable.t()
```

Iterate the log in order (seq=1 → head). Implementations may stream;
callers that walk the whole log (e.g., `Pkcs11ex.Audit.verify/1`) treat
the return as `Enumerable.t/0`.

# `append`

```elixir
@callback append(storage_handle(), Pkcs11ex.Audit.Entry.t()) :: :ok | {:error, term()}
```

Append `entry` as the new head.

# `at`

```elixir
@callback at(storage_handle(), pos_integer()) ::
  {:ok, Pkcs11ex.Audit.Entry.t()} | {:error, :not_found}
```

Look up an entry by its `:seq`.

# `head`

```elixir
@callback head(storage_handle()) :: {:ok, Pkcs11ex.Audit.Entry.t()} | {:error, :empty}
```

Return the most recently appended entry.

---

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