Commit Graph
749 Commits
Author SHA1 Message Date
AshimandGitHub 136a4dd641 Merge pull request #93 from ashim-hq/test/comprehensive-coverage
test: comprehensive test coverage expansion (+965 tests, 48/48 tools)
2026-04-23 17:12:53 +08:00
ashim-hq babca4cf97 test: comprehensive test coverage expansion (+965 tests)
Add 42 new test files covering all untested tool routes, image engine
internals, AI sidecar bridge, Zustand stores, and cross-format
compatibility. Expand e2e-docker suite with 7 spec files covering all
48 tools against a real Docker container.

Unit tests:
- Image engine: format detection, MIME mapping, metadata parsing, pipeline
- AI bridge: sidecar lifecycle, all 11 tool functions (mocked)
- Web stores: 14 Zustand stores (collage, settings, features, analytics, etc.)
- API helpers: format decoders, page range, file validation

Integration tests:
- 25 tool routes that had zero dedicated tests
- Cross-format matrix: 17 input formats x 3 tools
- Edge cases: zero-byte files, corrupted headers, path traversal, XSS, SQL injection
- Concurrent request handling and pipeline edge cases

E2E-Docker (Playwright against real container):
- 7 spec files: essential, adjustment, conversion, creative, utility, AI, pipeline
- Custom buildMultipart helper for multi-file tool uploads
- AI tools gracefully skip when sidecar not installed

Fixtures:
- Organized test media: formats/ (18 formats) + content/ (17 content types)
- Reduced from 3.1 GB unorganized samples to 33 MB structured fixtures

Bug fix:
- color-adjustments: gamma exposure used invalid single-param gamma() for
  positive values; fixed to use two-param gamma(gammaIn, gammaOut) form
2026-04-23 17:12:02 +08:00
AshimandGitHub 9ff23f38fb Merge pull request #92 from ashim-hq/fix/auth-false-escalation-90
fix: prevent admin escalation when AUTH_ENABLED=false
2026-04-23 14:46:20 +08:00
ashim-hq 7047ce5fae fix: prevent admin escalation when AUTH_ENABLED=false
When auth was disabled, users could log out, reach the login page,
and authenticate with the default admin/admin credentials to gain
full admin privileges — defeating the purpose of AUTH_ENABLED=false.

Defense-in-depth fix across five layers:
- Skip ensureDefaultAdmin() when auth is disabled (no admin user seeded)
- Return 403 from POST /api/auth/login when auth is disabled
- Return synthetic anonymous user from GET /api/auth/session when auth is disabled
- Hide logout button in settings when auth is disabled
- Redirect /login and /change-password to / via AuthGuard when auth is disabled

Closes #90
2026-04-23 14:45:04 +08:00
ashim-hq 19df740880 docs: add Code of Conduct and community guide for GitHub Discussions
Establishes Contributor Covenant 2.1 as the project Code of Conduct with
reporting to ashim.hq@gmail.com. Adds a community guide with the 5-category
Discussions layout, a pinned Welcome post draft, and seed post ideas.
2026-04-23 12:57:47 +08:00
ashim-hq 949ac5d15a docs: add SECURITY.md with vulnerability reporting, hardening checklist, and shared responsibility model 2026-04-23 12:49:44 +08:00
AshimandGitHub 47376b1664 Merge pull request #91 from ashim-hq/feat/analytics
feat: production-grade opt-in product analytics with PostHog and Sentry
2026-04-23 12:40:08 +08:00
ashim-hq d973ab61ee fix: robust auth setup and login helpers for E2E analytics tests 2026-04-23 12:08:03 +08:00
ashim-hq d6a977e149 fix: use full page reload after consent to avoid AuthGuard race condition 2026-04-23 11:19:31 +08:00
ashim-hq d543141d19 fix: prevent hydration effect from overwriting user consent actions 2026-04-23 11:14:48 +08:00
ashim-hq fc059c751d test: comprehensive analytics test suite — unit, API, E2E, air-gapped 2026-04-23 10:58:56 +08:00
ashim-hq de7b353871 fix: analytics E2E tests for post-auth-setup consent state
The auth setup project accepts analytics consent for the admin user
before tests run. The E2E tests incorrectly expected the consent page
to appear on subsequent logins. Fixed by:

- analytics-consent: verify home loads without consent redirect instead
  of expecting the consent page to appear
- analytics-privacy-policy: use getByRole("link") for PostHog/Sentry
  links to avoid matching multiple elements with getByText
