Skip to content

design admin scope

sinrimin edited this page Sep 30, 2026 · 1 revision

Admin scope tightening — personal resources are owner-only (#36)

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.

The rule

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.

What changed where

  • machines.ts — visible() owner-only; GET /api/machines lists own for every role; the module doc dropped "or an admin".
  • jobs.ts / runtime-config.ts / inventory.ts / workspace.ts — visibleMachine / visible owner-only; the now-dead MACHINE_OWNER_ONLY 403 branches were REMOVED (a non-owner never gets past the 404).
  • jobs/service.ts cancel — owner-only.
  • status.ts (posture) — every figure is self for every role; the scopes map stays on the wire but never says all. The web readout strip dropped its all/own markers (dead branches) and the i18n keys went with them.
  • mcp-servers.ts — /status filters to own-personal + global for every role; ownsOrAdmin → canManage (global → admin, personal → owner).
  • credentials.ts, llm-providers.ts, resources.ts, profiles.ts — same canManage shape; visibility helpers (visibleTo/serverVisible/ visibleProfile/…) lost their || role === 'admin' arm and the unused role param.
  • 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 — the admins socket room is GONE: machine:status, job:update, inventory:updated emit to user:<ownerId> only.

Tests

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).

Clone this wiki locally