# `Attesto.NumericDate`
[🔗](https://github.com/XukuLLC/attesto/blob/v2.1.0/lib/attesto/numeric_date.ex#L1)

Value-level helpers for JWT NumericDate comparisons and Unix-second clocks.

This module deliberately does not choose protocol policy. Callers provide
requiredness, non-negative validation, leeway, future skew, and maximum age,
then map the result to their own error atom.

# `fetch_result`

```elixir
@type fetch_result() :: {:ok, integer()} | :missing | {:error, :missing | :invalid}
```

# `freshness_result`

```elixir
@type freshness_result() :: :ok | :future | :stale | :invalid
```

# `bounded_lifetime`

```elixir
@spec bounded_lifetime(keyword(), atom(), pos_integer()) :: pos_integer()
```

Resolve a positive lifetime option that may only shorten `default`.

A missing, non-positive, non-integer, or longer requested lifetime falls
back to the supplied default.

# `fetch`

```elixir
@spec fetch(map(), term(), keyword()) :: fetch_result()
```

Fetch a NumericDate claim from `claims`.

Missing optional claims return `:missing`; missing required claims return
`{:error, :missing}`. A present value that is not an integer, or is negative
when `non_negative: true`, returns `{:error, :invalid}`.

# `fresh?`

```elixir
@spec fresh?(term(), term(), keyword()) :: freshness_result()
```

Classify an issued-at value against a future-skew and maximum-age window.

Boundary values are accepted: `iat == now + future_skew` and
`iat == now - max_age` both return `:ok`.

# `non_negative_now!`

```elixir
@spec non_negative_now!(keyword(), keyword()) :: non_neg_integer()
```

Resolve a Unix-second clock and reject negative values.

Stateful grant transitions use this boundary so a malformed clock cannot
produce a record with an invalid expiry or reach a mutating store callback.

# `not_before_reached?`

```elixir
@spec not_before_reached?(term(), term(), keyword()) :: boolean()
```

Return whether a not-before NumericDate has been reached.

# `not_expired?`

```elixir
@spec not_expired?(term(), term(), keyword()) :: boolean()
```

Return whether an expiry remains strictly beyond `now - leeway`.

# `now`

```elixir
@spec now(keyword(), keyword()) :: integer()
```

Resolve a Unix-second clock from options.

`default: :datetime | :system` preserves the caller's original live-clock
source. `invalid_override: :raise | :fallback` preserves whether an invalid
`:now` override raised or silently used that live clock.

# `valid?`

```elixir
@spec valid?(
  term(),
  keyword()
) :: boolean()
```

Return whether `value` is an integer NumericDate for the selected policy.

# `within_lifetime?`

```elixir
@spec within_lifetime?(term(), term(), term()) :: boolean()
```

Return whether `finish` is no more than `max_seconds` after `start`.

---

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