# `Concord.KV`
[🔗](https://github.com/gsmlg-dev/concord/blob/main/lib/concord/kv.ex#L1)

Public API for Concord's revisioned key-value store.

`Concord.KV` provides the canonical interface for reading and writing keys.
Every mutation produces a `%Concord.KV.Record{}` with MVCC metadata
(revision, version, content_type, etc.).

## Basic Usage

    # Simple get/put (backward-compatible)
    :ok = Concord.KV.put("key", "value")
    {:ok, "value"} = Concord.KV.get("key")

    # With full record metadata
    {:ok, %Concord.KV.Record{}} = Concord.KV.get("key", metadata: true)

    # With content type and metadata
    Concord.KV.put("notes/001", body, content_type: "text/markdown", metadata: %{author: "ci"})

## Range and Prefix Queries

    {:ok, records, %{has_more: false}} = Concord.KV.list(prefix: "/notes/", limit: 100)
    {:ok, records, cursor} = Concord.KV.list(range: {"a", "z"}, limit: 50, keys_only: true)

## Cluster Revision

    {:ok, 1843} = Concord.KV.revision()

# `create`

```elixir
@spec create(binary(), term(), keyword()) :: {:ok, map()} | {:error, term()}
```

Creates a key only if it does not already exist.

Implemented as a transaction wrapper.

# `delete`

```elixir
@spec delete(
  binary(),
  keyword()
) :: {:ok, map()} | :ok | {:error, term()}
```

Deletes a key.

Returns `{:ok, %{revision: integer, prev_kv: Record.t() | nil}}`.

# `delete_if`

```elixir
@spec delete_if(
  binary(),
  keyword()
) :: {:ok, map()} | {:error, term()}
```

Deletes a key only if its `mod_revision` matches the expected value.

Implemented as a transaction wrapper.

# `get`

```elixir
@spec get(
  binary(),
  keyword()
) :: {:ok, term()} | {:ok, Concord.KV.Record.t()} | {:error, term()}
```

Retrieves a value by key.

## Options

- `:metadata` — if `true`, returns `{:ok, %Record{}}` instead of `{:ok, value}`
- `:revision` — read the value as of a specific cluster revision (time-travel)
- `:consistency` — `:eventual`, `:leader` (default), or `:strong`
- `:timeout` — operation timeout in ms (default: 5000)

# `history`

```elixir
@spec history(
  binary(),
  keyword()
) :: {:ok, [Concord.KV.Record.t()]} | {:error, term()}
```

Returns the revision history of a single key.

## Options

- `:from_revision` — start of revision range (inclusive)
- `:to_revision` — end of revision range (inclusive)
- `:limit` — max records to return (default: 100)

# `list`

```elixir
@spec list(keyword()) :: {:ok, [Concord.KV.Record.t()], map()} | {:error, term()}
```

Lists keys matching a prefix or range selector.

## Options

- `:prefix` — prefix to match (mutually exclusive with `:range`)
- `:range` — `{start, end_exclusive}` tuple (mutually exclusive with `:prefix`)
- `:limit` — max results (default: 1000, max: 10000)
- `:keys_only` — omit values (default: false)
- `:revision` — snapshot read at a specific revision
- `:timeout` — operation timeout in ms (default: 5000)
- `:consistency` — read consistency level (default: :leader)

## Returns

`{:ok, [Record.t()], %{has_more: boolean, last_key: binary | nil}}`

# `put`

```elixir
@spec put(binary(), term(), keyword()) :: {:ok, map()} | :ok | {:error, term()}
```

Stores a key-value pair.

## Options

- `:ttl` — time-to-live in seconds
- `:lease` — attach to an existing lease ID
- `:content_type` — MIME-ish content type hint
- `:metadata` — application-level metadata map
- `:compress` — override automatic compression
- `:timeout` — operation timeout in ms (default: 5000)

## Returns

`{:ok, %{revision: integer, prev_kv: Record.t() | nil}}`

# `replace`

```elixir
@spec replace(binary(), term(), keyword()) :: {:ok, map()} | {:error, term()}
```

Replaces a key only if it already exists.

Implemented as a transaction wrapper.

# `revision`

```elixir
@spec revision(keyword()) :: {:ok, non_neg_integer()} | {:error, term()}
```

Returns the current cluster revision.

# `update_if`

```elixir
@spec update_if(binary(), term(), keyword()) :: {:ok, map()} | {:error, term()}
```

Updates a key only if its `mod_revision` matches the expected value.

Implemented as a transaction wrapper.

