The empty-state dropzone in the Automate preview panel was expanding
to fill the full 38% panel height, causing overlap and clipping of
the "Import from Library" button. Constrain to max 120px and tighten
spacing for a cleaner layout.
The security hardening commit changed this to false, which prevents
the analytics consent page from appearing on first login. Users see
"disabled by administrator" instead of being asked to opt in/out.
With ANALYTICS_ENABLED=true, the SDK initializes but NO user data is
sent until the user explicitly accepts on the consent page. The consent
page is the privacy safeguard, not the server-side flag. Self-hosters
who want to fully disable analytics can still set ANALYTICS_ENABLED=false.
The docs version badge was reading from apps/docs/package.json which
gets out of sync during manual releases. Read from the monorepo root
package.json instead so it always matches the released version.
- Bump Go from 1.23 to 1.24 to fix CVE-2025-68121 (CRITICAL:
crypto/tls certificate validation) and CVE-2025-61726 (HIGH:
net/url memory exhaustion) in the caire binary.
- Bump Pillow from 11.1.0 to 12.1.1 to fix CVE-2026-25990 (HIGH:
out-of-bounds write via crafted image).
All 13 HIGH CVEs (glob, minimatch, picomatch, tar) are bundled
inside pnpm 9.x itself, not in our application dependencies.
pnpm overrides only affect our app's dependency tree, not pnpm's
internal modules. All require upgrading to pnpm 10.x.
The Trivy scan finds HIGH CVEs in pnpm's own transitive dependencies
(glob, minimatch, tar, picomatch) which are build-time only and not
in the runtime image. These block manifest creation unnecessarily.
Scan results still upload to GitHub Security tab via SARIF.
- Add v1.17.2 entry to docs/changelog.md
- Add "Update docs changelog" step to release workflow that
auto-prepends .release-notes.md to the docs changelog on
each release, then commits and pushes to trigger docs deploy
Deleting .github breaks the Post Run cleanup for composite actions,
causing the entire job to fail. Use tar --exclude instead so the
working directory stays intact for GitHub Actions cleanup.
The archive step removes .git before creating the tarball, but
gh release upload needs git context to resolve the repo. Pass
--repo explicitly to avoid "not a git repository" errors.
- fix(ocr): change paddlepaddle-gpu from --extra-index-url to --index-url
for the CUDA 12.6 package index. With --extra-index-url, pip could
resolve from PyPI (CUDA 11 build) instead of the cu126 index, causing
"libcusolver.so.11: undefined symbol" errors on CUDA 12 containers.
- revert version to 1.17.1 (v1.17.2 release was deleted)
- fix(rate-limit): treat RATE_LIMIT_PER_MIN=0 as unlimited (50k/min)
instead of blocking all requests. @fastify/rate-limit interprets
max:0 as "allow zero requests," breaking fresh container startups.
- fix(docker): add libgles2 for MediaPipe face detection tools.
blur-faces, red-eye-removal, enhance-faces, and passport-photo
failed with "libGLESv2.so.2 not found" on all headless containers.
- fix(docker/arm64): remove conflicting system libheif1 to avoid
ABI symbol mismatch with our custom libheif 1.21.2 build.
heif-convert failed with "undefined symbol: heif_get_plugin_directories."
- fix(docker/arm64): pre-install wheel+setuptools in base Python venv
so basicsr can build from source on arm64 (no pre-built wheel).
This unblocks upscale-enhance and photo-restoration bundles.
Rewrote all homepage CSS overrides from scratch:
- Brand name at 44px with gradient, subtitle at 34px (clear hierarchy)
- Feature cards at 14px/13px with 20px padding (readable, not cramped)
- 3-column feature grid with equal-height rows
- Removed VitePress 128px default gap before footer
- Trimmed Local AI feature description to balance card heights
Entire page fits in one viewport without scrolling.
Relocate the terminal mockup from the separate HowItWorks section
into the hero so the install command is visible immediately without
scrolling. Remove the now-empty HowItWorks component from the page.
The .name and .clip are the same element (class="name clip"), not
nested, so .name .clip selector never matched. Use .name.clip instead.
Also remove VitePress default 128px margin-bottom on .VPHome that was
pushing the footer below the viewport.
Swap 25 dry feature bullets for 15 messages with voice -- mix of
cheeky, warm, and playful tones across privacy, simplicity, open
source, use cases, and capability themes. Interleaved rotation order
ensures theme variety for any viewing window.
The hero title was left-aligned while tagline/buttons were centered,
creating a visual mismatch. Use flexbox centering on .VPHero .main to
align all hero elements. Bump font sizes slightly and equalize feature
card heights with height: 100%.
Reduce hero padding and font sizes, center tagline and action buttons,
switch feature cards from 2-column to 3-column grid, and tighten all
section spacing so the entire docs homepage is visible without scrolling.
- Create 53 per-tool VitePress documentation pages with accurate
parameters from Zod schemas, example requests, and response formats
- Add root llms.txt for LLM-friendly repo browsing
- Fix OpenAPI spec: add auth and 422 error schemas to
edit-metadata/inspect and strip-metadata/inspect sub-routes
- Fix tool count inconsistency (52 -> 53) across landing site,
e2e tests, and local docs
- Rename color-adjustments.ts to adjust-colors.ts to match tool ID
- Update VitePress sidebar with all 8 tool categories and top nav
Two pipeline tests ("accepts pipeline with more than 20 steps when
limit is unlimited") expected unlimited steps but the test env didn't
set MAX_PIPELINE_STEPS, falling back to the default of 20.
* feat(a11y): add i18n keys for ARIA labels and screen reader text
* fix(security): harden API against pentest findings
- Default TRUST_PROXY=false to prevent XFF rate limit bypass (PT-01)
- Return 400 instead of 500 on malformed JSON input (PT-03)
- Default MAX_PIPELINE_STEPS=20 to prevent DoS (PT-04)
- Validate clientJobId length (max 128) across all routes (PT-06)
- Add security headers to all reply.hijack() streaming responses (PT-07)
- Sanitize usernames in audit log to prevent stored XSS (PT-08)
- Block TRACE method with 405 response (PT-10)
- Add 429 RateLimited response to OpenAPI spec (PT-12)
- Default MAX_SVG_SIZE_MB=50 to limit SVGZ decompression (PT-13)
- Pin Dockerfile base images by digest
- Sanitize OIDC IdP error and sub claim in audit log
- Sync Docker compose/Dockerfile defaults with env.ts
* feat(a11y): convert all hardcoded aria-labels to i18n keys
Replace 49 hardcoded aria-label="..." strings across 25 files with
their corresponding t.a11y.* and t.common.* i18n references. Add
useTranslation import and hook call to 15 components that lacked it.
Zero hardcoded aria-labels remain in the codebase.
* feat(a11y): add aria-labels to icon-only buttons, aria-hidden on decorative icons, sr-only status text
* feat(a11y): add aria-live regions for processing status announcements
* feat(a11y): add skip-nav link, route announcer, main content landmark, and page h1 elements
* feat(a11y): add prefers-reduced-motion support, preserve functional spinners
* feat(a11y): add useFocusTrap hook for modal focus management
* feat(a11y): add focus trapping and dialog roles to all modals
* feat(a11y): add toggle switch roles, form labels, and error association
* fix(a11y): fix contrast failures, touch targets, and add nav landmark to sidebar
* fix(a11y): add role=switch to remaining toggle buttons found in verification sweep
- Fix selective metadata stripping (P1): use Sharp's keepExif()/keepIccProfile()
instead of broken withMetadata({}) that preserved everything
- Fix meme font mapping (P1): add ArchivoBlack and ComicNeue fonts, map
arial-black and comic-sans to correct TTF files instead of Anton
- Fix meme contentType (P2): detect actual output format from Sharp metadata
instead of hardcoding image/png
- Fix info/text-overlay/color-palette i18n (P2): wire up existing translation
keys that were imported but never used
- Fix info and color-palette displayMode (P2): change from before-after to
no-comparison since neither tool produces a processed image
- Add missing i18n keys across all 21 locales
- Update displayMode test assertions
* fix(security): harden SVG sanitizer, rate limiting, and analytics defaults
- SVG: add control-char stripping in href values to block whitespace/null-byte
obfuscated javascript: URIs; block <feImage> with external href (SSRF via
SVG filter primitives); expand test suite to 32 inline bypass payloads
- Rate limiting: add per-route limits on tool endpoints (60/min) and batch
(20/min); fix compose files defaulting RATE_LIMIT_PER_MIN to 0 which mapped
to 50,000 in code; simplify rate limit registration to use env.ts default
- Analytics: default ANALYTICS_ENABLED to false so self-hosters do not
unknowingly send telemetry
- Docker: add --max-time 5 and -s flags to compose healthcheck curl commands
* fix: remove stale login limit bypass, reduce error log noise, clean up fixtures
- Fix getLoginAttemptLimit() ignoring LOGIN_ATTEMPT_LIMIT when global rate
limit exceeded 1000/min, which let the global limit override the stricter
per-route login brute-force protection
- Downgrade rate limit 429 responses from error to warn level in the global
error handler to avoid log noise and unnecessary Sentry reports
- Log 4xx client errors at warn level instead of error level
- Remove 11 orphaned SVG attack fixture files replaced by inline test payloads
- Apply biome formatting fixes to web app components
- Add required S3 credentials to loadEnv test when STORAGE_MODE=s3
- Update bento-grid test tool counts from 52 to 53 for html-to-image