diff --git a/AGENTS.md b/AGENTS.md index e7ed193..570a778 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,10 +35,28 @@ Rules: - Status pills and tinted panels: `var(--color-{info,success,warning,danger,primary}-50)` background with the matching `-700` text. These flip per theme; the pale `#eff6ff`/`#fef3c7`/`#fee2e2` hexes do not. - Solid saturated fills (a colored button background, a status dot, an icon) may stay as a saturated color; those read on both themes. Do not convert those to the `-50` tints. - Inputs/selects must set both `background` and `color` (a missing `color` shows black text on a dark surface). Prefer `BaseInput`/`BaseSelect`, which handle this. +- Native form controls are not accepted when a base primitive supports the same control. Theme correctness belongs to the primitive, not each page. +- Every changed form must be exercised with `data-theme="light"` and `data-theme="dark"`. Check entered text, placeholders, disabled controls, browser autofill, dropdown options, focus rings, and modal surfaces. + +## Authorization: permission and resource scope are separate + +A module permission answers what kind of operation an actor may perform. A resource grant answers where they may perform it. Features that operate on deployments, buckets, peers, or another owned resource must enforce both. + +Rules: + +- Define dedicated read and write permissions for each module. Do not reuse an unrelated permission because the feature shares a page or transport. +- Enforce permissions and resource scope in the agent API. Router guards and hidden buttons improve the experience but are not security boundaries. +- Filter collection responses to resources the actor may read. Validate every resource referenced by create, update, delete, bulk, and action requests. +- A bulk update must preserve records outside the actor's scope. Never let a scoped request replace a global collection. +- Host-wide, fleet-wide, and all-resource operations require an explicit global permission. An empty resource identifier must not silently mean global access. +- API keys may narrow their user's grants. Use the intersection of user and key access. +- The UI must hide mutation controls without write permission and exclude read-only resources from target selectors. +- Tests must call the HTTP endpoint with two actors whose resource grants differ. Prove that each actor sees only allowed records and cannot change the other actor's records. ## Review checklist (UI changes) - [ ] New inputs/selects/buttons/cards reuse `src/components/base/` rather than bespoke markup. Flag any hand-rolled control that duplicates a primitive. - [ ] No hardcoded hex/`white`/`black` in ` diff --git a/src/components/StorageBackupsSettings.vue b/src/components/StorageBackupsSettings.vue index 8751598..74c8e19 100644 --- a/src/components/StorageBackupsSettings.vue +++ b/src/components/StorageBackupsSettings.vue @@ -177,8 +177,8 @@ import { useNotificationsStore } from "@/stores/notifications"; const auth = useAuthStore(); const notifications = useNotificationsStore(); -const canWriteCreds = auth.hasPermission("backups:write"); -const canDeleteCreds = auth.hasPermission("backups:delete"); +const canWriteCreds = auth.hasPermission("storage:write"); +const canDeleteCreds = auth.hasPermission("storage:delete"); const canWriteDests = auth.hasPermission("config:write"); const creds = ref([]); diff --git a/src/layouts/DashboardLayout.vue b/src/layouts/DashboardLayout.vue index 54311e5..a3ded1c 100644 --- a/src/layouts/DashboardLayout.vue +++ b/src/layouts/DashboardLayout.vue @@ -205,7 +205,7 @@ -
+
Diagnose Try Again
+ + @@ -307,7 +302,7 @@