# `XMAVLink.Signing`
[🔗](https://github.com/fancydrones/xmavlink/blob/main/lib/mavlink/signing.ex#L1)

Stateful MAVLink 2 signing policy helpers.

This module validates parsed signed frames against a shared key, tracks
inbound replay state by `{source_system, source_component, link_id}`, and
signs unsigned outbound MAVLink 2 frames with a per-connection timestamp.
Optional timestamp load/save callbacks let applications preserve the local
signing timestamp across restarts.

# `new_error`

```elixir
@type new_error() ::
  :invalid_accept_unsigned
  | :invalid_options
  | :invalid_link_id
  | :invalid_secret_key
  | :invalid_timestamp
  | :invalid_timestamp_load
  | :invalid_timestamp_save
  | :missing_link_id
  | :missing_secret_key
  | :timestamp_load_failed
```

# `sign_error`

```elixir
@type sign_error() ::
  :already_signed
  | :checksum_invalid
  | :invalid_crc_extra
  | :invalid_link_id
  | :invalid_mavlink_2_frame
  | :invalid_secret_key
  | :invalid_timestamp
  | :mavlink_1_not_signable
  | :missing_crc_extra
  | :missing_mavlink_2_raw
  | :timestamp_save_failed
  | :timestamp_exhausted
  | :unsupported_incompatible_flags
```

# `stream_key`

```elixir
@type stream_key() :: {0..255, 0..255, 0..255}
```

# `t`

```elixir
@type t() :: %XMAVLink.Signing{
  accept_unsigned: boolean(),
  link_id: 0..255,
  secret_key: &lt;&lt;_::256&gt;&gt;,
  stream_timestamps: %{required(stream_key()) =&gt; timestamp()},
  timestamp: timestamp(),
  timestamp_load: timestamp_load() | nil,
  timestamp_save: timestamp_save() | nil
}
```

# `timestamp`

```elixir
@type timestamp() :: 0..281_474_976_710_655
```

# `timestamp_load`

```elixir
@type timestamp_load() :: (-&gt; timestamp_load_result()) | {module(), atom(), [term()]}
```

# `timestamp_load_result`

```elixir
@type timestamp_load_result() ::
  timestamp() | {:ok, timestamp() | nil} | nil | :error | {:error, term()}
```

# `timestamp_save`

```elixir
@type timestamp_save() ::
  (timestamp() -&gt; timestamp_save_result()) | {module(), atom(), [term()]}
```

# `timestamp_save_result`

```elixir
@type timestamp_save_result() :: :ok | {:ok, term()} | :error | {:error, term()}
```

# `validate_error`

```elixir
@type validate_error() ::
  :invalid_mavlink_2_frame
  | :invalid_secret_key
  | :signature_invalid
  | :signature_replay
  | :signature_too_old
  | :signed_frame_unsupported
  | :timestamp_save_failed
  | :unsigned_frame
  | :unsigned_frame_rejected
```

# `new`

```elixir
@spec new(nil | keyword()) :: {:ok, t() | nil} | {:error, new_error()}
```

# `now_timestamp`

```elixir
@spec now_timestamp() :: timestamp()
```

# `sign_outbound`

```elixir
@spec sign_outbound(XMAVLink.Frame.t(), t() | nil) ::
  {:ok, XMAVLink.Frame.t(), t() | nil} | {:error, sign_error(), t() | nil}
```

# `validate_inbound`

```elixir
@spec validate_inbound(XMAVLink.Frame.t(), t() | nil) ::
  {:ok, XMAVLink.Frame.t(), t() | nil} | {:error, validate_error(), t() | nil}
```

---

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