mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
docs: add settings phase 1 design spec
Design for 5 new admin features inspired by Stirling-PDF: teams management, tool disabling, feature flags, temp file management, and custom branding/logo upload.
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
# Settings Phase 1 — Admin Control Panel
|
||||
|
||||
Inspired by Stirling-PDF's settings system, this phase adds five features to the existing settings dialog to make Stirling-Image feel like a serious self-hosted product.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Extend existing settings dialog (no separate admin panel route)
|
||||
- Teams are organizational labels only — no per-team permissions
|
||||
- Tool disabling and feature flags require server restart
|
||||
- Temp file management is minimal (max age + startup cleanup)
|
||||
- Custom branding is app name + logo (no favicon, no custom theme colors)
|
||||
|
||||
## 1. Teams Management
|
||||
|
||||
**New "Teams" tab in settings dialog.**
|
||||
|
||||
Simple CRUD for teams. Users are assigned to teams from the existing People section.
|
||||
|
||||
### Database
|
||||
|
||||
New `teams` table:
|
||||
|
||||
| Column | Type | Notes |
|
||||
|---|---|---|
|
||||
| id | text | Primary key (UUID) |
|
||||
| name | text | Unique, not null |
|
||||
| createdAt | integer (timestamp) | Auto-set |
|
||||
|
||||
Migration steps (single Drizzle migration file):
|
||||
1. Create `teams` table
|
||||
2. Insert a "Default" team with a known UUID
|
||||
3. Collect all distinct `users.team` string values; for each non-"Default" value, insert a new team row
|
||||
4. Update `users.team` from the string value to the corresponding team UUID
|
||||
5. Keep `users.team` as a plain `text` column (no DB-level FK — SQLite doesn't support adding FK constraints via ALTER TABLE). Enforce the relationship at the application level.
|
||||
|
||||
Note: The existing `0003_add_team_to_users.sql` migration added the `team` column as free text. This new migration extends that by creating the `teams` table and converting values.
|
||||
|
||||
### Team Name Validation
|
||||
|
||||
- 1-50 characters
|
||||
- Trimmed (no leading/trailing whitespace)
|
||||
- Unique (case-insensitive)
|
||||
- The "Default" team cannot be deleted (it's the fallback for new users)
|
||||
|
||||
### API Routes
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|---|---|---|---|
|
||||
| GET | /api/v1/teams | auth | List all teams with member count |
|
||||
| POST | /api/v1/teams | admin | Create team (body: `{ name }`) |
|
||||
| PUT | /api/v1/teams/:id | admin | Rename team (body: `{ name }`) |
|
||||
| DELETE | /api/v1/teams/:id | admin | Delete team (fails if team has members or is "Default") |
|
||||
|
||||
### UI
|
||||
|
||||
- Table with columns: Team Name, Total Members, actions (three-dot menu: Rename, Delete)
|
||||
- "+ Create New Team" button
|
||||
- Delete blocked with message if team has assigned members or is the Default team
|
||||
- People section's team assignment dropdown pulls from teams table
|
||||
|
||||
## 2. Tool Disabling
|
||||
|
||||
**New "Tools" tab in settings dialog.**
|
||||
|
||||
Admin can globally disable specific tools. Disabled tools are hidden from all users.
|
||||
|
||||
### Settings Key
|
||||
|
||||
`disabledTools` — JSON array of tool IDs. Default: `"[]"`
|
||||
|
||||
### Behavior
|
||||
|
||||
- On save, shows "Restart required for changes to take effect" banner
|
||||
- On API startup, server reads `disabledTools` and skips registering those tool routes (server-side enforcement)
|
||||
- Frontend also filters disabled tools from the tool panel for immediate visual feedback after save, but API routes remain active until restart
|
||||
- Pipelines containing disabled tools: step renders but shows "tool unavailable" badge
|
||||
|
||||
### UI
|
||||
|
||||
- Searchable list of all registered tools
|
||||
- Each tool has a toggle (on = enabled, off = disabled)
|
||||
- Search/filter bar at top
|
||||
- Tools grouped by category for easier scanning
|
||||
- "Restart required" banner appears after any change is saved
|
||||
|
||||
## 3. Feature Flags
|
||||
|
||||
**Added to existing "System Settings" section.**
|
||||
|
||||
Single toggle controlling visibility of experimental tools.
|
||||
|
||||
### Settings Key
|
||||
|
||||
`enableExperimentalTools` — `"true"` or `"false"`. Default: `"false"`
|
||||
|
||||
### Tool Registry Change
|
||||
|
||||
Reuse the existing `alpha?: boolean` field on the `Tool` type in `packages/shared/src/types.ts`. Rename it to `experimental?: boolean` for clarity (update all references). Tools marked experimental are hidden unless the flag is enabled.
|
||||
|
||||
### Behavior
|
||||
|
||||
- Works independently of tool disabling (a tool can be both experimental AND manually disabled)
|
||||
- On save, shows "Restart required" banner
|
||||
- When flag is off, experimental tools are excluded from: tool panel, fullscreen grid, pipeline step picker
|
||||
|
||||
### UI
|
||||
|
||||
- Single toggle row in System Settings: "Enable Experimental Tools" with description "Show tools that are still in development. These may be unstable."
|
||||
|
||||
## 4. Temp File Management
|
||||
|
||||
**Added to existing "System Settings" section under "File Management" sub-heading.**
|
||||
|
||||
Admin controls how long processed files persist and whether to clean on startup.
|
||||
|
||||
### Settings Keys
|
||||
|
||||
| Key | Default | Description |
|
||||
|---|---|---|
|
||||
| tempFileMaxAgeHours | "24" | Hours before temp files are eligible for cleanup |
|
||||
| startupCleanup | "true" | Whether to run cleanup on server boot |
|
||||
|
||||
### Behavior
|
||||
|
||||
- The cleanup function re-reads `tempFileMaxAgeHours` from the settings DB on every cycle (not cached at startup). If the setting is not set, falls back to the `FILE_MAX_AGE_HOURS` env var (default 24). DB setting takes precedence over env var.
|
||||
- On startup, if `startupCleanup` is true, cleanup runs asynchronously (does not block server startup — matches current behavior where `startCleanupCron()` is non-blocking)
|
||||
- Changes take effect on next cleanup cycle (no restart required)
|
||||
|
||||
### UI
|
||||
|
||||
- Number input: "Max File Age (hours)" with description "How long processed files are kept before automatic cleanup"
|
||||
- Toggle: "Startup Cleanup" with description "Clean up old temporary files when the server starts"
|
||||
|
||||
## 5. Custom Branding — Logo Upload
|
||||
|
||||
**Added to existing "System Settings" section, below App Name.**
|
||||
|
||||
Admin uploads a custom logo displayed in the sidebar/navbar.
|
||||
|
||||
### API Routes
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|---|---|---|---|
|
||||
| POST | /api/v1/settings/logo | admin | Upload logo (PNG/SVG/JPEG, max 500KB) |
|
||||
| GET | /api/v1/settings/logo | public | Serve custom logo (404 if none) |
|
||||
| DELETE | /api/v1/settings/logo | admin | Remove custom logo |
|
||||
|
||||
### Settings Key
|
||||
|
||||
`customLogo` — `"true"` or `"false"`. Default: `"false"`
|
||||
|
||||
### Behavior
|
||||
|
||||
- All uploaded logos are converted to PNG and stored to `data/branding/logo.png` (SVGs are rasterized, JPEGs are re-encoded)
|
||||
- Server resizes to max 128x128 via Sharp on upload
|
||||
- `GET /api/v1/settings/logo` serves with `Content-Type: image/png`. This route must be added to `PUBLIC_PATHS` in `auth.ts` so the logo is accessible on the login page.
|
||||
- Sidebar/navbar checks `customLogo` on mount — if true, loads from logo endpoint; otherwise uses built-in SVG
|
||||
- No restart required — logo change is immediate
|
||||
|
||||
### UI
|
||||
|
||||
- Logo upload area with drag-and-drop, preview thumbnail
|
||||
- "Remove" button to revert to default logo
|
||||
- Accepts PNG, SVG, JPEG. Max 500KB.
|
||||
- Shows current logo preview if one is set
|
||||
|
||||
## 6. Settings Dialog Navigation
|
||||
|
||||
### Current Sections
|
||||
General, System Settings, Security, People, API Keys, About
|
||||
|
||||
### New Sections
|
||||
General, System Settings, Security, People, **Teams**, API Keys, **Tools**, About
|
||||
|
||||
### Section Contents
|
||||
|
||||
| Section | What's new |
|
||||
|---|---|
|
||||
| System Settings | Feature flags toggle, temp file management controls, logo upload area (all added to existing section) |
|
||||
| Teams | Entirely new — team CRUD table |
|
||||
| Tools | Entirely new — tool enable/disable list |
|
||||
|
||||
### Frontend Type Changes
|
||||
|
||||
- Add `"teams" | "tools"` to the `Section` type union in `settings-dialog.tsx`
|
||||
- Add corresponding entries to `NAV_ITEMS` array
|
||||
|
||||
### i18n
|
||||
|
||||
Add translation keys to `packages/shared/src/i18n/en.ts` under `settings` for the new sections (teams, tools) and their UI strings.
|
||||
|
||||
## Summary
|
||||
|
||||
| Feature | UI Location | New DB/API | Restart Required |
|
||||
|---|---|---|---|
|
||||
| Teams CRUD | New "Teams" tab | `teams` table, 4 CRUD routes | No |
|
||||
| Tool disabling | New "Tools" tab | `disabledTools` setting key | Yes |
|
||||
| Feature flags | System Settings | `enableExperimentalTools` setting key | Yes |
|
||||
| Temp file management | System Settings | 2 setting keys | No |
|
||||
| Logo upload | System Settings | 3 routes, `customLogo` key, `data/branding/` | No |
|
||||
Reference in New Issue
Block a user