feat(manager-core): admin is implicit app_admin; delete-script needs AppAdmin

Aligns the canonical capability rules with how the dashboard now shadows
its UI. Instance admins become implicit app_admin on every app (only
InstanceManageSettings stays owner-only), and the script-delete handler
moves from AppWriteScript to AppAdmin so editors can save but not delete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-28 19:27:32 +02:00
parent ec3c768262
commit 4644ea4919
5 changed files with 94 additions and 67 deletions

View File

@@ -1049,7 +1049,7 @@ pub struct Principal {
| Role | Powers |
|---|---|
| `owner` | full instance control, manage other owners, implicit `app_admin` on every app. Multiple owners allowed. |
| `admin` | create apps, invite users, implicit `editor` on every app. Cannot manage instance-wide settings or other owners. |
| `admin` | create apps, invite users, implicit `app_admin` on every app. Cannot manage instance-wide settings (sandbox ceiling, etc.) or other owners. |
| `member` | invited into specific apps only. Cannot create apps, cannot invite. **Strict isolation enforced at SQL** — list endpoints `WHERE app_id IN (SELECT app_id FROM app_members WHERE user_id = $1)`; the API never returns apps a member isn't part of. |
The current Phase 3a `admin_users` rows all become `owner` via `DEFAULT 'owner'` on the new column. Multi-owner installs get a startup `tracing::warn!` listing the active owner usernames so the operator can demote extras via `PATCH /api/v1/admin/admins/{id}`.
@@ -1058,11 +1058,13 @@ The current Phase 3a `admin_users` rows all become `owner` via `DEFAULT 'owner'`
| Role | Grants |
|---|---|
| `app_admin` | settings, domain claims, delete app |
| `editor` | CRUD on scripts, routes, sandbox config |
| `app_admin` | settings, domain claims, delete app, **delete scripts** |
| `editor` | create + edit scripts, routes, sandbox config (no script delete) |
| `viewer` | read scripts + execution logs |
Implicit grants from instance role: every `owner` is `app_admin` on every app; every `admin` is `editor` on every app. Explicit `app_members` rows are the only path for `member` users.
Implicit grants from instance role: every `owner` and every `admin` is `app_admin` on every app — a single-human install would otherwise have to add itself to each new app's `app_members`. Explicit `app_members` rows are the only path for `member` users.
Script **save** uses `AppWriteScript` (editor+); script **delete** uses `AppAdmin` (app_admin+). Editors can iterate on a script's source freely but cannot remove it — destructive cleanup stays with the role that also owns the app.
### Auth Methods — Same Principal, Different Extractor