# `Issho.Policy`
[🔗](https://github.com/hattoriai/issho/blob/v0.1.0/lib/issho/policy.ex#L1)

Your app's answer to "may this actor do this here?", and to "what is
this document?". Issho has no roles and no user model: it asks, and your
app answers with whatever it already uses.

    defmodule MyApp.Collaboration do
      @behaviour Issho.Policy

      @impl true
      def authorize(%Issho.Identity{} = who, "board:" <> id, action) do
        if MyApp.Boards.allowed?(who.claims["user_id"], id, action),
          do: :ok,
          else: {:error, :forbidden}
      end

      @impl true
      def document(_who, "board:" <> id) do
        board = MyApp.Boards.get!(id)
        {:ok, %{engine: Issho.Engine.Map, initial: board.content}}
      end
    end

## Actions

`authorize/3` gets the room (the topic, such as `"board:42"`) and one of:

  * `:join`: to enter the room, see its people and their places;
  * `:read`: to receive its documents and their changes, asked again
    for the changes others make, so that a person whose access you take
    away stops receiving them;
  * `:write`: to change its documents;
  * `:lock`: to hold an advisory lock on a place.

Issho asks on join and on every message in both directions, so keep it
fast: put what it needs in the identity's `claims` when you sign the
token (`Issho.Token.sign/4`), or cache.

## Documents

`document/2` says what a document is when it opens for the first time on
a node: its engine (`Issho.Engine`), its initial content from your
server (a browser never seeds a document), and the engine's options. A
room's documents are the room itself (`"board:42"`) and paths under it
(`"board:42/n7/body"`), so the nested documents of a canvas share the
room's people and authorization.

# `action`

```elixir
@type action() :: :join | :read | :write | :lock
```

# `document`

```elixir
@type document() :: %{
  :engine =&gt; module(),
  optional(:initial) =&gt; term(),
  optional(:opts) =&gt; keyword()
}
```

What a document is: its engine, its initial content (given to the
engine's `c:Issho.Engine.init/2` when the store has nothing), and the
engine's options.

# `authorize`

```elixir
@callback authorize(Issho.Identity.t(), room :: String.t(), action()) ::
  :ok | {:error, term()}
```

Whether the actor may do the action in the room.

# `document`
*optional* 

```elixir
@callback document(Issho.Identity.t() | nil, document_id :: String.t()) ::
  {:ok, document()} | {:error, term()}
```

What a document is, when it opens for the first time on a node.

---

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