# `Mutare.Phoenix.Token`
[🔗](https://github.com/foxbenjaminfox/mutare_phoenix/blob/v0.3.1/lib/mutare/phoenix/token.ex#L1)

`:token` — mutates the `Phoenix.Token` calls that generate and read signed or encrypted
tokens. Three kinds, each a variant label:

**`scheme`** swaps the call for its sibling scheme — `sign/3,4` ↔ `encrypt/3,4`,
`verify/3,4` ↔ `decrypt/3,4` — so a token generated at the mutated site can no longer be
read by the corresponding `verify` or `decrypt` call:

    Phoenix.Token.sign(endpoint, "user auth", user.id)     ->  Phoenix.Token.encrypt(...)
    Phoenix.Token.verify(endpoint, "user auth", token)     ->  Phoenix.Token.decrypt(...)

A survivor means no test ever verifies a token this site signed (or decrypts one it
encrypted, or passes a real token to this reader) — the email is asserted to contain a
link, say, and the link is never followed.

**`payload`** blanks the data a `sign`/`encrypt` call embeds, to `nil`:

    Phoenix.Token.sign(endpoint, "user auth", user.id)     ->  Phoenix.Token.sign(endpoint, "user auth", nil)

A survivor means the token still verifies but no test checks its payload — a
`{:ok, _} = verify(...)` that never compares the payload.

**`expiry`** disables the explicit `max_age:` of a `verify`/`decrypt` call:

    Phoenix.Token.verify(endpoint, salt, token, max_age: 86_400)  ->  max_age: :infinity

A survivor means no test checks that an expired token is rejected. Only an explicit
integer literal is mutated; a call relying on Phoenix's default (one day), or passing a
variable or `:infinity`, is left alone. The position is marked with the shared `:timeout` label
(`c:Mutare.Mutator.argument_marks/1`), so Mutare's built-in `:integer` family skips the
duration literal. The `expiry` mutation tests whether expiry is enforced; an off-by-one
change such as `86_400 → 86_401` would be difficult to detect reliably in a test.
The built-in `:atom` family also skips an explicit `:infinity` in this position.

Suppress one kind with `# mutare:ignore[token:expiry]`, or the whole family with
`# mutare:ignore[token]`. This family does not mutate the salt: Mutare's built-in
`:string` family mutates literal salts, and a salt stored in a module attribute is
compile-time data that Mutare never mutates.

Only the defined arities match — 3 and 4 for all four calls — so a name-matched call of any
other arity (reachable only by an explicit qualifier) is left alone, keeping every
metamutant compiling. A piped call (`endpoint |> Phoenix.Token.sign(salt, data)`) is the
same call with the context argument (an endpoint, conn, or socket) first. Matches direct
(`Phoenix.Token.sign(...)`), aliased, and bare-imported calls.

---

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