# `X402.AuthCapture.Journal`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/auth_capture/journal.ex#L1)

Durable signer-scope fencing for auth-capture transactions.

Each scope has at most one active transaction. Its immutable intent is
reserved before signing; raw bytes and their locally computed hash are
persisted before dispatch. `dispatch/3` grants permission to send exactly
once. A timeout or crash after that marker requires receipt reconciliation,
never another send, even if the first caller may not have reached the node.

Confirmed or reverted receipts retain the scope until the application has
durably applied their local effects and calls `acknowledge/3`. Completed
records remain as replay tombstones. The configurable history limit fails
closed instead of evicting them. Migration or compaction requires an
application-owned replay archive, not deleting live journal records.
Each history entry has its own key. The small scope record and the selected
entry are changed in one atomic multi-key transaction; unrelated history is
neither fetched nor rewritten. Existing-operation lookups use read-only
snapshots.

Only a preparation with no frozen transaction may be cancelled. Reserving
that cancelled intent again issues a fresh owner token. There are no leases
or timeout takeovers; abandoned preparations require explicit application
recovery. This module coordinates trusted execution code, not untrusted
HTTP clients: do not expose owner tokens or accept caller-supplied receipts.

A multi-transaction lifecycle uses one journal record per leg and a separate
durable payment record. Releasing the signer scope does not release that
payment's admission or authorize repeating a handler.

This namespace does not coordinate other schemes or the existing nonce
manager. Use a dedicated gas account or an external coordinator covering
every writer. Structural record checks fail closed on detectable corruption;
they cannot recover deleted data or authenticate a malicious storage adapter.

# `entry`

```elixir
@type entry() :: %{
  id: binary(),
  owner: binary(),
  intent: map(),
  phase:
    :preparing
    | :prepared
    | :dispatched
    | :confirmed
    | :reverted
    | :succeeded
    | :failed
    | :cancelled,
  transaction: %{raw: binary(), hash: String.t()} | nil,
  receipt: map() | nil
}
```

# `t`

```elixir
@type t() :: %X402.AuthCapture.Journal{
  history_limit: pos_integer(),
  scope: tuple(),
  store: X402.AuthCapture.Store.t()
}
```

# `acknowledge`
*since 0.9.0* 

```elixir
@spec acknowledge(t(), binary(), binary()) :: {:ok, entry()} | {:error, term()}
```

Releases a completed scope only after its local effects are durably applied.

# `active`
*since 0.9.0* 

```elixir
@spec active(t()) :: {:ok, entry() | nil} | {:error, term()}
```

Reads the active record, including finished work awaiting effect acknowledgement.

Returns `:journal_changed` if ownership changes between selecting the key and
reading the atomic snapshot. That is a safe read retry, not a new reservation.

# `cancel_preparation`
*since 0.9.0* 

```elixir
@spec cancel_preparation(t(), binary(), binary()) :: {:ok, entry()} | {:error, term()}
```

Cancels only unprepared work. Frozen or dispatched work cannot be cancelled.

# `dispatch`
*since 0.9.0* 

```elixir
@spec dispatch(t(), binary(), binary()) :: {:ok, entry()} | {:error, term()}
```

Durably grants the sole permission to send the frozen transaction.

# `fetch`
*since 0.9.0* 

```elixir
@spec fetch(t(), binary()) :: {:ok, entry() | nil} | {:error, term()}
```

Reads a retained operation without treating a store failure as absence.

# `finish`
*since 0.9.0* 

```elixir
@spec finish(t(), binary(), binary(), :confirmed | :reverted, map()) ::
  {:ok, entry()} | {:error, term()}
```

Records a trusted, verified receipt without releasing the signer scope.

The execution layer must establish transaction identity, finality, success
or revert status, and expected events before calling this function.

# `new`
*since 0.9.0* 

```elixir
@spec new(keyword()) :: {:ok, t()} | {:error, term()}
```

Builds a journal bound to a concrete EVM network and gas-account address.

* `:store` - Required.

* `:network` (`t:String.t/0`) - Required.

* `:signer` (`t:String.t/0`) - Required.

* `:history_limit` (`t:pos_integer/0`) - The default value is `10000`.

# `prepare`
*since 0.9.0* 

```elixir
@spec prepare(t(), binary(), binary(), binary()) :: {:ok, entry()} | {:error, term()}
```

Freezes raw transaction bytes and their local keccak-256 hash before any send.

# `reserve`
*since 0.9.0* 

```elixir
@spec reserve(t(), binary(), map()) ::
  {:ok, {:reserved | :existing, entry()}} | {:error, term()}
```

Reserves an immutable intent or returns its existing record.

Only `{:reserved, entry}` grants a new ownership token. An existing record
must be reconciled, not executed again. IDs are nonempty binaries of at most
128 bytes; the caller must derive them from the canonical payment operation.

---

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