When auth was disabled, the backend middleware attached the first admin
user from the database to every request, and the frontend granted all 12
permissions. This gave every unauthenticated visitor full admin access
to user management, settings, teams, branding, and feature installation.
Now both layers use role "user" with user-level permissions so tools,
files, and pipelines still work without login while admin-only routes
correctly return 403.
Closes#72
- Fix SKIP_MUST_CHANGE_PASSWORD not affecting login/session API responses,
causing frontend redirect even when the env var was set after user creation
- Increase Docker Playwright timeouts (test: 600s, expect: 60s, AI processing: 300s)
to support CPU-only self-hosted environments
- Increase default rate limit from 100 to 50000 req/min for self-hosted deployments
- Fix OCR tests: use filechooser pattern (Dropzone has no static file input),
correct enhance checkbox default, rewrite for actual fixture behavior
- Fix remove-bg tests: update quality labels (Balanced→HD, Best→Max)
- Fix noise-removal skip guard: use waitFor() instead of instant isVisible()
- Fix automate pipeline save test: clean up stale E2E pipelines before assertion
Several RBAC features from feat/rbac-permissions were silently lost
during the merge into main. This restores and completes them:
- Add permissions and teamName to login/session API responses
- Export Permission and Role types from shared package
- Filter settings tabs by user permissions in frontend
- Extend useAuth hook with role, permissions, and hasPermission
- Restrict teams listing to admin only
- Add admin override for API keys, files, and pipelines listing
- Add ownership scoping to file access, download, and delete routes
- Register userFileRoutes in integration test server
- Mock auth import in unit permissions test to avoid SQLite lock
Migrate settings, teams, branding, and user management routes to use
the new permission-based authorization system. Remove requireAdmin
function entirely.
- Health endpoint returns "healthy" instead of "ok" for consistency
- MAX_USERS now configurable via env var (default 5)
- People API returns team names instead of UUIDs in register/list
- PUT user update accepts team names (name-first lookup, fallback to ID)
- Login rate limit follows global rate limit when RATE_LIMIT_PER_MIN > 1000
- Strip-metadata preserves original format encoding instead of always PNG
- Fix e2e tests: rotate/crop/border button selectors match actual UI
- Fix e2e tests: create Engineering/Design teams in people test setup
- Fix e2e tests: people UI uses select for team field, not text input
- Update visual regression baseline for tablet home page
Remove hardcoded --platform=linux/amd64 from Dockerfile so buildx produces
native arm64 images for Apple Silicon and Raspberry Pi. Add audit logging
for auth events, harden file storage with extension whitelists and
double-extension attack prevention, reject null-byte buffers in validation,
add data-testid attributes to all tool settings components, update
deployment docs with architecture notes and correct CI workflow references,
and fix unit test mock to match throwWithMessage error extraction.
- Backend: look up teams by name first (frontend sends name, not ID)
- Frontend: parse response body on API errors instead of showing
generic "API error: 400" — now shows the actual server message
(e.g. "Password must be at least 8 characters...")
- Make ensureDefaultAdmin idempotent with onConflictDoNothing (fixes
UNIQUE constraint error when parallel test files share a DB)
- Move duplicate-username check before user-limit check so 409 takes
priority over 403
- Bump MAX_USERS from 5 to 50 (tests create ~15 users across files)
Remove docs/superpowers/, .claude/ config, and PRD.md from version
control (kept locally via .gitignore). Update README, CHANGELOG,
VitePress docs, and .env.example to reflect recent features: Files
page, teams, admin settings, persistent storage, and various API
improvements.
The /api/v1/jobs/ endpoint was blocked by auth middleware.
EventSource doesn't support custom headers so auth tokens can't be
sent. The jobId is a random UUID (unguessable capability token), same
security model as the download endpoint.
- Set up semantic-release with zero-touch CI pipeline on push to main
- Add version sync script to keep all package.json files and APP_VERSION
constant in sync automatically
- Consolidate Docker publishing into single tag-triggered workflow that
pushes to both Docker Hub and ghcr.io with semver tags
- Add help dialog with keyboard shortcuts, getting started guide, and
resource links
- Sync all versions to 0.2.1 to match Docker Hub latest
- Add user management endpoints (register, list, delete, change password)
- Add API key management (create, list, delete)
- Add settings persistence endpoints (get, put)
- Wire settings dialog to real backend (People, API Keys, System, Security)
- Fix login auth flow (window.location.href for full reload)
- Fix download URLs returning 401 (make public since UUIDs are unguessable)
- Fix border tool shadowColor validation (accept 6-8 hex digits)
- Fix remove-bg alpha matting fallback (retry without on failure)
- Fix AI tool silent fallbacks (report errors instead of no-ops)
- Add checkerboard background to before/after slider for transparency
- Add progress bars to all AI tool components
- Add Playwright E2E test suite (131 tests across 9 test files)
- Rewrite Dockerfile for production (tsx runtime, pre-baked AI models)
- Add .dockerignore for faster builds
- Add proper accessible labels to login form
1. Home page file drop now shows quick-action tool selector
2. Auth disabled by default in dev (Docker still defaults to true)
3. Tool settings wrapped in forms - Enter key triggers processing
Implement custom auth using crypto.scrypt password hashing and UUID
session tokens. Includes login/logout/session endpoints, preHandler
middleware that skips public routes, and automatic default admin
creation on first startup.