# `Parrhesia.API.Identity`

Server-auth identity management.

Parrhesia uses a single server identity for flows that need the relay to sign events or
prove control of a pubkey.

Identity resolution follows this order:

1. `opts[:private_key]` or `opts[:configured_private_key]`
2. `Application.get_env(:parrhesia, :identity)`
3. the persisted file on disk

Supported options across this module:

- `:path` - overrides the identity file path
- `:private_key` / `:configured_private_key` - uses an explicit hex secret key
- `:auto_generate?` - allows generating and persisting a fresh identity when none exists

A configured private key is treated as read-only input and therefore cannot be rotated.

# `identity_metadata`

```elixir
@type identity_metadata() :: %{
  pubkey: String.t(),
  source: :configured | :persisted | :generated | :imported
}
```

Public identity metadata returned to callers.

# `default_path`

Returns the default filesystem path for the persisted server identity.

# `ensure`

```elixir
@spec ensure(keyword()) :: {:ok, identity_metadata()} | {:error, term()}
```

Returns the current identity, generating and persisting one when necessary only when
auto-generation is enabled.

# `get`

```elixir
@spec get(keyword()) :: {:ok, identity_metadata()} | {:error, term()}
```

Returns the current server identity metadata.

This does not generate a new identity. If no configured or persisted identity exists, it
returns `{:error, :identity_not_found}`.

# `import`

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

Imports an explicit secret key and persists it as the server identity.

The input map must contain `:secret_key` or `"secret_key"` as a 64-character lowercase or
uppercase hex string.

# `rotate`

```elixir
@spec rotate(keyword()) :: {:ok, identity_metadata()} | {:error, term()}
```

Generates and persists a fresh server identity.

Rotation is rejected with `{:error, :configured_identity_cannot_rotate}` when the active
identity comes from configuration rather than the persisted file.

# `sign_event`

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

Signs an event with the current server identity.

The incoming event must already include the fields required to compute a Nostr id:

- `"created_at"`
- `"kind"`
- `"tags"`
- `"content"`

On success the returned event includes `"pubkey"`, `"id"`, and `"sig"`.

---

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