# `Stevedore.Store`
[🔗](https://github.com/oshlabs/stevedore/blob/v0.2.0/lib/stevedore/store.ex#L1)

The content-addressed blob storage seam.

On-disk transports (OCI layouts, the registry server, the static tree) all read and write
blobs by digest; `Store` is the single interface they go through, so storage backends are
interchangeable. Blobs are immutable and addressed by their `Stevedore.Digest` — there is no
rename or mutate, only put/get/delete/exists.

The `config` term threaded through every callback is the backend's own handle (a root path,
an agent pid, …); each implementation defines its shape.

Implementations: `Stevedore.Store.Local` (filesystem) and `Stevedore.Store.Memory` (in-process,
for tests).

# `config`

```elixir
@type config() :: term()
```

Backend-specific handle (e.g. `{root: path}` for Local, a pid for Memory).

# `delete`

```elixir
@callback delete(config(), Stevedore.Digest.t()) :: :ok | {:error, term()}
```

Deletes the blob for `digest`. Deleting an absent blob is `:ok` (idempotent).

# `exists?`

```elixir
@callback exists?(config(), Stevedore.Digest.t()) :: boolean()
```

Whether a blob exists for `digest`.

# `get`

```elixir
@callback get(config(), Stevedore.Digest.t()) :: {:ok, binary()} | {:error, :not_found}
```

Fetches the blob for `digest`.

# `list`

```elixir
@callback list(config(), opts :: keyword()) :: {:ok, [Stevedore.Digest.t()]}
```

Lists the digests currently held.

# `local_path`

```elixir
@callback local_path(config(), Stevedore.Digest.t()) :: {:ok, Path.t()} | :unsupported
```

Returns a filesystem path to the blob for zero-copy serving (`send_file`), or `:unsupported`
for backends without a stable on-disk path.

# `put`

```elixir
@callback put(config(), Stevedore.Digest.t(), iodata()) :: :ok | {:error, term()}
```

Stores `data` under `digest`. Implementations must verify the bytes match the digest.

---

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