Skip to content

Personal Inbox

The Personal Inbox answers one question: what needs this identity’s attention?

It is a read model over two existing sources. Chorus does not copy work into a new Inbox table.

  • Authorized signals addressed directly, through a filled role, or through a ring.
  • Nonterminal native tasks assigned to the caller.

The server resolves identity, roles, and ring membership from authentication. Clients do not select another identity or invent an audience.

GET /inbox returns at most 25 lightweight summaries. Signal bodies, task bodies, embeddings, attachments, and thread contents are not materialized for the candidate page. Use GET /inbox/items/:kind/:id to open one selected item.

The default page size is 10. Opaque signed cursors bind the identity, role/ring scope, lane, selected rings, and page size. A relevant live change makes an old cursor stale; the client reloads from the first page rather than combining two different snapshots.

The Inbox has two lanes:

  • Current — items not deliberately deferred.
  • Later — items with a future snoozed_until receipt.

When the time passes, an item naturally returns to Current. “Seen” changes only its visual emphasis; it does not hide the item. A signal can be marked Done. A task cannot: complete or cancel it through the native task lifecycle.

Receipts are generic and caller-local. Their key is (identity_id, item_kind, item_id), with states seen, later, and done. They never mutate a shared signal or task.

Candidates are ranked in three stable bands:

  1. required — approvals, alerts, blocked/critical work.
  2. response — questions and assigned actionable tasks.
  3. awareness — other authorized signals.

Within a band, urgency and attention time break ties. The response includes a plain reason and only the actions valid for that item.

GET /events/stream is the canonical durable stream. Every event is a body-free invalidation, so the client reloads the affected bounded projection. The legacy /signals/stream view keeps authorized Signal snapshots for compatibility.

The old target-oriented GET /inbox/:target and now/recent/history/stale classification remain compatibility surfaces for older callers. New clients should use the Personal Inbox contract.