# `AWSAuth.EventStream`
[🔗](https://github.com/neilberkman/ex_aws_auth/blob/v1.4.1/lib/aws_auth/event_stream.ex#L1)

AWS Signature Version 4 signing for event stream messages.

Some AWS APIs accept a stream of events from the client over a single
connection (for example Amazon Transcribe streaming and Bedrock
bidirectional streaming). Each event is individually signed, and the
signatures form a chain: the first event is signed using the seed
signature from the initial HTTP request's `Authorization` header, and each
subsequent event is signed using the signature of the event before it.

The signature for an event is computed as:

    string_to_sign =
      "AWS4-HMAC-SHA256-PAYLOAD" <> "\n" <>
      <amz_date>                 <> "\n" <>   # YYYYMMDDTHHMMSSZ
      <credential_scope>         <> "\n" <>   # YYYYMMDD/region/service/aws4_request
      <prior_signature>          <> "\n" <>   # hex
      sha256_hex(<header_bytes>) <> "\n" <>
      sha256_hex(<payload>)

    signature = hmac_sha256(signing_key, string_to_sign)

## High-level usage

`sign_message/6` does the whole thing — encode the `:date` header, sign,
and frame a wire-ready event stream message. Chain the returned signature
into the next call:

    seed = "..." # signature from the initial request's Authorization header
    creds = AWSAuth.Credentials.from_env() |> Map.put(:region, "us-east-1")

    {frame1, sig1} =
      AWSAuth.EventStream.sign_message(creds, "transcribe", seed, payload1, time1)

    {frame2, sig2} =
      AWSAuth.EventStream.sign_message(creds, "transcribe", sig1, payload2, time2)

## Low-level usage

`sign_event/7` mirrors the canonical algorithm exactly (and matches the
`aws_signature` Erlang library's `sign_v4_event/7`) when you want to control
the encoded header bytes yourself.

# `encode_byte_array_header`

Encodes a byte-array header (value type 6) into the AWS event stream binary
format. The value is length-prefixed with a 16-bit big-endian length.

# `encode_message`

Frames serialized `headers` and a `payload` into a complete event stream
message, including the prelude, prelude CRC, and message CRC.

## Wire format

    [total length      :: big-32]
    [headers length    :: big-32]
    [prelude CRC32      :: big-32]   # crc32 of the 8 prelude bytes above
    [headers bytes]
    [payload bytes]
    [message CRC32      :: big-32]   # crc32 of everything before it

# `encode_string_header`

Encodes a string header (value type 7) into the AWS event stream binary
format. The value is length-prefixed with a 16-bit big-endian length.

Used for application message headers such as `:content-type`, `:event-type`,
and `:message-type` on the events some services expect (e.g. Bedrock
bidirectional streaming input chunks).

# `encode_timestamp_header`

Encodes a timestamp header (value type 8) into the AWS event stream binary
format. The value is the milliseconds since the Unix epoch.

`request_time` may be a `NaiveDateTime` (interpreted as UTC) or a `DateTime`.

# `sign_event`

Signs a single event and returns the chunk signature as a lowercase hex string.

This is the low-level entry point. `header_bytes` must be the event's headers
already serialized in the AWS event stream binary format (typically just the
`:date` header — see `encode_timestamp_header/2`), and `payload` is the raw
event payload.

Options:

  * `:region` - overrides the region from `credentials`
  * `:raw` - when `true`, returns the raw 32-byte signature instead of hex

## Example

    iex> creds = %AWSAuth.Credentials{
    ...>   access_key_id: "AKIDEXAMPLE",
    ...>   secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    ...>   region: "us-east-1"
    ...> }
    iex> header_bytes = <<5, 58, 100, 97, 116, 101, 8, 0, 0, 1, 137, 171, 187, 255, 224>>
    iex> AWSAuth.EventStream.sign_event(
    ...>   creds,
    ...>   "transcribe",
    ...>   "ce2704cf5f348fd66f179d5883162f223c30b3fb8213fb1bc097bf2ecd34b1b5",
    ...>   header_bytes,
    ...>   "",
    ...>   ~N[2023-07-31 11:36:12]
    ...> )
    "29ef82c39850abdcc65f9d6046f3e437e385112b80b7f17b31ba33a7da3cc8af"

# `sign_message`

Signs an event and frames it as a wire-ready event stream message.

Encodes the `:date` header from `request_time`, signs the message (using the
encoded `:date` header as the signed headers and `payload` as the body),
then builds the full event stream frame containing the `:date` and
`:chunk-signature` headers followed by `payload`.

Returns `{frame, signature_hex}`. Pass `signature_hex` as the
`prior_signature` for the next event in the stream.

Accepts the same options as `sign_event/7` (except `:raw`).

---

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