# Notifications reference

Every kind of Borago Board notification, what raises it, where a click lands, how read state syncs across devices, repeat folding and the bell.

A notification is a stored, synced row that says something needs a person. Nearly all of them are raised by the desktop app, because that is where the work runs. Reading one anywhere clears it everywhere. Clicking one opens the place where the fix is.

## What raises a notification

| Raiser | What it raises |
|---|---|
| The desktop app | Everything about runs, tasks, containers, credentials, updates and flows. The desktop is the machine executing the work, so it is the one that knows |
| A browser on the local network | Nothing of its own. It receives the desktop's notifications live, because it is served by the same backend |
| The cloud service | Two kinds exist for it, account notice and security alert. Neither needs a running task |
| The cloud browser and the phone | Nothing of their own. They read the synced rows and receive the same notice the desktop raised, once sync carries it |

There are 20 kinds. Four things are deliberately not notified. A task simply finishing, a question the person was already watching in an open task, an ordinary retry, and any move a person made themselves.

## Every kind

The kind decides the colour of the dot and the grouping. Where a click lands is decided per notice, and a notice that names a specific project tab always opens that tab.

| Kind | Meaning | Colour | A click opens |
|---|---|---|---|
| Auth failed | A run was refused by the provider because the project's stored credential was rejected. The project's queue pauses | Red | The project on its **AI Auth** tab |
| Task blocked | A run ended with the task blocked, the task used up all its retries, or the retry check judged that another run would fail the same way | Red | The task |
| Task question | The agent asked a question with nobody watching, so the task paused as blocked, or the person closed the task while a question was open | Amber | The task, where the question is answered |
| Task action required | A task finished with steps for the person to do, or the post-run review flagged the result | Blue, with an **Action needed** badge | The task |
| Container error | A container start failed, the repository could not be cloned into it, the container was not running when a task needed it, or the container itself is the problem | Red | The tab holding the fix when the notice names one. The task when it concerns one. Otherwise an offer to restart the container, behind the same confirm as the board's own restart |
| Firewall blocked | The host firewall is blocking the policy proxy the container uses to manage containers | Red | The project on its **Containers** tab |
| Git auth error | The project's stored git key exists but cannot be decrypted with any key this machine holds. The container's existing git setup is left untouched. Once per project until a decryption succeeds | Red | The project on its **Project Info** tab |
| Rate limited | The provider answered with a rate limit and the project's queue paused. A resume time is shown in the reader's own time zone, and only when the provider stated one | Amber | The project |
| Queue held | The queue starts nothing, because every waiting task interferes with blocked work or the project's cost budget is reached. Once per hold | Amber | The project |
| Task error | The run ended cleanly but recording its result failed | Red | The task |
| Update available | A newer desktop version was found and is downloading, or the install is one the person updates by hand | Blue | The download page when the notice carries a link, otherwise Settings, then Application |
| Update ready | A downloaded update is ready to apply | Green, with an **Action needed** badge | On the desktop, a restart that installs it, guarded while a task runs. Elsewhere, Settings, then Application |
| Container notice | A fact about how the container runs on this machine. It is built for another CPU architecture and runs emulated, or its Dockerfile looks like it needs the other architecture. Nothing is broken and the start proceeds | Blue | The project on its **Containers** tab |
| Secret removed | A change synced from another device removed a project credential. The previous value is held on this machine until restored or deleted, and the notice says for how long | Amber | The project on the tab holding that credential |
| Container rebuild needed | A run added tools to the project's Dockerfile, so the file is ahead of the running container. The tool works now and disappears at the next recreate | Blue, with an **Action needed** badge | An offer to restart the container, behind the recreate confirm |
| Flow failed | A flow run ended in error or blocked. A flow runs with nobody watching, so this notice is often its only surface. Blocked means the run could not take place, and is worded differently from a failure | Red | The project's flows page |
| Security alert | Kept for the cloud service to report a security event about the account | Red | Nowhere specific |
| Account notice | News about the account. The cloud service raises it for an announcement from the operator. The desktop raises it when its cloud session has ended, and when another desktop took the account's link | Blue | Settings, then Account |
| Credential storage weak | The key that seals every credential on this desktop is not itself sealed by a real keychain, so stored credentials are readable by anything that can read the person's files. Raised once per launch while it is true. Nothing is blocked | Amber | Settings, then Account, where the same warning sits beside the cloud sign-in |
| Container ready | The Docker client that container management installs in the background has landed in the running container. A success with nothing to do | Green | The project on its **Containers** tab |

