# `AttestoPhoenix.DevTLS`
[🔗](https://github.com/XukuLLC/attesto_phoenix/blob/v2.1.0/lib/attesto_phoenix/dev_tls.ex#L1)

A one-line, dev-only helper that wires a locally-trusted TLS certificate into a
Phoenix endpoint's `https:` listener.

attesto requires an **https** issuer (RFC 8414 §2: the issuer identifier MUST be
an `https` URL) — the discovery documents, DPoP `htu`, and RFC 9728 resource
identifiers are all https by spec, and attesto enforces that at config-build
time. So a plain `http://localhost` dev server can't drive the OAuth / MCP flow.

Rather than adding an https-disable switch (there is deliberately none in a
security library), this helper makes the RIGHT path frictionless: serve a
certificate from a local certificate authority — [mkcert](https://github.com/FiloSottile/mkcert) —
so `https://localhost` is trusted with no tunnel and no downgrade.

Generate the certificate once with `mix attesto_phoenix.gen.dev_https`, then in
`config/dev.exs`:

    config :my_app, MyAppWeb.Endpoint, https: AttestoPhoenix.DevTLS.https_opts(port: 4443)

The MCP / OAuth issuer then becomes `https://localhost:4443`, so discovery,
DPoP, and the RFC 8707 resource identifiers all line up automatically.

## This is a dev-only convenience

It does **not** weaken any https requirement and it is not for production. In
production, TLS is terminated at the load balancer / ingress with a real CA
certificate, and the endpoint's `https:` listener (if any) uses that
certificate — never an mkcert one. `mix mkcert -install` trusts a CA on the
local machine only; never run it on a server or in CI.

This helper only wires a locally-trusted certificate into the dev endpoint. It
never touches the issuer/audience validation, and attesto's https-only
guarantee stays fully intact.

# `https_opts`

```elixir
@spec https_opts(keyword()) :: keyword()
```

Returns the Phoenix endpoint `https:` keyword list for a locally-trusted
mkcert certificate.

## Options

  * `:port` - the TLS port to listen on. Defaults to `4443`.
  * `:certfile` - path to the certificate. Defaults to the conventional
    `priv/cert/localhost.pem` resolved against the caller's app (see below).
  * `:keyfile` - path to the private key. Defaults to the conventional
    `priv/cert/localhost-key.pem` resolved against the caller's app.
  * `:otp_app` - when given, the default cert/key paths resolve via
    `Application.app_dir/2` (release-safe). When omitted, they resolve relative
    to `File.cwd!/0` — the app root when running `mix phx.server`, which is the
    idiomatic Phoenix-dev spelling (`phx.gen.cert` emits the same bare relative
    paths).
  * `:max_header_length` - the Bandit `http_1_options` max header length.
    Defaults to `65536`.

Returns:

    [
      port: 4443,
      cipher_suite: :strong,
      certfile: "…/priv/cert/localhost.pem",
      keyfile: "…/priv/cert/localhost-key.pem",
      http_1_options: [max_header_length: 65_536]
    ]

Raises `ArgumentError` if the certificate or key is missing, pointing you at
`mix attesto_phoenix.gen.dev_https`. It NEVER silently falls back to http.

## Examples

    # config/dev.exs
    config :my_app, MyAppWeb.Endpoint,
      https: AttestoPhoenix.DevTLS.https_opts(port: 4443)

    # release-safe path resolution
    config :my_app, MyAppWeb.Endpoint,
      https: AttestoPhoenix.DevTLS.https_opts(port: 4443, otp_app: :my_app)

---

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