# `Tay.Storage.Record`
[🔗](https://github.com/AndriiSydorenko1904/tay/blob/v1.6.1/lib/tay/storage/record.ex#L1)

Pure Tay v1 physical framing and integrity codec.

The public contract is `docs/storage.md`: a 24-byte
header, 28-byte overhead, big-endian integers, CRC32C over header bytes 0..19
and over those bytes followed by the opaque payload, and a 16 MB hard limit.

Every type in 1..254 and schema in 1..255 is physically valid. Success does
not establish sequence continuity, semantic acceptance, or an applied event.
A physical cursor is not an applied replay checkpoint. Those checks belong
to later layers, not this codec.

Decoding examines one record at offset zero and returns the exact remainder
only on success. Every other result consumes nothing. Incomplete data is
only a parse classification, never permission or a recommendation to repair.
No payload interpretation, I/O, processes, or sequence allocation occurs.

# `corrupt_reason`

```elixir
@type corrupt_reason() ::
  domain_reason() | :invalid_magic | :header_checksum | :record_checksum
```

# `decode_result`

```elixir
@type decode_result() ::
  {:ok, t(), binary()}
  | {:incomplete, :header}
  | {:incomplete, :payload | :checksum, metadata()}
  | {:error, {:corrupt, corrupt_reason()}}
  | {:error, {:unsupported, unsupported_reason()}}
  | {:error, {:resource_limit, non_neg_integer(), non_neg_integer()}}
  | {:error, {:invalid_argument, :input}}
  | {:error, {:invalid_options, option_error()}}
```

# `domain_reason`

```elixir
@type domain_reason() ::
  {:invalid_format, 0}
  | {:reserved_type, 0 | 255}
  | {:invalid_schema, 0}
  | {:invalid_sequence, 0}
  | {:payload_length_exceeds_format, non_neg_integer(), 16_777_216}
```

# `encode_result`

```elixir
@type encode_result() ::
  {:ok, binary()}
  | {:error, {:invalid_argument, :record}}
  | {:error, {:invalid_record, domain_reason() | {:field, primitive_field()}}}
  | {:error, {:unsupported, unsupported_reason()}}
```

# `metadata`

```elixir
@type metadata() :: %{
  format_version: 1,
  record_type: 1..254,
  flags: 0,
  payload_schema_version: 1..255,
  sequence: 1..18_446_744_073_709_551_615,
  payload_length: 0..16_777_216,
  record_bytes: 28..16_777_244,
  available_bytes: non_neg_integer(),
  missing_bytes: pos_integer()
}
```

# `option_error`

```elixir
@type option_error() ::
  :not_keyword
  | :duplicate_keys
  | :unknown_keys
  | :invalid_max_decode_payload_bytes
```

# `primitive_field`

```elixir
@type primitive_field() ::
  :format_version
  | :record_type
  | :flags
  | :payload_schema_version
  | :sequence
  | :payload
```

# `t`

```elixir
@type t() :: %Tay.Storage.Record{
  flags: 0,
  format_version: 1,
  payload: binary(),
  payload_schema_version: 1..255,
  record_type: 1..254,
  sequence: 1..18_446_744_073_709_551_615
}
```

# `unsupported_reason`

```elixir
@type unsupported_reason() :: {:format, 2..255} | {:flags, 1..255}
```

# `decode`

```elixir
@spec decode(term(), term()) :: decode_result()
```

Decodes one physical record, leaving all trailing bytes unchanged.

The only option is `:max_decode_payload_bytes` (0..16_777_216, default
16_777_216). This is a resource budget, not an insertion or format limit.
A resource error permits retry with adequate resources at the same position.

# `encode`

```elixir
@spec encode(term()) :: encode_result()
```

Encodes a physical record; all primitive fields are checked before domain rules.

---

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