# `MishkaCmsCore.Runtime.CspNonce`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/csp_nonce.ex#L5)

The Content-Security-Policy nonce, carried from the plug into a LiveView and into every template
it renders.

## Why a LiveView needs it at all

The root layout can read `conn.assigns` and so marks its inline `<script>` without help. A
LiveView's OWN template cannot: it renders from its socket, which never saw the conn. Several
templates here emit a `<style>` element — the editor's canvas draws its chrome, its icons and the
site's theme that way — and every one of them is refused by `style-src-elem` without a nonce.

## One nonce per response, signed into the LiveView session

`MishkaCmsWeb.Runtime.Plugs.SecurityHeaders` mints a fresh nonce for every response, as the CSP
specification asks: a nonce is only worth something while it cannot be guessed, and one that
outlives its response is one an attacker has longer to learn.

A LiveView keeps rendering over its socket long after that response, and everything it renders
must carry the nonce THAT document's header named. The socket's own session is the cookie at the
moment it connects, so a nonce kept there would follow whichever tab loaded last. Instead,
`session/1` is a `live_session` `:session` function: Phoenix signs what it returns into the page
(`data-phx-session`), the connected mount reads it back from that token, and a live navigation
inside the session carries the same token — so every render of one document agrees with its own
header, and two tabs never share a nonce.

    live_session :public, session: {MishkaCmsCore.Runtime.CspNonce, :session, []} do

## Using it in a template

`@csp_nonce` in a LiveView's own template, and `csp_nonce()` anywhere a runtime template is
compiled — a page, a layout, a component — because a component sees only the attrs it is handed:

    <style nonce={csp_nonce()}>…</style>

A `<style>` is the last resort. A class, the element's CSS box in the editor or a stylesheet row
is cached, shared between pages and needs no nonce at all.

`on_mount/4` records the value for the process, and the plug does the same for a response that
renders no LiveView, so `current/0` is one process-dictionary read on every call.

# `current`

```elixir
@spec current() :: String.t() | nil
```

The nonce of the response this process is rendering, or `nil` outside one.

Set by the plug for the request process and by `on_mount/4` for a LiveView process.

# `process_key`

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

The process dictionary key `put/1` writes, which
`MishkaCmsCore.Runtime.LiveViewHelpers.carry_into_tasks/0` registers so a task a template starts
renders with the same nonce.

# `put`

```elixir
@spec put(String.t() | nil) :: :ok
```

Records `nonce` as the one this process renders with. `nil` clears it.

# `session`

```elixir
@spec session(Plug.Conn.t()) :: %{optional(String.t()) =&gt; String.t()}
```

What a `live_session` signs into the page for its LiveViews: this response's nonce.

`%{}` when the plug did not run, so the session carries nothing rather than a `nil` the mount
would have to tell apart from a real value.

# `session_key`

```elixir
@spec session_key() :: String.t()
```

The session key `session/1` writes and `on_mount/4` reads.

---

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