- analytics-no-data-leak: use page.evaluate with in-browser auth token
  to toggle analytics via API instead of separate login calls that hit
  the rate limiter; handle both "/" and "/analytics-consent" post-login
2026-04-23 10:51:58 +08:00
ashim-hq e46356c4d5 fix: hydrate analytics store from session data on login 2026-04-23 10:08:24 +08:00
ashim-hq 7275e4bfaa fix: AuthGuard checks analytics store for real-time consent state 2026-04-23 10:06:46 +08:00
ashim-hq 9724e5229c test: add comprehensive E2E Playwright tests for analytics feature
Covers consent flow, API endpoints, privacy/no-data-leak verification,
disabled-server behavior, settings toggle, and privacy policy page.
2026-04-23 09:59:41 +08:00
ashim-hq 3ef52d0aa9 feat: set PostHog and Sentry default keys for analytics 2026-04-23 00:29:22 +08:00
ashim-hq 9ad94f3d54 docs: update README analytics statement 2026-04-22 19:16:01 +08:00
ashim-hq c2130148c4 fix: add statement-breakpoint separators to analytics migration 2026-04-22 19:15:38 +08:00
ashim-hq 6e319efadd feat: add analytics init, identify, search tracking, consent header, settings toggle 2026-04-22 19:14:16 +08:00
ashim-hq f115275796 feat: add analytics consent page and auth flow integration 2026-04-22 19:10:52 +08:00
ashim-hq 9f66ad85bf feat: add Sentry error tracking with PII scrubbing 2026-04-22 19:10:28 +08:00
ashim-hq 544f81c48d feat: add frontend analytics wrapper and consent store 2026-04-22 19:07:50 +08:00
ashim-hq a3f707a361 feat: instrument tool_used, pipeline_executed, ai_bundle_action events 2026-04-22 19:07:17 +08:00
ashim-hq 39b011eccb docs: update privacy policy to reflect analytics 2026-04-22 19:06:01 +08:00
ashim-hq 075f017dbf feat: add backend analytics wrapper, config/consent API routes 2026-04-22 19:03:23 +08:00
ashim-hq 4904e8d140 feat: add analytics env vars, DB schema columns, instance ID generation 2026-04-22 19:00:15 +08:00
ashim-hq 03df555e10 feat: add shared analytics types, events, consent logic, and i18n strings 2026-04-22 18:58:16 +08:00
AshimandGitHub 5a45bcbc8f feat: production-grade RBAC with editor role, custom roles, API key scoping, and audit log (#89)
* feat(rbac): add editor role, 3 new permissions, ownership helper

* feat(rbac): add audit_log table, apiKeys.permissions column, editor role to schema

* feat(rbac): wire requirePermission into all routes, add editor role support

* refactor(rbac): replace ad-hoc role checks with permission-based ownership

* feat(rbac): add audit log DB writes + query endpoint

Dual-write audit events to stdout (existing) and SQLite audit_log table.
Add GET /api/v1/audit-log with pagination, action filter, and date range
filtering, gated behind audit:read permission.

* feat(rbac): add API key permission scoping with ceiling enforcement

* feat(rbac): add escalation prevention and last-admin protection

* feat(rbac): add editor role to UI, API key permission scoping in settings

* test(rbac): add full permission matrix integration test

* test(rbac): add editor role E2E tests

* feat(rbac): add custom roles with CRUD API and DB-backed permission lookup

* feat(rbac): add API key expiration

* feat(rbac): add roles management UI and API key expiration to settings

* feat(rbac): add audit log UI to settings

* fix: remove any cast in API key permission validation

* test(rbac): add unit tests for username validation rules

* test(rbac): add unit tests for effective permissions and ownership

* test(rbac): add comprehensive route permission matrix (all routes × all roles)

* test(rbac): add auth route edge case tests (login failures, session expiry, password side effects)

* test(rbac): add escalation prevention tests (register, update, self-demote, last-admin)

* test(rbac): add ownership enforcement tests (files, pipelines, editor access, cross-user isolation)

* test(rbac): add API key edge cases (name validation, delete behavior, key revocation)

* test(rbac): add audit log edge cases (all events, pagination clamping, structure)

* test(rbac): add custom roles edge case tests (validation, CRUD, functional permissions)

* test(rbac): add comprehensive E2E tests (roles UI, audit log, custom role, API key scoping)
2026-04-22 18:10:04 +08:00
AshimandGitHub 2d7a61c18f feat: allow multi-file selection for automation pipeline (#88)
* feat: allow multi-file selection for automation pipeline

Add two ways to import server-stored files into the pipeline:

1. Files page: "Pipeline" bulk action button and "Open in Pipeline"
   button in file details panel — navigates to /automate with selected
   file IDs via React Router state.

2. Automate page: "Import from Library" button opens a modal with
   thumbnails, search, and multi-select checkboxes to pick files from
   the user's server-stored library.

Both paths download the selected files and load them into the existing
useFileStore, reusing the batch pipeline processing infrastructure.

Closes #35

* fix: resolve 8 pre-existing test failures across unit and integration suites

- file-validation.ts: Return valid:false when Sharp fails to read
  metadata for standard formats (PNG, JPEG, BMP) instead of silently
  accepting corrupt buffers. CLI-decoded formats already skip Sharp.

- pipeline.ts: Enforce hard cap of 20 steps via .max() instead of
  relying on MAX_PIPELINE_STEPS env var (default 0 = unlimited).
  Tighten name limit to 100 chars and description to 500 chars to
  match test expectations.

- env.ts: Change MAX_LOGO_SIZE_KB default from 2048 to 500 to match
  the branding upload size limit the tests verify.
2026-04-22 00:02:00 +08:00
ashim-hq 9a015c8501 fix: AVIF sidecar crash, edit-metadata silent no-op, passport batch blank images, color-palette hex overflow, OCR log noise
- Convert all AI bridge inputs to PNG before writing to disk so PIL can
  read AVIF/WebP/TIFF (7 bridge files; face-detection and OCR already
  had this pattern)
- Add title/author aliases to edit-metadata schema so common field names
  actually write EXIF tags instead of being silently stripped by Zod
- Port extend/pad crop logic from passport-photo single endpoint to the
  batch pipeline so crop regions extending beyond the image get filled
  with background color instead of producing all-white output
- Clamp quantized color channels to 255 in color-palette to prevent
  Math.round(255/16)*16=256 from producing invalid hex like #100100100
- Compare OCR fallback warning against expected engine name per tier
  instead of comparing engine name against tier name (always mismatch)
2026-04-21 23:54:25 +08:00
AshimandGitHub 0b8e0bf774 fix: auto-fallback from CodeFormer to GFPGAN in face enhancement (#87)
When model is set to "auto", CodeFormer failure previously threw an
error telling users to manually switch to GFPGAN. Now it falls back
to GFPGAN automatically, matching the graceful degradation pattern
already used in OCR.
2026-04-21 23:51:11 +08:00
AshimandGitHub 6fcf43016d Merge pull request #86 from ashim-hq/fix/issue-72-auth-false-admin
fix: prevent admin escalation when AUTH_ENABLED=false
2026-04-21 23:42:18 +08:00
ashim-hq bf73150301 fix: prevent admin escalation when AUTH_ENABLED=false
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
2026-04-21 23:38:42 +08:00
AshimandGitHub ba26ea4bc7 feat: add AVIF output format support across 6 remaining tools (#85)
Closes #73

AVIF was already supported in the core engine, convert, compress,
optimize-for-web, upscale, erase-object, svg-to-raster, and
pdf-to-image tools. This adds AVIF as an output format option to
the 6 tools that were missing it: split, collage, stitch,
image-to-base64, noise-removal, and red-eye-removal.

For each tool, both the frontend format selector (with quality
slider for AVIF's lossy encoding) and the backend Zod schema +
Sharp .avif() encoding were updated. AVIF defaults: quality from
the user slider, effort 4 (balanced encode speed).

Also fixes pre-existing Biome formatting violations in 5 files
that were blocking a clean lint pass.
2026-04-21 23:34:48 +08:00
AshimandGitHub 7d422c2fd0 Merge pull request #84 from ashim-hq/fix/settings-default-tool-view
fix: wire up Default Tool View save in General settings
2026-04-21 23:27:04 +08:00
ashim-hq 7920fbfd20 chore: fix pre-existing biome formatting issues 2026-04-21 23:25:41 +08:00
ashim-hq afac4b9870 fix: wire up Default Tool View save in General settings
The <select> for Default Tool View was an uncontrolled dead control with
no value binding, no onChange handler, and no save mechanism. This wires
it up end-to-end:

- Add defaultToolView to the Zustand settings store
- Load the persisted value from the settings API on mount
- Bind the <select> with value/onChange
- Add Save Settings button mirroring SystemSection's pattern
- Redirect home page to /fullscreen when defaultToolView is "fullscreen"

Closes #75
2026-04-21 23:25:34 +08:00
ashim-hq 77a60b24cc fix: resolve 5 bugs found during comprehensive tool testing
1. split batch 404: register split tool in batch registry via
   registerToolProcessFn() so /api/v1/tools/split/batch works

2. CodeFormer crash: inference_app() expects a file path, not a numpy
   array. Save to temp file before calling, read result back.

3. OCR fallback chain: fix case-sensitive "Segmentation fault" match
   that prevented PaddleOCR crash from triggering Tesseract fallback.
   Also add "process crashed" check. Upgrade ARM paddlepaddle to >=3.2.1.

4. blur-faces large images: downscale to 1920px max before MediaPipe
   detection, scale coordinates back. Also add rotation retry for
   portrait-oriented images where BlazeFace misses faces. Applied to
   detect_faces.py, enhance_faces.py, and restore.py.

5. color-adjustments tool ID: fix mismatch in index.ts registration
   array (was "color-adjustments", should be "adjust-colors").
2026-04-21 22:25:06 +08:00
ashim-hq c17caa42e0 fix: add missing ConnectionMonitor component
The connection-monitor.tsx component was referenced in App.tsx but the
file was missing, causing TypeScript compilation failure during Docker
build. This component combines the useConnectionMonitor hook with
the ConnectionBanner UI.
2026-04-21 21:25:39 +08:00
ashim-hq 26506ba41b Merge remote-tracking branch 'origin/feat/docker-hardening-v1' into merge-work-on-demand 2026-04-21 21:23:52 +08:00
AshimandGitHub 8f6dbeca32 Merge pull request #83 from ashim-hq/feat/extended-format-support
feat: extended image format support (JXL, RAW, ICO, TGA, PSD, EXR, HDR)
2026-04-21 10:55:32 +08:00
ashim-hq b966d81b10 chore: remove test-only compose file 2026-04-21 10:45:17 +08:00
ashim-hq 4ccde70dad fix: info tool fails for CLI-decoded formats (PSD, TGA, EXR, HDR, ICO)
The info tool reads metadata directly via Sharp without going through
the format decoder pipeline. Added CLI format detection and decoding
before metadata read, matching the pattern used by all other tools.
2026-04-21 10:34:10 +08:00
ashim-hq 966d7abaf0 fix: AVIF compress fails because Sharp metadata reports heif not avif
Sharp's metadata() returns format:"heif" for AVIF files. The compress
function was using this raw value without normalizing through FORMAT_MAP,
so toFormat("heif",...) was called which requires a compression option.
Now both explicit and detected formats go through FORMAT_MAP, mapping
heif→avif correctly.
2026-04-21 10:27:02 +08:00
ashim-hq dc9160746e fix: ICO needs CLI decode, AVIF compress missing options, remove JXL output
- ICO: Sharp cannot decode ICO files. Added ImageMagick-based ICO decoder
  that extracts the largest embedded image. Added ICO to CLI_DECODED_FORMATS
  and SERVER_PREVIEW_EXTENSIONS. Removed from BROWSER_PREVIEWABLE sets.
- AVIF compress: Sharp's AVIF encoder requires effort option. Added
  formatOpts() helper that supplies effort:4 for AVIF format.
- JXL output: Docker's bundled libvips lacks the JXL encoder plugin.
  Removed JXL as a convert output target to avoid guaranteed failures.
  JXL remains fully supported as an input format.
2026-04-21 10:20:08 +08:00
AshimandGitHub 4c9dc6e38e fix: Docker hardening, security, and deployment readiness for V1 (#82)
Phase 1 — Docker Artifact Optimization:
- Replace broad `COPY . .` with targeted frontend source copies (API/Python
  changes no longer bust the frontend build cache)
- Replace build-essential with gcc/g++ (leaner runtime)
- Fix LOG_LEVEL=debug → info for production
- Harden .dockerignore (exclude worktrees, IDE, CI, test artifacts)

Phase 2 — State & Persistence:
- Add PUID/PGID support in entrypoint.sh for bind mount compatibility
- Guard against PUID=0/PGID=0 to prevent accidental root execution
- Evict conflicting system users (e.g. node:1000) before UID remap

Phase 3 — Security:
- Always register @fastify/rate-limit so login brute-force protection
  works even when global rate limit is disabled (RATE_LIMIT_PER_MIN=0)
- Add trustProxy support (TRUST_PROXY env var, default true) so rate
  limiting and audit logs use real client IPs behind reverse proxies
- Strip stack traces from 500 error responses in production
- Fix FSTDEP022 deprecation: maxParamLength → routerOptions
- Add multi-file guard on single-file tool endpoint with clear error
  message pointing to the /batch endpoint

Phase 4 — Graceful Degradation:
- Add consolidated hardware detection startup banner (GPU, rate limit,
  upload limit, proxy status)
- Add ConnectionMonitor component with health polling and reconnecting
  overlay that auto-dismisses when the server comes back

Phase 5 — Deployment Docs:
- Rewrite deployment.md with copy-paste CPU and GPU compose templates
- Add hardware requirements table (minimum, recommended, heavy workloads)
- Add PUID/PGID bind mount documentation
- Add complete env var reference table
- Add reverse proxy guides for Nginx, Nginx Proxy Manager, Traefik,
  and Cloudflare Tunnels
2026-04-21 10:19:08 +08:00
ashim-hq 1dc3adbdba fix: Docker hardening, security, and deployment readiness for V1
Phase 1 — Docker Artifact Optimization:
- Replace broad `COPY . .` with targeted frontend source copies (API/Python
  changes no longer bust the frontend build cache)
- Replace build-essential with gcc/g++ (leaner runtime)
- Fix LOG_LEVEL=debug → info for production
- Harden .dockerignore (exclude worktrees, IDE, CI, test artifacts)

Phase 2 — State & Persistence:
- Add PUID/PGID support in entrypoint.sh for bind mount compatibility
- Guard against PUID=0/PGID=0 to prevent accidental root execution
- Evict conflicting system users (e.g. node:1000) before UID remap

Phase 3 — Security:
- Always register @fastify/rate-limit so login brute-force protection
  works even when global rate limit is disabled (RATE_LIMIT_PER_MIN=0)
- Add trustProxy support (TRUST_PROXY env var, default true) so rate
  limiting and audit logs use real client IPs behind reverse proxies
- Strip stack traces from 500 error responses in production
- Fix FSTDEP022 deprecation: maxParamLength → routerOptions
- Add multi-file guard on single-file tool endpoint with clear error
  message pointing to the /batch endpoint

Phase 4 — Graceful Degradation:
- Add consolidated hardware detection startup banner (GPU, rate limit,
  upload limit, proxy status)
- Add ConnectionMonitor component with health polling and reconnecting
  overlay that auto-dismisses when the server comes back

Phase 5 — Deployment Docs:
- Rewrite deployment.md with copy-paste CPU and GPU compose templates
- Add hardware requirements table (minimum, recommended, heavy workloads)
- Add PUID/PGID bind mount documentation
- Add complete env var reference table
- Add reverse proxy guides for Nginx, Nginx Proxy Manager, Traefik,
  and Cloudflare Tunnels
2026-04-21 10:18:57 +08:00
ashim-hq 2df0fe026e fix: use ImageMagick for RAW decoding instead of dcraw_emu
dcraw_emu is not included in libraw-dev (only libraries). ImageMagick
already delegates to LibRaw for all major RAW formats (DNG, CR2, NEF,
ARW, ORF, RW2). Moved ImageMagick helpers above RAW decoder to fix
declaration order.
2026-04-21 10:03:18 +08:00
ashim-hq 2aadb66031 feat: add support for JXL, Camera RAW, ICO, TGA, PSD, EXR, HDR image formats
Extends the platform to handle 7 new image format families alongside
the existing AVIF support gap-fill. Uses the established HEIC decoder
pattern (CLI decode → PNG → Sharp) for formats Sharp can't handle
natively: Camera RAW via dcraw_emu/LibRaw, PSD/TGA/EXR/HDR via
ImageMagick. JXL and ICO are Sharp-native. Adds server-side preview
for non-browser-displayable formats and JXL as a new convert output
target. All 27 validateImageBuffer callers updated with filename for
extension-based format detection.
2026-04-21 09:59:57 +08:00
AshimandGitHub fa35f57813 Merge pull request #81 from ashim-hq/worktree-automate-ui-redesign
feat: redesign Automate page — tool palette + pipeline canvas
2026-04-21 09:27:47 +08:00