# `Parrhesia.API.Identity`

Server-auth identity management.

Parrhesia uses server identities for flows that need the relay to sign events or
prove control of a pubkey. The default role is `:relay`, preserving the normal
public relay identity for callers that do not specify a role.

Identity resolution follows this order:

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

Supported options across this module:

- `:role` - identity role, defaulting to `:relay`
- `: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(),
  role: atom(),
  source: :configured | :persisted | :generated | :imported
}
```

Public identity metadata returned to callers.

# `default_path`

Returns the default filesystem path for the persisted server identity.

# `default_path`

Returns the default filesystem path for a persisted role 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"`.

# `sign_events`

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

Signs multiple events with the current server identity.

This is equivalent to calling `sign_event/2` for each event, but resolves the configured
identity once for the whole batch.

---

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