# Inbox.Notifications — the people the inbox names, told in their bell

> `Osysharp.WorkQueues.Notifications` joins `Osysharp.WorkQueues` to `Osysharp.Notifications`: the person an item is offered to, the cover it is handed to while its holder is away, the holder a promise's policy says to tell, and a queue's leads each find it in their bell, in the second person and their own language — with nothing written in the app. Who leads is whoever the app's `LeadsInbox` policy says.

<!-- id: workflow-inbox-notifications-kit · area: workflow · stability: preview · html: https://osysharp.com/reference/workflow/inbox-notifications-kit/ -->

## Summary        {#summary}
The Inbox says who should know on its own events — `ItemOffered.To`, `HolderChanged.Told` (a cover, while the holder
is away), `PromiseToldToHolder.Holder` — and Notifications tells anybody about anything. This package hears the first
and calls the second. It is a bridge ([Bridges — a package that arrives when an app uses the two it completes](https://osysharp.com/reference/project/bridges/)): an app that uses both writes nothing at all — `osy lock`
includes it and says so:

```console
+ Osysharp.WorkQueues.Notifications 0.2.0 included: completes Osysharp.WorkQueues + Osysharp.Notifications
```

Each is told in the second person, in their language, when they read it: "Offered to you — it is yours if you take it
within 15 minutes.", "Handed to you — Ines is away until Mon 8 Jun 06:00 UTC.", "First reply is at risk."

## Signature      {#signature}
```osy syntax
// arrives by itself with Osysharp.WorkQueues@1 and Osysharp.Notifications@1 — no `use` line

void InboxNotify(Principal person, Event e)            // tell one person what an inbox event says to them
void InboxNotifyAll(Principal[] people, Event e)   // …each of several, once each
```

## Description    {#description}

### Who is told, with nothing written   {#told}
| the inbox raises | who is told | what they read |
|---|---|---|
| `ItemOffered` | `To`, the person offered it | "Offered to you — it is yours if you take it within 15 minutes." |
| `HolderChanged` with a `Told` | the cover it was handed to | "Handed to you — Ines is away until Mon 8 Jun 06:00 UTC." |
| `PromiseToldToHolder` | `Holder` | "First reply is at risk." / "Resolution was missed." |
| `PickupOverdue` | the queue's leads | "Nobody has picked it up in Repairs — it has waited more than 30 minutes." |
| `PromiseToldToLeads` | the queue's leads | the promise, at risk or missed, in the same words as the holder's |

A change of holder that names nobody tells nobody: taking an item, or handing it to a colleague, is not news to the
one who did it. One unread notification per item and kind of event — a second "at risk" on one item moves the unread
one to the top instead of adding another.

### Who are the leads?   {#leads}
Whoever the app says — once, as the policy it already gives the inbox: `policy LeadsInbox => IsLead;`. A queue's leads
are its active members who satisfy that policy, asked of each of them ([Security.Authorize — does THIS person satisfy a policy](https://osysharp.com/reference/security/authorize/), the WorkQueues kit's
`InboxLeads(item)`); when none of them does — or the item waits in no queue — everybody who leads in any queue, so an
item in a queue nobody leads still reaches somebody. The app writes nothing for its leads; an app that wants a "tell the
leads" action of its own hands `InboxLeads(item)` to its notifier.

### Never about an item they may not read   {#may-read}
Every notification is about the item. Notifications delivers it, shows it and mails it only if the recipient may read
that item under their own rules — so an offer on a restricted item, to somebody who may not read it, leaves their bell
empty ([The Notifications kit — telling a person that something needs them](https://osysharp.com/reference/ui/notifications-kit/)).

## Examples       {#examples}

### A repair desk whose crew and leads are told   {#example-desk}
```osy title="the bridge — the app says who leads, and nothing about telling anybody" test app=workflow-inbox-notifications-kit
app Repairs {
  use Osysharp.Identity@0;
  use Osysharp.Organizations@0;
  use Osysharp.Organizations.ServicePlans@0;
  use Osysharp.Presence@0;
  use Osysharp.Observability;
  use Osysharp.Workflow;
  use Osysharp.ServiceHours;
  use Osysharp.Ui;
  use Osysharp.WorkQueues@1;
  use Osysharp.Mail@0;
  use Osysharp.EmailTemplates@0;
  use Osysharp.Notifications@1;   // …and Osysharp.WorkQueues.Notifications arrives by itself
  model "model/**/*.osy";
}

using Osysharp.Identity;
using Osysharp.WorkQueues;
using Osysharp.Notifications;
using Osysharp.WorkQueues.Notifications;

[Role] enum CrewRole { Authenticator, Crew, Lead }
policy IsCrew => RoleGrant.Any(g => g.Member == user && (g.Role == CrewRole.Crew || g.Role == CrewRole.Lead));
policy IsLead => RoleGrant.Any(g => g.Member == user && g.Role == CrewRole.Lead);
policy WorksInbox => IsCrew;
policy LeadsInbox => IsLead;
policy AdministersInbox => IsLead;
policy ManagesOrganizations => IsLead;
policy CollaboratesOnRecords => IsCrew;
policy ReceivesNotifications => IsCrew;
policy ManagesClock => IsLead;

/// A repair somebody reported.
[Title(Title)]
entity Repair : WorkItem {
  security { allow read, create, update when IsCrew; }
}

partial entity ServiceHours { security { allow read, create, update, delete when IsLead; } }
partial entity Notification { security { allow create when IsCrew; } }

app.Notifications = new NotificationsSetup { AppName = "Repairs" };
```

## See also       {#see-also}
- [The WorkQueues kit — queues, who holds what, and the service levels promised on any item](https://osysharp.com/reference/workflow/inbox-kit/) — the events the inbox raises, and who each names
- [The Notifications kit — telling a person that something needs them](https://osysharp.com/reference/ui/notifications-kit/) — the bell, the mail, and the read check every notification passes
- [Security.Authorize — does THIS person satisfy a policy](https://osysharp.com/reference/security/authorize/) — how the leads are found: the app's `LeadsInbox`, asked of each member
- [[On] — hear an event, after the commit that raised it](https://osysharp.com/reference/function/on/) — hearing an event, as this package does
