A global admin observes and steers system agent threads
Maintainer, 2026-10-04: "this is no entitlement ⇒ this is access to the bug fix thread", "make a standing rule for global admin for access", "i want to also contribute to thread and be able to steer … same as claude code".
The situation it resolves
The platform's own agents — the pull-request babysitter and fixer, triage, the bug-fix pool, rounds a
supervisor relaunches — run their conversations in system and package partitions (for example
Hosting/Triage/_Thread/…). No person holds a write grant there, and a platform admin is not a data
superuser, so an operator could at best READ such a thread through an entitlement and could never post
into it or stop its round. Viewer and Commenter carry neither Update (posting and stopping are writes
to the thread node) nor Thread (the permission the delivery gate demands for the cells a round
writes).
The rule
ThreadAccessRule (src/MeshWeaver.AI/ThreadAccessRule.cs) is registered for both Thread and
ThreadMessage. For everybody it decides exactly what SatelliteAccessRule decided before — a
conversation is a satellite of the node it is about. When that says no, and the caller is a global
admin (hub.IsGlobalAdmin(userId)), it adds:
| Node type | A global admin may | Never |
|---|---|---|
Thread |
Read; Create (a delegated sub-thread a steered round opens); Update (post a message, stop or redirect the round); Thread and Comment on the thread |
Delete |
ThreadMessage |
Read; Create; Update of a cell the admin wrote | Delete; Update of a cell somebody else wrote |
Scope is the type, not the starter. The widening covers every conversation outside a person's home partition — in practice the system and package partitions the platform's agents run in. No "started by a system identity" predicate is evaluated (maintainer, 2026-10-04: "keep it SIMPLE … Keep ONE exclusion only: threads inside another person's own home partition"); a shared space's ordinary conversations are therefore observable and steerable by a global admin too.
And for both: nothing in a person's home partition (a partition whose root is a User or
VUser, matched against UserNodeType.NodeType / VUserNodeType.NodeType — their private
conversations; the admin's own home included, where the fold already grants its owner everything). A
partition whose root cannot be read counts as private, so the rule fails closed. A cell's author is
read from the STORED cell, never from the submitted payload. The node the thread is about, and every other non-thread node, is untouched:
the rule governs these two types and nothing else, and GetEffectivePermissions answers for the admin
exactly what it answered before.
How the seams ask it
The rule is a core INodeTypeAccessRule for the CRUD operations and an INodeTypePermissionRule for
Thread / Comment (core MeshWeaver, Doc/Architecture/AccessControl → the rule table). All three
seams consult it through NodeTypeAccessRuleGate, only after the ordinary fold denied: the RLS
validator (queries, writes), the [RequiresPermission] delivery gate (submissions, stops, the round's
cell creates) and the stream-cache read gate (every node view). So the Threads app's groups, the
thread page and an MCP get agree.
Opening versus listing
The rule decides access to a thread reached BY ITS PATH: a link in the Threads app, a notification
or a triage item opens it. The Threads app's groups LIST threads with a partitions:all query, and
that fan-out spans the partitions the viewer can enumerate. A system partition the admin holds no
grant on is not enumerated, so its threads are not listed there, even though each one opens. On the
control instance the operator holds a Viewer entitlement on Hosting, so the babysitter, triage and
bug-fix groups list as well. ThreadGroupsAccessTest pins this listing boundary.
What steering means
A message the admin posts is the next user turn, and the round that answers it runs as the admin — exactly as it would for any other sender. The agent then acts with the admin's own grants, never with the identity that started the thread; anything the admin may not do, the steered agent may not do either.
Pinned by
MeshWeaver.AI.Test/GlobalAdminThreadAccessTest— on a mesh with row-level security and no public-admin grant, with a Store-gated package: the admin reads a system thread (refused before), posts into it and stops it (refused before); an outsider is refused all three; the admin is still refused the package's non-thread content, deleting the thread, rewriting a message somebody else wrote, and a thread in another person's home partition.MeshWeaver.AI.Test/StewardThreadSubmissionAccessTest— the steward's threads: a global admin is accepted, an outsider and a Viewer are refused.