Repository navigation
design admin scope
Decision (2026-09-30, user): all personal resources are visible and operable by their owner ONLY. Compared to a normal user, an admin gains exactly three things: system switch control (registration toggle), user management, and the ability to create/modify global resources. Admins are curators of the global library, not tenant overseers.
Issue: #36. The pre-existing global-create gate (403 for non-admins on
scope: 'global' create) was already correct; this change removed every
owner-or-admin READ/MUTATE bypass.
| Row | Read | Mutate |
|---|---|---|
personal (ownerId set) |
owner only — everyone else (admin included) gets 404 (existence-hiding) | owner only |
global (ownerId null) |
everyone |
admin only (canManage) |
Machines, credentials, MCP servers, profiles, resources, LLM providers carry the scope; machine-scoped surfaces (jobs, agents, sessions listing, inventory, workspace listing, runtime-config, config view) inherit their machine's ownership.
-
machines.ts—visible()owner-only;GET /api/machineslists own for every role; the module doc dropped "or an admin". -
jobs.ts/runtime-config.ts/inventory.ts/workspace.ts—visibleMachine/visibleowner-only; the now-deadMACHINE_OWNER_ONLY403 branches were REMOVED (a non-owner never gets past the 404). -
jobs/service.tscancel— owner-only. -
status.ts(posture) — every figure isselffor every role; thescopesmap stays on the wire but never saysall. The web readout strip dropped itsall/ownmarkers (dead branches) and the i18n keys went with them. -
mcp-servers.ts—/statusfilters to own-personal + global for every role;ownsOrAdmin→canManage(global → admin, personal → owner). -
credentials.ts,llm-providers.ts,resources.ts,profiles.ts— samecanManageshape; visibility helpers (visibleTo/serverVisible/visibleProfile/…) lost their|| role === 'admin'arm and the unusedroleparam. -
registry.ts,marketplace.ts,client-config.ts— profile/server visibility checks aligned (admin no longer resolves another user's personal profile/server, including via/mcp?profile=and machine-PAT bundles). -
plugins/realtime.ts— theadminssocket room is GONE:machine:status,job:update,inventory:updatedemit touser:<ownerId>only.
packages/server/test/admin-scope.test.ts (machine routes 404 for admin on a
foreign machine; foreign personal credential/mcp unmanageable by admin while
global rows remain admin turf; mcp status filtered) + updated assertions in
machines/jobs/runtime-config/config-view/status-filter/status-posture (the
old expectations — admin sees all, MACHINE_OWNER_ONLY 403, posture all —
were the codified OLD behavior and flipped).