# `SSL.Lifecycle`
[🔗](https://github.com/gsmlg-dev/http_fetch/blob/v1.0.0-rc.9/apps/ex_ssl/lib/ssl/lifecycle.ex#L1)

Provider lifecycle evidence and transferable cancellation authority.

Create a handle before connecting and pass `{handle, lease}` under
`ex_ssl: [lifecycle: ...]`. A successful cancel accepts retirement; only a
confirmed await receipt establishes local resource cleanup. Control deadlines
are finite absolute monotonic milliseconds. Handles contain no cancellation
authority and remain readable after the provider exits.

# `accept`

```elixir
@spec accept(
  SSL.Lifecycle.Transfer.t() | SSL.Lifecycle.Pair.Transfer.t(),
  {:abs_ms, integer()}
) ::
  term()
```

# `await`

```elixir
@spec await(
  SSL.Lifecycle.Handle.t() | SSL.Lifecycle.Pair.Handle.t(),
  {:abs_ms, integer()}
) :: term()
```

# `cancel`

```elixir
@spec cancel(
  SSL.Lifecycle.Lease.t() | SSL.Lifecycle.Pair.Lease.t(),
  {:abs_ms, integer()}
) ::
  :ok | {:error, term()}
```

# `connect_failure`

```elixir
@spec connect_failure(SSL.Lifecycle.Handle.t()) ::
  {:ok, %{phase: :connect}} | :unknown
```

Reads authenticated native connection failure evidence before establishment.

Only the original allocator's observed failure, committed with its original
resource ownership and deadline, establishes this phase. A generic setup error,
cancellation, timeout or missing publication returns `:unknown`. The evidence
survives provider exit and does not establish cleanup; use `await/2` separately.

# `layers`

```elixir
@spec layers({SSL.Lifecycle.Pair.Handle.t(), SSL.Lifecycle.Pair.Lease.t()}) ::
  {:ok, map()} | {:error, atom()}
```

Returns the fixed outer and inner scalar descriptors of one pair reservation.

# `new`

```elixir
@spec new(keyword()) ::
  {:ok, SSL.Lifecycle.Handle.t(), SSL.Lifecycle.Lease.t()} | {:error, atom()}
```

# `new_pair`

```elixir
@spec new_pair(keyword()) ::
  {:ok, SSL.Lifecycle.Pair.Handle.t(), SSL.Lifecycle.Pair.Lease.t()}
  | {:error, term()}
```

Reserves both independent lifecycle obligations before nested TLS performs I/O.

Use `layers/1` to give each scalar descriptor to its own TLS connection. Pair
status and await require both receipts; a layer receipt never proves outer TCP
cleanup. No extra data process or physical socket is allocated by the pair.

# `offer`

```elixir
@spec offer(
  SSL.Lifecycle.Lease.t() | SSL.Lifecycle.Pair.Lease.t(),
  %{controller: pid(), owner: pid()},
  {:abs_ms, integer()}
) :: term()
```

# `offer_controller`

```elixir
@spec offer_controller(SSL.Lifecycle.Lease.t(), pid(), {:abs_ms, integer()}) :: term()
```

Offers a new cancellation controller while preserving the provider's current socket owner.

# `setup_failure`

```elixir
@spec setup_failure(SSL.Lifecycle.Handle.t()) ::
  {:ok, %{phase: :tls_setup}} | :unknown
```

Reads authenticated fatal setup-phase evidence separately from resource cleanup.

A proven result means the original Connection accepted ServerHello and committed
a fatal setup failure within its original deadline. The fixed result survives
provider exit. Missing or uncommitted evidence returns `:unknown`; cancellation,
timeout, and a successful handshake alone do not establish this phase.
Use `await/2` separately to establish local resource cleanup.

# `status`

```elixir
@spec status(SSL.Lifecycle.Handle.t() | SSL.Lifecycle.Pair.Handle.t()) ::
  {:pending, map()} | {:terminal, map()} | {:unconfirmed, term()}
```

# `status`

```elixir
@spec status(
  SSL.Lifecycle.Handle.t() | SSL.Lifecycle.Pair.Handle.t(),
  {:abs_ms, integer()}
) :: term()
```

Observes exact live resource counts within one finite absolute deadline.

---

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