# `Accrue.Plug.PutOperationId`
[🔗](https://github.com/szTheory/accrue/blob/accrue-v0.3.0/lib/accrue/plug/put_operation_id.ex#L1)

Sets `Accrue.Actor` operation_id from `conn.assigns[:request_id]`.

Run AFTER `Plug.RequestId` in the host endpoint pipeline so that the
request_id assign is populated:

    plug Plug.RequestId
    plug Accrue.Plug.PutOperationId

The operation_id propagates into outbound Stripe idempotency keys
(via `Accrue.Actor.current_operation_id!/0`) so retries of the same
HTTP request converge to the same Stripe-side call.

## Fallback order

  1. `conn.assigns[:request_id]` — set by `Plug.RequestId`
  2. `x-request-id` header (if RequestId plug is not wired)
  3. Randomly generated `http-<16hex>` sentinel

The third branch is NOT written back to the header — it is only used
as a process-local seed. Wire `Plug.RequestId` for deterministic
request tracing.

## Security

The `x-request-id` header is untrusted attacker input. It is used
ONLY as the idempotency seed — never for authorization.
An attacker pinning a value at worst causes their own retries to
converge to the same Stripe call, which is correct.

---

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