Brain Monitor

Phase 11 7 entity types Soft-delete + 30-day retention Migration 0017 + 0018

What the Brain Monitor does

The Brain Monitor is a single-page view of everything currently entering your team's brain — memories, conversations, messages, tasks, contacts, Granola transcripts. Instead of seven separate admin pages, the monitor streams all seven entity types into a unified, filterable, paginated feed scoped to one team at a time.

It is the operator console for the memory layer. You open it to see what your team is producing right now, to flip an item's truth_level from WORKING to VALIDATED after a peer review, to delete a piece of noise (soft delete — recoverable for 30 days), or to drill in as a superadmin and inspect another team's brain cross-team.

Universal truth-level contract

From Phase 11 on, every entity table written by xbrain (not just memory_items) carries the three Brain Monitor columns: truth_level, deleted_at, deleted_by. Adding a new entity table after Phase 11 requires these columns by default.

How to access

The Brain Monitor lives on app-site at the team-scoped URL:

urlhttps://app.grooveos.app/account/teams/brain/?team=<team-slug>

You must be signed in (GitHub OAuth via Phase 10) and you must be a member of the team. The page reads your xbt_ token from localStorage; the API enforces X-Team-Scope server-side, so you cannot bypass team isolation by editing the URL.

Truth levels — the 5-level epistemic ladder

Every Brain Monitor row carries a truth_level badge. The five levels form a one-way progression: you can promote a fact forward (e.g. WORKING → VALIDATED), but you cannot demote it without an explicit workflow.

EPHEMERAL Level 0 — Raw output

Raw chat output, web clips, draft notes. Unverified. The default level for anything that enters xbrain without explicit classification.

WORKING Level 1 — In-progress knowledge

In-progress knowledge actively used but not yet validated. Most team knowledge lives here.

VALIDATED Level 2 — Peer-reviewed

Peer-reviewed: at least one team member has explicitly approved this fact.

CANONICAL Level 3 — Team truth

The definitive answer your team has agreed on. CANONICAL facts are injected automatically in agent runs via system prompts.

PUBLIC Level 4 — Published externally

Shareable outside the team. Requires explicit promotion from CANONICAL.

Editing a row inline

Each Brain Monitor row exposes a truth_level dropdown on the right. Click it, pick a new level, the change is sent immediately as a PATCH against the underlying entity:

bashPATCH /v1/brain/events/<entity_type>/<entity_id>
Authorization: Bearer xbt_...
X-Team-Scope: <slug>
Content-Type: application/json

{"truth_level": "VALIDATED"}

On success the row re-renders with the new badge. On 403 (you tried to edit something you didn't author, see Permissions below) a toast surfaces:

toastYou can only edit items you created. Contact a team admin to modify
items created by others.

Deleting and restoring — 30-day window

Every row has a Delete button. Confirming it issues a DELETE /v1/brain/events/<entity_type>/<entity_id>:

Within the next 30 days the row is recoverable. In the Brain Monitor, flip the Show deleted toggle — deleted rows appear faded with a Restore button. Clicking it:

bashPOST /v1/brain/events/<entity_type>/<entity_id>/restore
Authorization: Bearer xbt_...
X-Team-Scope: <slug>

Returns 200 and deleted_at is set back to NULL. The row is fully visible again.

After 30 days — brain-janitor purges hard

A daily cron (xbrain-brain-janitor container) runs at 03:00 UTC. Rows with deleted_at < NOW() - INTERVAL '30 days' are hard-deleted from Postgres, Qdrant, and Neo4j in that order. After that point the row is unrecoverable.

The 7 entity types covered

entity_type Underlying table Vector-backed Has created_by
memory_item memory_items Yes (Qdrant) No (admin-only edit)
granola_note memory_items (filtered on source='granola') Yes (Qdrant) No (admin-only edit)
conversation conversations No Yes
message messages No No (admin-only edit)
team_message team_messages No Yes
task tasks No Yes
contact contacts No No (admin-only edit)

Permissions

Role View team brain Edit own items Edit any item Delete + restore
Member Yes Yes No (403) Own items only
Team admin (team_members.role='admin') Yes Yes Yes Yes
Superadmin (sub in ADMIN_USER_SUBS) Every team (drill-down, audited) n/a (v1 read-only) No (v1 read-only) No (v1 read-only)

Why admin-only for some types

memory_items, contacts, and messages have no created_by column in the current schema (legacy from Phase 2 / Phase 7). The author check therefore cannot run, so a member cannot edit these — only a team admin can. A future migration can add created_by to lift this restriction.

Live updates — 30-second polling

The Brain Monitor uses a 30-second polling cycle (not WebSockets, not SSE — locked v1 choice). Every cycle, the page calls GET /v1/brain/events?since=<last-seen-iso> and prepends any new rows to the top of the table.

Superadmin dashboard — cross-team visibility

A second page at /account/admin/ grants superadmins a cross-team view of every team's brain. Superadmins are defined server-side by the ADMIN_USER_SUBS env var (a comma-separated list of user subs — e.g. google:115...,github:mrboups). Anyone whose sub is in that list can open the dashboard.

Who is a superadmin?

Adding a new superadmin is a deliberate operator action with privacy implications. The workflow is:

  1. Edit infrastructure/.env on the VM: append a sub to ADMIN_USER_SUBS.
  2. docker compose restart memory-api — the gate (_is_admin()) re-reads the env at startup.
  3. The new principal can now open /account/admin/. There is no UI flow to add a superadmin — this is intentional (no privilege escalation path from inside the app).

The 4 sections

Section What it shows Endpoint
Brain Overview Per-team matrix — counts × entity_type × truth_level. Hover a cell for the per-level breakdown. GET /v1/admin/brain/overview
Storage Per-team Postgres rows + Qdrant points + MinIO bytes (human-formatted). Cells showing N/A mean Qdrant or MinIO was unreachable during this fetch — the page fails soft. GET /v1/admin/brain/storage
Activity 30-day events/day sparklines per team. Inline SVG — no chart library. GET /v1/admin/brain/activity
Top Sources Top-5 source labels per team plus an "other" bucket (LibreChat, OWUI, Granola, agent-runtime, API, etc. — discovered dynamically). GET /v1/admin/brain/sources

Drill-down with audit

Clicking Drill down → on any team row in Brain Overview navigates to:

urlhttps://app.grooveos.app/account/teams/brain/?team=<slug>&as_superadmin=1

The page renders a yellow banner:

Viewing as superadmin — this access is logged.

The Brain Monitor table loads exactly as it would for a team member, except:

No break-glass / opt-in in v1

A superadmin gets full content visibility on drill-down. Team admins are not pre-notified. The audit row is the trace, not the consent. A break-glass / opt-in approval workflow is deferred to a later phase.

Lockdown

Set ADMIN_USER_SUBS="" (empty) on the VM and restart memory-api — all five /v1/admin/brain/* endpoints return 403 for every caller, including a principal that was previously a superadmin. This is the kill-switch for the cross-team scope.

Deeper reading