## Storage and sync

| Property | Value |
|---|---|
| Where a notification lives | A row owned by the account, in the desktop's database and, with cloud sync on, on the cloud |
| Live delivery | An open board learns of a new notice at once over its live event stream. Sync is not waited for |
| Read state | Stored with the row and synced. Reading a notice on the desktop clears it on the phone, and the other way round |
| Every read path counts | A click on a panel row, the **Mark as read** control, **Mark all read**, and a click on a desktop notification all mark the notice read |
| Clearing | The removal reaches every device, and a cleared notice does not return on the next sync |
| How many are kept | 300. Beyond that the oldest are removed for good, on each peer |
| Signed out on the desktop | Notifications are still raised and kept locally. They belong to whichever account signs in next, like the rest of the unclaimed board |

## Repeat folding

A condition that persists, such as an overnight rate limit, would otherwise raise the same notice again on every check. So a repeat of a condition-shaped notice, while an unread notice of the same kind exists for the same project, updates that notice in place instead of adding a row. The wording refreshes to the latest, the first-seen time is kept, and nothing re-alerts.

| Rule | Detail |
|---|---|
| Kinds that fold | Rate limited, queue held, auth failed, git auth error, firewall blocked, container rebuild needed, container notice, and credential storage weak (which names no project and folds per account) |
| Kinds that never fold | Everything about one task. Two tasks asking for action are two different asks |
| The update pair | Update ready replaces an unread update available, and a newer version's update available replaces a stale update ready |
| Unread is the boundary | A repeat of a notice already read or cleared is news again and gets its own row |
| Nothing is lost | Every folded occurrence is kept on the row with its time and any superseded wording, up to 200 per row. The panel shows the count with the first and last, and **Show all** unfolds them |

## The bell and the panel

The bell sits in the top bar on every surface and shows the unread count. It opens a panel listing notices newest first, each with its colour dot, title, body and time.

| Control | Where | What it does |
|---|---|---|
| Click on a row | Each row | Marks it read and opens the place in the table above |
| **Mark all read** | Panel header | Marks every notice read, without going anywhere |
| **Clear** | Panel header | Removes every notice |
| **Mark as read** | On an unread row | Marks that one notice read without navigating. Absent on a read row, since there is no unread control to undo it |
| **Clear this notification** | On each row | Removes that one notice |
| **Copy this notification** | On each row | Copies the title, body and local time as plain text |
| **Create task** | On a row that has a project | Opens the create form with the notice's text as the description, and a mention of the related task when there is one |
| **Ask in chat** | On a row that has a project, when chat is available | Opens the project's chat with a reference to the notice and read access to the code |
| **Show all** | On a folded row | Unfolds every kept occurrence |

A notice can also be referenced from a task or a chat by its short id, which the mention picker offers.

## Desktop notifications

Settings, then Notifications, then **Desktop notifications**. Off by default. When on, every incoming notice also appears as a system notification, and clicking that focuses the window, marks the notice read, and opens the same place a panel click would.

| Property | Value |
|---|---|
| Scope | This window only. The desktop app and each browser on the local network decide for themselves, and the choice does not sync |
| Turning it on | Asks the browser or the operating system for permission. A refusal shows a hint and leaves the switch off |
| macOS | The app checks the system's own notification setting at start, on focus and when the switch goes on. While the app has the switch on and macOS blocks it, a dialog offers **Open macOS Settings** and **Turn off in app** |

## On the phone

A phone receives notifications while its board is open. A phone board that comes back to the foreground reloads its state, so nothing raised in the meantime is missed once it is open again.

Related: [Notifications](/docs/guides/notifications/), [The queue and its holds](/docs/reference/queue-and-holds/), [Messages](/docs/reference/messages/), [Cloud sync](/docs/reference/cloud-sync/), [When the agent asks a question or needs you](/docs/guides/questions-and-actions/).
