# `Sigra.Workers`
[🔗](https://github.com/sztheory/sigra/blob/v1.20.0/lib/sigra/workers.ex#L1)

Behaviour contract for Sigra-aware background workers that require
tenant context. Pure `@callback` contract — the behaviour itself has
zero compile-time dependency on any background job library.

Workers implementing this behaviour:

1. Accept stringified `"organization_id"` and `"actor_id"` args (nil values
   OK, absent keys NOT OK).
2. Reconstruct a minimal `%Scope{}` in `perform/1` via `Sigra.Scope.build/3`.
3. Emit audits through `Sigra.Audit.log_safe/3` with the reconstructed scope.

## Worker scopes are audit-only

Host apps MUST NOT pass a worker-reconstructed scope to authorization
functions. Worker scopes carry only `user.id` and
`active_organization.id` — no request, no session, no membership. They
exist solely so that `Sigra.Audit.log_safe/3` picks up the right IDs
without a separate call shape.

## Not every worker needs this

`Sigra.Workers.AuditCleanup`, `TokenCleanup`, and `EmailDelivery` are
genuinely tenant-agnostic and deliberately do NOT implement this
behaviour. Use it when and only when the worker emits tenant-relevant
audits.

## v1.2 notes

When impersonation ships in v1.2, workers enqueued by an impersonator will
receive `"impersonating_from"` as an additional stringified arg, and
`perform/1` will thread it through `Sigra.Scope.build/3` — a purely
additive change. The current callback shape does NOT need to change.

# `perform`

```elixir
@callback perform(scope :: term() | nil, args :: map()) ::
  :ok | {:ok, term()} | {:error, term()} | {:snooze, pos_integer()}
```

# `fetch_arg!`

```elixir
@spec fetch_arg!(map(), String.t()) :: term()
```

Fetches a required arg or raises `KeyError`. Call from inside `perform/1`
before reconstructing scope. Belt + suspenders beyond `new/3` validation
(D-20): hand-built jobs bypass `new/3` but still hit this at run time.

# `new`

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

Enqueue a job with fail-fast validation that required tenant keys are
present. Nil values are allowed (pre-auth / system jobs); absent keys
raise.

`audit_schema` is intentionally NOT in the required-keys list — it is a
worker-specific concern. Workers that emit audits add `"audit_schema"`
to their own arg list and validate it in their own `perform/1`.

---

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