# `AttestoMCP.Anubis.JSONSafe`
[🔗](https://github.com/XukuLLC/attesto_mcp/blob/v1.0.5/lib/attesto_mcp/anubis/json_safe.ex#L1)

Produce a JSON-safe copy of an MCP session-state map before it is written to a
`jsonb` column.

Anubis folds the whole request `conn.assigns` into the persisted session
`frame`, so the state map an `Anubis.Server.Session.Store` is handed can carry
values with **no `JSON.Encoder` implementation** - a request-scoped struct
(e.g. a host's authenticated-user struct), a tuple, a pid, a ref, a function,
a `MapSet`. Encoding such a map raises in the database driver, which - because
it happens mid-`initialize` - would crash the session process and drop the
connection.

`sanitize/1` recursively drops anything non-encodable from its enclosing map
or list while preserving encodable siblings:

  * a struct **with** a `JSON.Encoder` impl (`DateTime`, `Date`, `Decimal`,
    ...) is kept; a bare struct without one is dropped;
  * a map keeps only entries whose key is a valid JSON object key (binary or
    atom) **and** whose value survives sanitization;
  * a list keeps only its surviving elements.

Keys are otherwise preserved as-is, so a string-keyed restore reads the same
values back after the `jsonb` round-trip. The result always encodes cleanly.

# `sanitize`

```elixir
@spec sanitize(term()) :: term()
```

Return a JSON-encodable copy of `value`, dropping any non-encodable members.

A top-level value that is itself non-encodable (and not a map or list to
descend into) sanitizes to an empty map, so the return is always encodable.

---

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