Files
semantic-release-bot 6aacb4f3a9 chore(release): 2.2.0 [skip ci]
# [2.2.0](https://github.com/snapotter-hq/snapotter/compare/v2.1.0...v2.2.0) (2026-07-29)

### Bug Fixes

* **a11y:** focus indicators meet the 3:1 non-text contrast bar ([#574](https://github.com/snapotter-hq/snapotter/issues/574)) ([6339370](https://github.com/snapotter-hq/snapotter/commit/63393700939e34ad3d847043b03728e3c2907445)), closes [#A85518](https://github.com/snapotter-hq/snapotter/issues/A85518) [#F0A766](https://github.com/snapotter-hq/snapotter/issues/F0A766)
* **a11y:** WCAG AA contrast retune for the Otter Orange palette ([#567](https://github.com/snapotter-hq/snapotter/issues/567)) ([5102262](https://github.com/snapotter-hq/snapotter/commit/51022628dc19d8a03525bab98473f3c23b1a2709)), closes [#E07832](https://github.com/snapotter-hq/snapotter/issues/E07832) [#1A1814](https://github.com/snapotter-hq/snapotter/issues/1A1814)
* **ai-bridge:** surface sidecar exit reasons in Sentry via SafeError ([#538](https://github.com/snapotter-hq/snapotter/issues/538)) ([55e1e95](https://github.com/snapotter-hq/snapotter/commit/55e1e95f20792cae4f1f2257bafe839b83332c93))
* **ai-bundles:** stop CPU onnxruntime from clobbering onnxruntime-gpu ([#544](https://github.com/snapotter-hq/snapotter/issues/544)) ([c8629c9](https://github.com/snapotter-hq/snapotter/commit/c8629c9d22b455b6deac206e3816ae0f730f06c6)), closes [#490](https://github.com/snapotter-hq/snapotter/issues/490)
* **ai:** advance the progress bar during upscale and background removal ([#608](https://github.com/snapotter-hq/snapotter/issues/608)) ([e56edc6](https://github.com/snapotter-hq/snapotter/commit/e56edc659f742430798104b52a08806a8d8fbff2)), closes [#591](https://github.com/snapotter-hq/snapotter/issues/591)
* **ai:** warn that upscale and background removal are slow without a GPU ([#605](https://github.com/snapotter-hq/snapotter/issues/605)) ([d43208b](https://github.com/snapotter-hq/snapotter/commit/d43208b85e1ba1f0ac687970b8fb52ca1738ae15)), closes [#591](https://github.com/snapotter-hq/snapotter/issues/591)
* **api:** contain library stored-name path traversal ([#600](https://github.com/snapotter-hq/snapotter/issues/600)) ([4333432](https://github.com/snapotter-hq/snapotter/commit/43334324c446c53eb1dc2f8ef14cbecca4e2a676))
* **api:** enforce job ownership on cancel endpoint ([#599](https://github.com/snapotter-hq/snapotter/issues/599)) ([577d74b](https://github.com/snapotter-hq/snapotter/commit/577d74bdb134d9a7d02c27ba976731839d071e63))
* **api:** gate every tool endpoint and stop ZIP streams failing quietly ([#646](https://github.com/snapotter-hq/snapotter/issues/646)) ([2d8b57c](https://github.com/snapotter-hq/snapotter/commit/2d8b57c57fad4e1d98ab7eb327198809aa64bd09)), closes [#645](https://github.com/snapotter-hq/snapotter/issues/645) [#643](https://github.com/snapotter-hq/snapotter/issues/643) [#645](https://github.com/snapotter-hq/snapotter/issues/645)
* **api:** wait for Postgres and Redis at startup instead of crash-looping ([#537](https://github.com/snapotter-hq/snapotter/issues/537)) ([4ac89fe](https://github.com/snapotter-hq/snapotter/commit/4ac89fe6505e50645174e8de5fcdc40c46420cc4))
* **audio:** expose sample rate setting in Convert Audio ([#561](https://github.com/snapotter-hq/snapotter/issues/561)) ([d4eaa65](https://github.com/snapotter-hq/snapotter/commit/d4eaa655b24236da5633006871415afbf0c92d08)), closes [#558](https://github.com/snapotter-hq/snapotter/issues/558)
* **auth:** close the MFA policy lockout and add self-service enrollment ([#531](https://github.com/snapotter-hq/snapotter/issues/531)) ([190d4c2](https://github.com/snapotter-hq/snapotter/commit/190d4c2a002c6d3d240ff18480e37217fcbeae12)), closes [#529](https://github.com/snapotter-hq/snapotter/issues/529) [#515](https://github.com/snapotter-hq/snapotter/issues/515)
* **auth:** give OIDC/SAML logins a real MFA challenge instead of a hard block ([#536](https://github.com/snapotter-hq/snapotter/issues/536)) ([bbfcbe9](https://github.com/snapotter-hq/snapotter/commit/bbfcbe9c8212afb244bb2738a6e3643d06dcee68)), closes [#533](https://github.com/snapotter-hq/snapotter/issues/533)
* **background-removal:** surface failures with a diagnosable SafeError ([#535](https://github.com/snapotter-hq/snapotter/issues/535)) ([43ddf96](https://github.com/snapotter-hq/snapotter/commit/43ddf96ccf7baf94416050ec6229efca68124679))
* **ci:** repair the chronically-failing nightly workflow ([#624](https://github.com/snapotter-hq/snapotter/issues/624)) ([44f5aea](https://github.com/snapotter-hq/snapotter/commit/44f5aea3268f022641832af4b8c60cbd2d5e2c7e))
* **compress-pdf:** land close to the target size, honestly ([#522](https://github.com/snapotter-hq/snapotter/issues/522)) ([7d938af](https://github.com/snapotter-hq/snapotter/commit/7d938af1f9e601238fd49af4c2cd157d16616266))
* **deps:** patch 4 HIGH/CRITICAL transitive CVEs (fast-uri, svgo, sharp, tar) ([#619](https://github.com/snapotter-hq/snapotter/issues/619)) ([10a2aab](https://github.com/snapotter-hq/snapotter/commit/10a2aabe589b5afd470f6c47ccdb1bf8bca15c02))
* **doc-engine:** guard sidecar JSON parsing against non-JSON stdout ([#532](https://github.com/snapotter-hq/snapotter/issues/532)) ([a2cb1a8](https://github.com/snapotter-hq/snapotter/commit/a2cb1a8261b2669ae7e656a418999b70a37f6b4f))
* **docker:** harden Postgres readiness checks in compose and startup ([#595](https://github.com/snapotter-hq/snapotter/issues/595)) ([4ba7503](https://github.com/snapotter-hq/snapotter/commit/4ba7503f15a4444c4937576dbcadafdb19a8848d)), closes [#592](https://github.com/snapotter-hq/snapotter/issues/592)
* **docs:** keep the nav within the viewport on tablets and laptops ([#570](https://github.com/snapotter-hq/snapotter/issues/570)) ([69f72a6](https://github.com/snapotter-hq/snapotter/commit/69f72a6c712512e8489b23bcf78a233d872d897c)), closes [#556](https://github.com/snapotter-hq/snapotter/issues/556)
* **docs:** keep the translated locale trees out of the search index ([#662](https://github.com/snapotter-hq/snapotter/issues/662)) ([42e1dc9](https://github.com/snapotter-hq/snapotter/commit/42e1dc9799f60c7dde46b9485e5f37a5a29630ae))
* **docs:** localize the docs homepage, nav, and sidebar chrome across 20 languages ([#547](https://github.com/snapotter-hq/snapotter/issues/547)) ([9247947](https://github.com/snapotter-hq/snapotter/commit/92479477042740d7026de9b9bb3c71eeb0668231))
* **download:** ask reverse proxies not to buffer file downloads ([#604](https://github.com/snapotter-hq/snapotter/issues/604)) ([89d7585](https://github.com/snapotter-hq/snapotter/commit/89d75853f45c98d6e9cae661dbda02bc8285009b)), closes [#590](https://github.com/snapotter-hq/snapotter/issues/590)
* **download:** reset the socket when a stream is shorter than Content-Length ([#617](https://github.com/snapotter-hq/snapotter/issues/617)) ([0467e87](https://github.com/snapotter-hq/snapotter/commit/0467e87bfe410b313fa21d9758f8c162b12113a6)), closes [#590](https://github.com/snapotter-hq/snapotter/issues/590) [#590](https://github.com/snapotter-hq/snapotter/issues/590) [#590](https://github.com/snapotter-hq/snapotter/issues/590)
* **editor:** repair rotate/flip/resize, levels/curves, filters, and layer lock ([#597](https://github.com/snapotter-hq/snapotter/issues/597)) ([a6bce68](https://github.com/snapotter-hq/snapotter/commit/a6bce6825ae27890951becf7c858d4626c513714))
* enforce role authority for user management ([#616](https://github.com/snapotter-hq/snapotter/issues/616)) ([1f8a42e](https://github.com/snapotter-hq/snapotter/commit/1f8a42e54822142132270df1aefa768f4626613f))
* enforce settings authority boundaries ([#618](https://github.com/snapotter-hq/snapotter/issues/618)) ([44d8109](https://github.com/snapotter-hq/snapotter/commit/44d8109486aa6efd9383e573f0a36deb4ffda460))
* **erase-object:** crop-based HD inpainting to remove ghosting and blur ([#501](https://github.com/snapotter-hq/snapotter/issues/501)) ([380419d](https://github.com/snapotter-hq/snapotter/commit/380419dd0603693ad542082bd6197e6505f9b1e9)), closes [#491](https://github.com/snapotter-hq/snapotter/issues/491) [hi#res](https://github.com/hi/issues/res) [#141](https://github.com/snapotter-hq/snapotter/issues/141)
* **files:** decode CLI-decoded formats before URL-import preview generation ([#637](https://github.com/snapotter-hq/snapotter/issues/637)) ([841f47f](https://github.com/snapotter-hq/snapotter/commit/841f47f6ca25e79dc56dc1e735afa37f02023f99)), closes [#634](https://github.com/snapotter-hq/snapotter/issues/634)
* **files:** store null instead of 0x0 for undecoded upload dimensions ([#636](https://github.com/snapotter-hq/snapotter/issues/636)) ([511633f](https://github.com/snapotter-hq/snapotter/commit/511633fa1c76f00fe9c4e2a0935a02b5601cae6a)), closes [#635](https://github.com/snapotter-hq/snapotter/issues/635)
* give remove-background job timeouts an actionable failure message ([#518](https://github.com/snapotter-hq/snapotter/issues/518)) ([58121f2](https://github.com/snapotter-hq/snapotter/commit/58121f205f7ae2b34b3d789c80db37c8bf0950bf)), closes [#494](https://github.com/snapotter-hq/snapotter/issues/494)
* **help:** render the help dialog from i18n instead of hardcoded English ([#647](https://github.com/snapotter-hq/snapotter/issues/647)) ([2848dd0](https://github.com/snapotter-hq/snapotter/commit/2848dd0e53d8a7c1e19ee82c1a1f2d485380d356)), closes [#644](https://github.com/snapotter-hq/snapotter/issues/644)
* honor unlimited processing timeout ([#638](https://github.com/snapotter-hq/snapotter/issues/638)) ([025851b](https://github.com/snapotter-hq/snapotter/commit/025851beefaac6f8d12c1dbcdb69276965072ac9))
* **image-tools:** surface Sharp encode failures instead of "Error: Error" ([#534](https://github.com/snapotter-hq/snapotter/issues/534)) ([9cccbc9](https://github.com/snapotter-hq/snapotter/commit/9cccbc957681f8d12547e87be0e335f98e789cb7))
* **image:** decode real iPhone HEIC files instead of rejecting them at validation ([#631](https://github.com/snapotter-hq/snapotter/issues/631)) ([098ed50](https://github.com/snapotter-hq/snapotter/commit/098ed50d0693ba181fae6f934bf427079e1f8e9f)), closes [#622](https://github.com/snapotter-hq/snapotter/issues/622)
* **image:** image-to-pdf presets no longer 404 on 2+ files ([#633](https://github.com/snapotter-hq/snapotter/issues/633)) ([330cf55](https://github.com/snapotter-hq/snapotter/commit/330cf559e00b6e5f1ca8df199cabee4c0fa650d0)), closes [#627](https://github.com/snapotter-hq/snapotter/issues/627)
* **jobs:** classify BullMQ stall (UnrecoverableError) as operational ([#610](https://github.com/snapotter-hq/snapotter/issues/610)) ([e537cb0](https://github.com/snapotter-hq/snapotter/commit/e537cb04013d7bf4fd0fb125fb72f42f5a51917f))
* **jobs:** make timeout messages tool-agnostic and CPU-aware ([#596](https://github.com/snapotter-hq/snapotter/issues/596)) ([37c915c](https://github.com/snapotter-hq/snapotter/commit/37c915c3da6b2183b0befe1521a643bb36edcce6)), closes [#591](https://github.com/snapotter-hq/snapotter/issues/591)
* **landing-i18n:** commit missed landing-seo re-translation (remove.bg comparison) ([b8c3700](https://github.com/snapotter-hq/snapotter/commit/b8c3700c15333b2eb328cab0979f8d943c15d7ab))
* **landing,docs:** use build-time GitHub star count, drop per-page api.github.com fetch ([#560](https://github.com/snapotter-hq/snapotter/issues/560)) ([54073a7](https://github.com/snapotter-hq/snapotter/commit/54073a7c501788dea49f77f6e94bdebb9b8f0f65))
* **landing:** derive conversion-preset copy from real format differences ([#663](https://github.com/snapotter-hq/snapotter/issues/663)) ([a75a22d](https://github.com/snapotter-hq/snapotter/commit/a75a22dd3ff8e675002a13da0ec12d00f91136c8))
* **landing:** keep mixed-case locale casing in emitted URLs ([#562](https://github.com/snapotter-hq/snapotter/issues/562)) ([67f5434](https://github.com/snapotter-hq/snapotter/commit/67f54347b2ca711f40495fa7fcb05e132ea8f3da)), closes [#554](https://github.com/snapotter-hq/snapotter/issues/554)
* **landing:** link English-only tool-detail and self-hosted pages to un-prefixed URLs ([#553](https://github.com/snapotter-hq/snapotter/issues/553)) ([6ecc598](https://github.com/snapotter-hq/snapotter/commit/6ecc598fc4fc8fa6da5db9d9d0c66e53d2f2376d))
* **landing:** open Product dropdown below the navbar bottom line ([#571](https://github.com/snapotter-hq/snapotter/issues/571)) ([e3a01b6](https://github.com/snapotter-hq/snapotter/commit/e3a01b6be6fa077fa00c6c7245be7ba18b6e913c))
* **landing:** rework footer badge/switcher layout ([#514](https://github.com/snapotter-hq/snapotter/issues/514)) ([74e7d23](https://github.com/snapotter-hq/snapotter/commit/74e7d23abad924f04b348f00edf34e67188c4f2e))
* **landing:** stop mangling #hash fragments in localized links ([#516](https://github.com/snapotter-hq/snapotter/issues/516)) ([5bd0522](https://github.com/snapotter-hq/snapotter/commit/5bd052286c5a7920161b21cb791cc122fe3a1616)), closes [#hash](https://github.com/snapotter-hq/snapotter/issues/hash)
* make OCR portable and reliable across AMD64 and ARM64 ([#519](https://github.com/snapotter-hq/snapotter/issues/519)) ([991c981](https://github.com/snapotter-hq/snapotter/commit/991c981529c81ebb719199aba084db4c2d9a7c6f))
* **ocr:** unblock and harden accurate-OCR install ([#552](https://github.com/snapotter-hq/snapotter/issues/552)) ([bda4db3](https://github.com/snapotter-hq/snapotter/commit/bda4db3f358eebd659a1f8b7892112061a82b000))
* **pdf:** flag scanned PDFs in pdf-to-text and serve text as UTF-8 ([#603](https://github.com/snapotter-hq/snapotter/issues/603)) ([7d37f6e](https://github.com/snapotter-hq/snapotter/commit/7d37f6e6f5aa68aa5954182d76bb6ccf1c6b0649)), closes [#589](https://github.com/snapotter-hq/snapotter/issues/589)
* **pdf:** pdf-to-image presets no longer 404 on 2+ files ([#643](https://github.com/snapotter-hq/snapotter/issues/643)) ([a713795](https://github.com/snapotter-hq/snapotter/commit/a7137958a158309ff8128490de96313e517ae554)), closes [#627](https://github.com/snapotter-hq/snapotter/issues/627) [#633](https://github.com/snapotter-hq/snapotter/issues/633) [#632](https://github.com/snapotter-hq/snapotter/issues/632)
* **pdf:** restore downloads on PDF conversion preset pages ([#629](https://github.com/snapotter-hq/snapotter/issues/629)) ([e0a7aec](https://github.com/snapotter-hq/snapotter/commit/e0a7aecde8f194b6375747a5a5f8ea4c57053813)), closes [#623](https://github.com/snapotter-hq/snapotter/issues/623)
* **pdf:** stop page tools failing on short and encrypted PDFs ([#594](https://github.com/snapotter-hq/snapotter/issues/594)) ([73df107](https://github.com/snapotter-hq/snapotter/commit/73df1077580904c37d159dafe51a294b250bb074))
* preserve colored blocks in PDF-to-Word ([#500](https://github.com/snapotter-hq/snapotter/issues/500)) ([e7cfc00](https://github.com/snapotter-hq/snapotter/commit/e7cfc00fe1d294256a0a4663797b8a8cdf58d8c0))
* **readme:** self-host the star history chart ([#625](https://github.com/snapotter-hq/snapotter/issues/625)) ([90483c9](https://github.com/snapotter-hq/snapotter/commit/90483c944a4d4c912d3c5e2c09b2ee61bed3d150))
* release QA hardening across processing, media, security, and CI gates ([#649](https://github.com/snapotter-hq/snapotter/issues/649)) ([d10d0f5](https://github.com/snapotter-hq/snapotter/commit/d10d0f544f2a093d2adb13cbd69d54a31c0cbf7a))
* **release:** resolve the release by id, and make the vulnerability gate cover HIGH ([#661](https://github.com/snapotter-hq/snapotter/issues/661)) ([935861b](https://github.com/snapotter-hq/snapotter/commit/935861bced95cd778ea77d5a3741ff1da1a2ffed)), closes [#649](https://github.com/snapotter-hq/snapotter/issues/649)
* **security:** bump Pillow to 12.3.0, fixes 5 disclosed CVEs ([#517](https://github.com/snapotter-hq/snapotter/issues/517)) ([30d36d7](https://github.com/snapotter-hq/snapotter/commit/30d36d7949817751b869916775138dc4fa7a34d2))
* **security:** close the gaps a full 2.0 re-audit left open ([#620](https://github.com/snapotter-hq/snapotter/issues/620)) ([079fcd2](https://github.com/snapotter-hq/snapotter/commit/079fcd2631216147db4b68acbcaca58ac4f93fb4))
* **seo:** emit clean docs URLs and de-index the demo ([#598](https://github.com/snapotter-hq/snapotter/issues/598)) ([e6718ad](https://github.com/snapotter-hq/snapotter/commit/e6718ada719e8931f643e1184aee354d4698c1da))
* **settings:** let admins relax the minimum password length to 1 ([#543](https://github.com/snapotter-hq/snapotter/issues/543)) ([846044a](https://github.com/snapotter-hq/snapotter/commit/846044a463f18f490f7752b0cb6b4b225b107367)), closes [#136](https://github.com/snapotter-hq/snapotter/issues/136)
* **sign-pdf:** surface PDF load failures instead of a blank canvas ([#545](https://github.com/snapotter-hq/snapotter/issues/545)) ([1f4878a](https://github.com/snapotter-hq/snapotter/commit/1f4878ac4df417331a8cff9b8d5ab4da2edc788a))
* **telemetry:** classify environmental database errors as operational ([#540](https://github.com/snapotter-hq/snapotter/issues/540)) ([631d82e](https://github.com/snapotter-hq/snapotter/commit/631d82eaae36a15d401c7408182d52a0754b1e36))
* **telemetry:** data-quality pass (opt-in noise, onboarding split, file_count, OIDC) ([#614](https://github.com/snapotter-hq/snapotter/issues/614)) ([b20bca3](https://github.com/snapotter-hq/snapotter/commit/b20bca3c3c4ef3a63aca6ba420986d49bbeb905b)), closes [hi#level](https://github.com/hi/issues/level)
* **telemetry:** fingerprint stackless uncaught errors so they stop collapsing ([#611](https://github.com/snapotter-hq/snapotter/issues/611)) ([82f5708](https://github.com/snapotter-hq/snapotter/commit/82f5708193984e863b95319e0e0ec8be47e46075))
* **telemetry:** sharpen Sentry signal for v2.1.0 residual defects ([#498](https://github.com/snapotter-hq/snapotter/issues/498)) ([b457596](https://github.com/snapotter-hq/snapotter/commit/b4575966495c1a022154149832aedcd727d411e2))
* **telemetry:** surface AI sidecar and DOMException failure reasons in Sentry ([#612](https://github.com/snapotter-hq/snapotter/issues/612)) ([6a0768b](https://github.com/snapotter-hq/snapotter/commit/6a0768b39da648d3b62b39f2370b97f9ce876da0)), closes [#535](https://github.com/snapotter-hq/snapotter/issues/535)
* **tools:** classify expected input and timeout errors, not bugs ([#539](https://github.com/snapotter-hq/snapotter/issues/539)) ([39b89b9](https://github.com/snapotter-hq/snapotter/commit/39b89b9fbd4f67012b55ecdef35ddf369a3fb874))
* **video:** write faststart mp4/mov output from stabilize-video ([#593](https://github.com/snapotter-hq/snapotter/issues/593)) ([df92f7e](https://github.com/snapotter-hq/snapotter/commit/df92f7ee42b22b5b6cb3434a6b972851388c67ad)), closes [#588](https://github.com/snapotter-hq/snapotter/issues/588)
* **web:** use h-dvh for app shells so mobile tool controls stay reachable ([#559](https://github.com/snapotter-hq/snapotter/issues/559)) ([3f7214b](https://github.com/snapotter-hq/snapotter/commit/3f7214bac22fe392eb7d179752e9c4583e4dbe0e))

### Features

* add landing testimonial wall, unblock the onboarding survey ([#639](https://github.com/snapotter-hq/snapotter/issues/639)) ([5cc0a85](https://github.com/snapotter-hq/snapotter/commit/5cc0a850c68e0af7a427b8442c24c55f6157416e))
* **analytics:** instance census, full capture, richer error context ([#511](https://github.com/snapotter-hq/snapotter/issues/511)) ([e1b8c24](https://github.com/snapotter-hq/snapotter/commit/e1b8c24e5d78153a62629972932a65cd1491ee77))
* clearer, disambiguated tool names across all surfaces ([#520](https://github.com/snapotter-hq/snapotter/issues/520)) ([f858c4c](https://github.com/snapotter-hq/snapotter/commit/f858c4cea00ae7165718509c8a78881fe6fc24fc))
* **docs-i18n:** translate all documentation into 20 languages ([4963ab3](https://github.com/snapotter-hq/snapotter/commit/4963ab3bbd36fe86b856a3be791f192af4582142))
* **erase-object:** add freeform lasso selection mode ([#503](https://github.com/snapotter-hq/snapotter/issues/503)) ([601557e](https://github.com/snapotter-hq/snapotter/commit/601557edaed32f331b5271334923f1c010098d91))
* **erase-object:** optional high-quality diffusion inpainting bundle ([#566](https://github.com/snapotter-hq/snapotter/issues/566)) ([1bac663](https://github.com/snapotter-hq/snapotter/commit/1bac663a2e76c98313a7a56c97231c2bbc1b36f2)), closes [hi#quality](https://github.com/hi/issues/quality) [#141](https://github.com/snapotter-hq/snapotter/issues/141)
* **feedback:** gate onboarding survey on first processing, add prompt lifecycle events ([#615](https://github.com/snapotter-hq/snapotter/issues/615)) ([129e42b](https://github.com/snapotter-hq/snapotter/commit/129e42b95cd9c078eebcb3c52be10e8661dd7903))
* **files:** add save-as-new vs overwrite choice for library file edits ([#564](https://github.com/snapotter-hq/snapotter/issues/564)) ([a23158d](https://github.com/snapotter-hq/snapotter/commit/a23158d968c32e8cdf319225d73bf51120f20cbf)), closes [#495](https://github.com/snapotter-hq/snapotter/issues/495)
* **i18n:** 21-language pipeline, landing/docs/API wiring, landing+API translations ([00b651c](https://github.com/snapotter-hq/snapotter/commit/00b651c9f851a8754cac755f6929ba2eeac8602b))
* **image:** add rounded-square and squircle crop tool ([#602](https://github.com/snapotter-hq/snapotter/issues/602)) ([e7ffb37](https://github.com/snapotter-hq/snapotter/commit/e7ffb37e981c553cf17db88155ac12667f104062)), closes [#601](https://github.com/snapotter-hq/snapotter/issues/601)
* **landing-i18n:** recall a returning visitor's chosen language ([1bc9fe9](https://github.com/snapotter-hq/snapotter/commit/1bc9fe93ec4ca82295e77f2c8068bc700ef94367))
* **landing:** add a live system status indicator to the footer ([#641](https://github.com/snapotter-hq/snapotter/issues/641)) ([d690a6e](https://github.com/snapotter-hq/snapotter/commit/d690a6e26d82f9783cac154faa11f19481902a0e))
* **landing:** add Twelve Tools and Wired Business footer badges ([#512](https://github.com/snapotter-hq/snapotter/issues/512)) ([ce54d06](https://github.com/snapotter-hq/snapotter/commit/ce54d06e797c8f3fe25ed8c00ef42047ddf63882))
* **landing:** move language switcher from navbar to footer ([#513](https://github.com/snapotter-hq/snapotter/issues/513)) ([2dee9ea](https://github.com/snapotter-hq/snapotter/commit/2dee9ead0b1c84c02831c5e92082cd4598b7b8f5))
* **library:** wire save-mode into the five custom-client tool submitters ([#577](https://github.com/snapotter-hq/snapotter/issues/577)) ([1113c76](https://github.com/snapotter-hq/snapotter/commit/1113c761ead67664e4a7120b8bdf1b8e9da52c43))
* **onboarding:** collect install method and friction area in the usage survey ([#499](https://github.com/snapotter-hq/snapotter/issues/499)) ([430b87e](https://github.com/snapotter-hq/snapotter/commit/430b87eda0078c9afe31aa49da1f2293c928a147))
* **resize:** add aspect-ratio proportion presets ([#530](https://github.com/snapotter-hq/snapotter/issues/530)) ([d88999e](https://github.com/snapotter-hq/snapotter/commit/d88999e7a91d65adb37ea4cb3f9f7fe5650ad6c5))
* **search:** start typing anywhere to fill the search box ([#644](https://github.com/snapotter-hq/snapotter/issues/644)) ([0058fc6](https://github.com/snapotter-hq/snapotter/commit/0058fc610f4b88ddf0660889b2ea78bf33a527d1))
* **telemetry:** add a safe input_format tag to worker error reports ([#541](https://github.com/snapotter-hq/snapotter/issues/541)) ([281b4a0](https://github.com/snapotter-hq/snapotter/commit/281b4a06e39756a3a2b981e93d033454eb494c8c))
* **telemetry:** Sentry + PostHog quality pass ([#546](https://github.com/snapotter-hq/snapotter/issues/546)) ([8625143](https://github.com/snapotter-hq/snapotter/commit/86251434b5858c63049c50dda44acb8e281a4cdf))
* **tools:** remove background from animated GIFs (WebP, APNG) ([#502](https://github.com/snapotter-hq/snapotter/issues/502)) ([cb5db59](https://github.com/snapotter-hq/snapotter/commit/cb5db59f77e6b77fd9a575996b8514d6760aaf5b))
2026-07-29 13:08:27 +00:00

160 KiB

2.2.0 (2026-07-29)

Bug Fixes

  • a11y: focus indicators meet the 3:1 non-text contrast bar (#574) (6339370), closes #A85518 #F0A766
  • a11y: WCAG AA contrast retune for the Otter Orange palette (#567) (5102262), closes #E07832 #1A1814
  • ai-bridge: surface sidecar exit reasons in Sentry via SafeError (#538) (55e1e95)
  • ai-bundles: stop CPU onnxruntime from clobbering onnxruntime-gpu (#544) (c8629c9), closes #490
  • ai: advance the progress bar during upscale and background removal (#608) (e56edc6), closes #591
  • ai: warn that upscale and background removal are slow without a GPU (#605) (d43208b), closes #591
  • api: contain library stored-name path traversal (#600) (4333432)
  • api: enforce job ownership on cancel endpoint (#599) (577d74b)
  • api: gate every tool endpoint and stop ZIP streams failing quietly (#646) (2d8b57c), closes #645 #643 #645
  • api: wait for Postgres and Redis at startup instead of crash-looping (#537) (4ac89fe)
  • audio: expose sample rate setting in Convert Audio (#561) (d4eaa65), closes #558
  • auth: close the MFA policy lockout and add self-service enrollment (#531) (190d4c2), closes #529 #515
  • auth: give OIDC/SAML logins a real MFA challenge instead of a hard block (#536) (bbfcbe9), closes #533
  • background-removal: surface failures with a diagnosable SafeError (#535) (43ddf96)
  • ci: repair the chronically-failing nightly workflow (#624) (44f5aea)
  • compress-pdf: land close to the target size, honestly (#522) (7d938af)
  • deps: patch 4 HIGH/CRITICAL transitive CVEs (fast-uri, svgo, sharp, tar) (#619) (10a2aab)
  • doc-engine: guard sidecar JSON parsing against non-JSON stdout (#532) (a2cb1a8)
  • docker: harden Postgres readiness checks in compose and startup (#595) (4ba7503), closes #592
  • docs: keep the nav within the viewport on tablets and laptops (#570) (69f72a6), closes #556
  • docs: keep the translated locale trees out of the search index (#662) (42e1dc9)
  • docs: localize the docs homepage, nav, and sidebar chrome across 20 languages (#547) (9247947)
  • download: ask reverse proxies not to buffer file downloads (#604) (89d7585), closes #590
  • download: reset the socket when a stream is shorter than Content-Length (#617) (0467e87), closes #590 #590 #590
  • editor: repair rotate/flip/resize, levels/curves, filters, and layer lock (#597) (a6bce68)
  • enforce role authority for user management (#616) (1f8a42e)
  • enforce settings authority boundaries (#618) (44d8109)
  • erase-object: crop-based HD inpainting to remove ghosting and blur (#501) (380419d), closes #491 hi#res #141
  • files: decode CLI-decoded formats before URL-import preview generation (#637) (841f47f), closes #634
  • files: store null instead of 0x0 for undecoded upload dimensions (#636) (511633f), closes #635
  • give remove-background job timeouts an actionable failure message (#518) (58121f2), closes #494
  • help: render the help dialog from i18n instead of hardcoded English (#647) (2848dd0), closes #644
  • honor unlimited processing timeout (#638) (025851b)
  • image-tools: surface Sharp encode failures instead of "Error: Error" (#534) (9cccbc9)
  • image: decode real iPhone HEIC files instead of rejecting them at validation (#631) (098ed50), closes #622
  • image: image-to-pdf presets no longer 404 on 2+ files (#633) (330cf55), closes #627
  • jobs: classify BullMQ stall (UnrecoverableError) as operational (#610) (e537cb0)
  • jobs: make timeout messages tool-agnostic and CPU-aware (#596) (37c915c), closes #591
  • landing-i18n: commit missed landing-seo re-translation (remove.bg comparison) (b8c3700)
  • landing,docs: use build-time GitHub star count, drop per-page api.github.com fetch (#560) (54073a7)
  • landing: derive conversion-preset copy from real format differences (#663) (a75a22d)
  • landing: keep mixed-case locale casing in emitted URLs (#562) (67f5434), closes #554
  • landing: link English-only tool-detail and self-hosted pages to un-prefixed URLs (#553) (6ecc598)
  • landing: open Product dropdown below the navbar bottom line (#571) (e3a01b6)
  • landing: rework footer badge/switcher layout (#514) (74e7d23)
  • landing: stop mangling #hash fragments in localized links (#516) (5bd0522), closes #hash
  • make OCR portable and reliable across AMD64 and ARM64 (#519) (991c981)
  • ocr: unblock and harden accurate-OCR install (#552) (bda4db3)
  • pdf: flag scanned PDFs in pdf-to-text and serve text as UTF-8 (#603) (7d37f6e), closes #589
  • pdf: pdf-to-image presets no longer 404 on 2+ files (#643) (a713795), closes #627 #633 #632
  • pdf: restore downloads on PDF conversion preset pages (#629) (e0a7aec), closes #623
  • pdf: stop page tools failing on short and encrypted PDFs (#594) (73df107)
  • preserve colored blocks in PDF-to-Word (#500) (e7cfc00)
  • readme: self-host the star history chart (#625) (90483c9)
  • release QA hardening across processing, media, security, and CI gates (#649) (d10d0f5)
  • release: resolve the release by id, and make the vulnerability gate cover HIGH (#661) (935861b), closes #649
  • security: bump Pillow to 12.3.0, fixes 5 disclosed CVEs (#517) (30d36d7)
  • security: close the gaps a full 2.0 re-audit left open (#620) (079fcd2)
  • seo: emit clean docs URLs and de-index the demo (#598) (e6718ad)
  • settings: let admins relax the minimum password length to 1 (#543) (846044a), closes #136
  • sign-pdf: surface PDF load failures instead of a blank canvas (#545) (1f4878a)
  • telemetry: classify environmental database errors as operational (#540) (631d82e)
  • telemetry: data-quality pass (opt-in noise, onboarding split, file_count, OIDC) (#614) (b20bca3), closes hi#level
  • telemetry: fingerprint stackless uncaught errors so they stop collapsing (#611) (82f5708)
  • telemetry: sharpen Sentry signal for v2.1.0 residual defects (#498) (b457596)
  • telemetry: surface AI sidecar and DOMException failure reasons in Sentry (#612) (6a0768b), closes #535
  • tools: classify expected input and timeout errors, not bugs (#539) (39b89b9)
  • video: write faststart mp4/mov output from stabilize-video (#593) (df92f7e), closes #588
  • web: use h-dvh for app shells so mobile tool controls stay reachable (#559) (3f7214b)

Features

  • add landing testimonial wall, unblock the onboarding survey (#639) (5cc0a85)
  • analytics: instance census, full capture, richer error context (#511) (e1b8c24)
  • clearer, disambiguated tool names across all surfaces (#520) (f858c4c)
  • docs-i18n: translate all documentation into 20 languages (4963ab3)
  • erase-object: add freeform lasso selection mode (#503) (601557e)
  • erase-object: optional high-quality diffusion inpainting bundle (#566) (1bac663), closes hi#quality #141
  • feedback: gate onboarding survey on first processing, add prompt lifecycle events (#615) (129e42b)
  • files: add save-as-new vs overwrite choice for library file edits (#564) (a23158d), closes #495
  • i18n: 21-language pipeline, landing/docs/API wiring, landing+API translations (00b651c)
  • image: add rounded-square and squircle crop tool (#602) (e7ffb37), closes #601
  • landing-i18n: recall a returning visitor's chosen language (1bc9fe9)
  • landing: add a live system status indicator to the footer (#641) (d690a6e)
  • landing: add Twelve Tools and Wired Business footer badges (#512) (ce54d06)
  • landing: move language switcher from navbar to footer (#513) (2dee9ea)
  • library: wire save-mode into the five custom-client tool submitters (#577) (1113c76)
  • onboarding: collect install method and friction area in the usage survey (#499) (430b87e)
  • resize: add aspect-ratio proportion presets (#530) (d88999e)
  • search: start typing anywhere to fill the search box (#644) (0058fc6)
  • telemetry: add a safe input_format tag to worker error reports (#541) (281b4a0)
  • telemetry: Sentry + PostHog quality pass (#546) (8625143)
  • tools: remove background from animated GIFs (WebP, APNG) (#502) (cb5db59)

2.1.0 (2026-07-10)

Bug Fixes

  • demo: boot to dashboard, sample-data notice, robust mobile editor icon (#464) (a94b69b)
  • demo: point banner "Self-host SnapOtter" link at the docs guide (#466) (463ccff)
  • demo: populate admin data, fix settings crash and mobile editor icon (#463) (7329bc6)
  • error-only Sentry telemetry, storm-proof capture, and crash fixes (#476) (ae6a4c8)
  • landing: clarify OIDC is free, SAML is enterprise on pricing (#461) (c2c9a9e)
  • landing: fix top nav overflow and text overlap (#473) (ffeacd4)
  • landing: green the landing e2e suite (#470) (10ae6d1)
  • landing: highlight Open Source as Most Popular tier (#462) (e468cef)
  • landing: reposition residual meta framing and demote homepage tool count (#471) (958c3e8)
  • reliable, self-healing AI feature-bundle installs (#472) (a731c3d)
  • restyle sponsor button (37a3cfc)
  • reword sponsor button to "Support us" (#468) (331e3bf)
  • update python protobuf dependency (780624e)

Features

  • demo: populate the Files library with sample files (#465) (a6e8f75)
  • landing: add dismissible 2.0 launch banner (ea7a671)
  • landing: add Product dropdown to nav (#475) (3d1744a)
  • landing: restore Developers nav link, swap out Features anchor (#474) (a08afbc)
  • reposition to self-hosted file-processing infrastructure (#469) (af011d5)

2.0.0 (2026-07-07)

  • feat!: SnapOtter 2.0.0 (6205525), closes #254 #261
  • feat(db)!: SnapOtter 2.0 phase 1 foundation: postgres, migrator, compose stack (#216) (1c724d5)

Bug Fixes

  • adopt sharp 0.35.2+ by centralizing the FormatEnum key type (#362) (9052da2)
  • ai-bundles: lock the numpy-1.x ABI closure so the OCR bundle can't strand scipy (67c5566)
  • ai-bundles: lock the numpy-1.x ABI closure so the OCR bundle can't strand scipy (#437) (fd39f66)
  • ai-bundles: repair bundle build + publish pipeline (deepsafe repo, CPU provider, manifest) (3b50bcd)
  • ai: broaden SSRF pre-scan regex to cover srcset, poster, formaction, @import (5397f9b)
  • ai: detect a paddle-only GPU so OCR uses PaddleOCR-GPU not Tesseract (#439) (7cd514d)
  • ai: enforce the feature gate on the per-request fallback path (#331) (7a70aff), closes #327
  • ai: gate AI tools on per-framework GPU detection, not a shared boolean (#445) (36dde9a)
  • ai: pin protobuf<5 on arm64 so mediapipe face landmarks work (#417) (2c2fb65)
  • ai: pin rembg to 2.0.69 to keep numpy<2 compatibility (3726335)
  • ai: surface actionable fix for libGL.so.1 missing on headless installs (7c70c60)
  • ai: update arm64 bundle sha256/size after protobuf<5 rebuild (#421) (2a36b3d), closes #417
  • allow reinstall of AI bundles with broken model files (#214) (27a56c7)
  • always show NonNativePreview for non-native formats, even after processing (abaae18)
  • analytics: harden analytics opt-out and feedback surfaces (#423) (23efce9)
  • api: batch user-files delete to eliminate N+1 queries (e2c5714)
  • api: decode RAW via LibRaw first so DNG processes at full resolution (#289) (#290) (3d9ff1e)
  • api: drop app-logger import from media-input; update stale errors mock (c483897)
  • api: fix batch user-files delete recursive CTE query (82991b6)
  • api: isolate the factory validation scratch dir from the worker's (7a205ee)
  • api: log only genuine processing faults at error level (965501a)
  • api: make OpenAPI spec ASCII-only so Schemathesis can load it (#344) (c2ae334)
  • api: narrow friendlyError matching to avoid collapsing valid messages (6220885)
  • api: propagate lenient structural-validation flag to batch + pipeline (e52e0bb), closes #244
  • api: reject non-PDF inputs in pdf-to-image (37b9c6d)
  • api: respect RATE_LIMIT_PER_MIN for tool routes (#272) (ce02ce1), closes #280
  • api: return user-safe processing errors, keep raw stderr in logs (4af4bfa)
  • api: section override for backwards-compat alias routes (adjust-colors) (fc205c7)
  • api: stop leaking raw ffprobe stderr in media validation errors (3fc4149)
  • api: support sharp 0.35 types (6f85b3d)
  • api: wrap role rename and delete in transactions (b564932)
  • apply processedFileName fallback everywhere processedFilename is used (857aa75)
  • audio: low-samplerate ogg encode + post-2.0 QA hygiene (19d9ed1)
  • benchmark: use section-prefixed tool URLs for 2.0 route scheme (76fc695)
  • build script venv handling and lint fixes (b1e94bd)
  • cache useSyncExternalStore snapshot to prevent infinite re-render (f68fcb8)
  • ci: address spec review findings in verify-bundle.sh (4b5b351)
  • ci: deploy landing from dist, not the stale Next.js out path (#240) (44bfca1)
  • ci: grant ai-bundles reusable call its required token scopes (03c1a5e)
  • ci: harden smoke tests against set -e and fix parameter issues (efac88c)
  • ci: resolve pre-existing failures making main red (#250) (622c9f9), closes #249 246/#248
  • ci: revert rembg to 2.0.62 (2.0.75 requires numpy>=2.3) (3b8d529)
  • clean file info cards for non-native video/media formats on tool page (511e941)
  • clear file store when navigating between tools (f32b3bd)
  • correct SAML idpCert property name for @node-saml/node-saml v5 (b9dac59)
  • critical first-login soft-lock in usage survey overlay (#392) (ca076f9)
  • deps: close js-yaml DoS alert + document rembg non-reachability (#286) (5d5117a)
  • deps: drop undici override (broke jsdom@29) (5662532)
  • deps: patch Dependabot security alerts (8792080)
  • doc-engine: treat qpdf exit code 3 (warnings) as success, not failure (2a2151d)
  • docker: copy patches/ before pnpm install so cold builds succeed (#300) (f74f648)
  • docker: make storage writable under non-root/foreign UIDs (TrueNAS, OpenShift) (#299) (1fec971), closes #230
  • docker: make venv bootstrap upgrade-aware with pip-freeze stamp (39543d6), closes #85
  • docker: patch OS + pip image CVEs, document accepted Trivy residuals (#288) (c203267)
  • docker: repair copied AI venv paths (#390) (7e01d36), closes #127 #127
  • docker: restore Postgres/Redis in GPU compose stack + pause image publishing (9b64a96)
  • e2e,landing: robust path escaping (CodeQL) + unique file-tools card (a6837b6)
  • e2e: disable Astro Dev Toolbar during landing e2e tests (2927e0d)
  • e2e: wait for post-login redirect before forcing navigation (#341) (5b75d81), closes #340
  • editor: apply layer effects + object flip, add Beta badge, repair e2e specs (3120e67), closes #259
  • editor: capture document pixels without the zoom/pan transform (#259) (81e16d7), closes #258
  • editor: fill canvas viewport, fix black rulers, add resizable panel (#258) (063a2e4)
  • enforce file type filtering using tool's acceptedInputs (adfa532)
  • enterprise: SCIM token generation, GDPR job cancellation, MFA replay, config redaction, encryption validation, SCIM rate limit (29dd675)
  • enterprise: ship enterprise package in prod image + S3, analytics, tracing, queue fixes (#342) (8f4235d), closes #82
  • fetch settings on home page mount so tools are visible (cf543f6)
  • file library upload accepts all file types, not just images (6bcee1e)
  • files: record the source tool in toolChain on Save to Files (#435) (47a60e7)
  • first-run QA sweep of the single-container image (#413) (bf417a5)
  • GPU deployment robustness (6 fixes from end-to-end testing on an RTX 4070) (#334) (35e18d8)
  • grey out incompatible files in library instead of hiding them (3a5d55c)
  • handle non-image modalities across uploads, previews, and filenames (#255) (8eee17a)
  • harden against three production Sentry crashes (#328) (8952e9b)
  • harden Docker image and async job responses (f3342a1)
  • harden install queue/dispatcher lifecycle and repair review-sweep regressions (#395) (b4375e5), closes #388 #390 #391 #392 #393 #394 #392
  • i18n: complete and correct Italian translation (#231) (#298) (c0a8b36)
  • i18n: complete the Italian feedback translations (#426) (3ae48cc), closes #425
  • i18n: complete the Italian translation update (#438) (#450) (0fafeb2)
  • i18n: restore accents in Italian loading-message arrays (#322) (29fcc87), closes #298
  • i18n: translate Arabic (ar) UI strings (#314) (ab37505)
  • i18n: translate Brazilian Portuguese (pt-BR) UI strings (#307) (3900350)
  • i18n: translate Dutch (nl) UI strings (#309) (d036ff6)
  • i18n: translate French (fr) UI strings (#306) (fe5c7c8)
  • i18n: translate German (de) UI strings (#308) (4de24b8)
  • i18n: translate Hindi (hi) UI strings (#316) (00c89e4)
  • i18n: translate Indonesian (id) UI strings (#318) (8a8a4f9)
  • i18n: translate Japanese (ja) UI strings (#304) (d8b037c)
  • i18n: translate Korean (ko) UI strings (#305) (e7b412f)
  • i18n: translate Polish (pl) UI strings (#312) (7ce9c64)
  • i18n: translate Russian (ru) UI strings (#311) (eb9a14a)
  • i18n: translate Simplified Chinese (zh-CN) UI strings (#302) (26d8a06)
  • i18n: translate Spanish (es) UI strings (#301) (b3ff8ac)
  • i18n: translate Swedish (sv) UI strings (#310) (c4ce5f9)
  • i18n: translate Thai (th) UI strings (#319) (5a6368d)
  • i18n: translate Traditional Chinese (zh-TW) UI strings (#303) (de4d2ed)
  • i18n: translate Turkish (tr) UI strings (#315) (8c1c2c3)
  • i18n: translate Ukrainian (uk) UI strings (#313) (6ee1b0f)
  • i18n: translate Vietnamese (vi) UI strings (#317) (4702721)
  • image-engine: support sharp 0.35 types (2137be4)
  • jobs: pre-warm QueueEvents to kill first-sync-wait flake (#285) (dba8a85)
  • jobs: strip internal paths from all worker SSE error frames (fc718c1)
  • landing: add www redirect, noindex JS chunks, and website badge (47b6984)
  • lint: biome-format tool-factory and json-xml to green apps/api lint (#252) (7865339), closes #251
  • lint: clear remaining biome errors (unused code, optional chains, non-null assertions, effect deps) (19dc6ba)
  • lint: make husky hook executable; rename backend useS3 to isS3Enabled (clears 17 false-positive useHookAtTopLevel) (7561f2a)
  • lint: resolve #280 Lint failures (route formatting + landing import sort) (6e1b9cd)
  • make search bar full-width to align with tabs and grid (207c1c3)
  • media: encode gif-to-video WebM as yuv420p (e96c314)
  • migrator: correct and harden the 1.x to 2.0 SQLite import (#434) (dadf766)
  • nightly: de-flake matrix timeouts, exclude browser tool from fuzz (#349) (bbad953), closes #347
  • nightly: qpdf in test image, NUL-byte settings, AI sub-path fuzz exclude (#348) (078743d), closes #346 #346
  • normalize-audio: preserve source sample rate after loudnorm (#248) (1548d47)
  • offline CodeFormer face-enhance (ship RealESRGAN_x2plus in upscale-enhance bundle) (#433) (cf884b5)
  • passport-photo: require the face-detection bundle, not just background-removal (#329) (32c1192), closes #327 #327
  • PDF tool QA sweep - library auto-save versioning, AI fileId threading, modality polish (#251) (08961fc)
  • post-2.0 audit bug fixes (404 route, worker logging, outpaint gate, pandoc path) (2bd3e23)
  • prevent double scrollbar by locking html/body overflow (914ff1b)
  • preview generation works for processed results too (b93dc95)
  • QA sweep - tool routes, security, i18n, a11y, + AI bundle install hardening (#393) (b37faed), closes hi#resolution hi#severity
  • reassign 4 tools to correct display modes (619f61b)
  • release-acceptance QA follow-ups (upload crash, scipy ABI conflict, rate limit, OCR fallback) (#458) (60d01ab), closes #413 #437
  • remove all legacy redirects from routes (fd26fa3)
  • remove automatic third-party egress of user data + optional strict offline mode (OSM tiles, Scalar fonts, editor fonts, AI model downloads) (#422) (6e3a14e)
  • remove double scrollbar on home page (ae95976)
  • remove duplicated 1.x migration callout in README (#456) (2a899ef), closes #448 #454
  • remove redundant Getting Started section from home page (287f6f1)
  • repair docker validation QA tooling, dispatcher crash-accounting, and image-enhancement RAW hang (#391) (bd1838e)
  • repair URL import (DNS-pinned fetch on Node 22 + non-image modalities) (#246) (8f6312c)
  • resolve 18 QA-discovered bugs across tools, previews, and the AI pipeline (#242) (d8cf979)
  • resolve 6 bugs from enterprise audit (SIEM cursor, legal hold join, SCIM role, GDPR self-purge, export OOM, quota check) (7f62b1b)
  • resolve hardcoded /app paths and loosen mediapipe pin for native installs (60e3ac2), closes community-scripts/ProxmoxVE#14720
  • resolve Sharp 0.35.1 and BullMQ type incompatibilities after dep bumps (b76dc68)
  • Save to Files shows green success state with checkmark after saving (f4061fe)
  • security: basename-sanitize file-preview paths (CodeQL js/path-injection) (7a3b4e6)
  • security: close file-preview path-injection + tighten subtitle detection (c1cd871)
  • security: close remaining high-severity CodeQL alerts (bdadb84), closes hi#severity
  • security: explicit per-route rate limits (CodeQL js/missing-rate-limiting) (ae4fc1d)
  • security: harden auth and outbound fetches (c6319cf)
  • security: harden rate limits, Redis auth, resource caps, and error sanitization (d612264)
  • security: numeric CIDR matching for IPv6 SSRF allow/deny (f75cc32)
  • send auth token with preview generation request (6090688)
  • set a writable HOME for the app user so PaddleOCR works in non-root deployments (#430) (e0dbf2a)
  • settings dialog and settings API correctness bugs (8e9452e)
  • show all tools on All tab, remove Popular and Browse sections (b166f47)
  • show image viewer for video-to-gif/webp results instead of broken video player (90acd5b)
  • show modality starting points in landing command center (#387) (852f6ce)
  • show tool-specific accepted formats in dropzone, remove privacy note (5241ccd)
  • sort enterprise exports for Biome lint compliance (3b7f44e)
  • stamp SnapOtter as Producer on generated PDFs (#416) (8b3f1e6)
  • sync demo theme with app (f6f7b5a)
  • test server registration gaps, Redis subscriber cleanup, atomic settings upsert (954cfb0)
  • test: align analytics-env test with ANALYTICS_ENABLED=true default (96764ec)
  • test: mock db/index.js in unit tests that import API modules (5b3b3c7)
  • test: repair integration suite after analytics column/endpoint removal (#340) (6917a8b), closes #336
  • test: resolve CI failures from the overhaul (34b006d)
  • tests: section-prefix tool API URLs across overhauled suite (d4dc2ea), closes #280
  • test: update import paths for cleanup.test.ts after move to integration (78679c5)
  • tools: honest content-type for edit-metadata pass-through (#350) (88af8d4)
  • tools: surface chars count in pdf-to-text result payload (3c44335)
  • top nav respects dark mode theme (43b1901)
  • ui: constrain preview dropzone height in pipeline builder (931e15a)
  • ui: show repair UI when AI bundle models are broken (#214) (edea82b)
  • update privacy policy to reference PostgreSQL instead of SQLite (5af1ac4)
  • use media-player for all video/audio tools that had no-comparison or side-by-side (69300b5)
  • use processedFileName fallback for non-native format detection after processing (14ded6f)
  • validate non-image inputs by modality (batch + pipeline) (#244) (03e7123)
  • web: add modality to fuse search keys, merge docs+files in fullscreen grid (3114323)
  • web: point tool keyboard shortcuts at section routes (0689ae5)
  • web: resolve feature install status sync and mutual exclusivity (#214) (492da82)
  • web: restore preview panel rendering for all file types (1181b1f)
  • web: show modality thumbnails for non-image files in the strip (#245) (aa3ae6e)
  • web: update dropzone to accept all file types, not just images (b8b6b0a)
  • web: wrap modality tabs to prevent overflow in narrow sidebar (dab31d6)

Features

  • add a Keep it free sponsor button to the top nav (#427) (7b04317)
  • add AES-256-GCM encryption at rest for sensitive settings (2520cdd)
  • add audio waveform visualization with wavesurfer.js (d8a8e05)
  • add backup status tracking endpoints (2aea351)
  • add bundle build script for CI (52b9405)
  • add CI workflow for building and publishing AI bundles (7dabfe2)
  • add Cmd+Enter (process) and Cmd+S (download) keyboard shortcuts (7c9ca85)
  • add enterprise Phase 1-4 feature flags and new permissions (86d6f50)
  • add full-width dropzone state and tool branding to tool page (f2ac057)
  • add GET /api/v1/tools/popular endpoint (1107005)
  • add landing tool command center (#386) (3b1d484)
  • add OpenTelemetry distributed tracing (enterprise) (#232) (3fb8164)
  • add page-level drop overlay and paste handler on tool page (6ea515c)
  • add per-tool permission model with category and per-tool modes (9fa23f4)
  • add per-user rate limiting and concurrent job limits (239f85f)
  • add PostHog customer feedback (649e65b)
  • add recent tools tracking via localStorage (6c61ae4)
  • add request correlation IDs to audit logs and response headers (1cf1f47)
  • add session idle timeout and concurrent session limit (3cc4ef6)
  • add settings slide-in, review panel with size delta, start-over preserving settings (45121c1)
  • add Sign PDF tool (draw/type/upload signatures, place on a PDF) (#370) (0cdd560)
  • add storage usage tracking with DB counters and reconciliation (aaa8a37)
  • add team-level storage quotas with enforcement on upload and save (d064286)
  • add TopNav and AvatarDropdown components (f79958a)
  • add usage onboarding survey overlay (#388) (a0d1c70)
  • add webhook delivery module with retry and backoff (ab88b9a)
  • ai: add a Reset AI Environment admin feature for the upgrade gap (#459) (fb96cf8)
  • All tab groups tools by modality with collapsible sections (e7126f9)
  • all-in-one embedded single-container mode (#377) (084a9c9)
  • analytics: build-time bake + telemetry depth (#336) (5d36ac0)
  • analytics: inject Sentry DSN + PostHog key from build env (#367) (9819c58), closes #336
  • analytics: upload web source maps to Sentry + tie release to build (#369) (1c202c6)
  • api: section-prefix all custom tool route literals (10bb73f)
  • api: section-prefix factory + batch routes via apiToolPath (+section validation) (68dd7da)
  • arrow key navigation in Files list (52693fc)
  • audit: add TOOL_EXECUTED logging with opt-in setting (36f083b)
  • audit: capture IP address, make TRUST_PROXY configurable (5d2f520)
  • audit: extensible event type system with shared constants (37b2b9c)
  • automate: make the pipeline builder fully multi-modal (#335) (a53038e)
  • bump feature manifest to v2 with archive metadata (a4ac7cf)
  • ci: add verify job to ai-bundles workflow (7d09927)
  • ci: add verify-bundle.sh for AI bundle smoke testing (5ee948d)
  • clean preview button with progress bar, add document preview support (3decfaa)
  • clean tool page nav, add Import from Files on dropzone (b5eef64)
  • copy-primary for data tools, download-all label for multi-output, batch failure display (bc3ad2b)
  • db: add audit integrity/requestId columns, user_preferences table, audit indexes (cafd2d8)
  • db: add data lifecycle columns (deleteAfter, legalHold, quotas, retention) (7e5843c)
  • db: add identity columns (lastActivity, toolPermissions, TOTP) (7ed043e)
  • disable auto-save, add Save to Files button, accept all file types in library (d0795b6)
  • docs: Two-Doors home, otter-orange brand, Pagefind search, and enterprise SSO/SCIM/roles guides (91ac583)
  • enterprise: add audit log archival with crash-safe state machine (c1dc27f)
  • enterprise: add audit log export endpoint (CSV/JSON) (913dd6b)
  • enterprise: add configuration export/import with dry-run and dependency validation (0f883fe)
  • enterprise: add GDPR user data export (async) (b6a8226)
  • enterprise: add GDPR user/team data purge with audit redaction (dd2a507)
  • enterprise: add IP allowlisting with CIDR matching and Redis cache (db6f7bf)
  • enterprise: add legal hold with cleanup bypass (fa7da7c)
  • enterprise: add per-team retention overrides with deleteAfter (b60f550)
  • enterprise: add SAML 2.0 SSO with SP-initiated login (54132d1)
  • enterprise: add SCIM 2.0 provisioning (Users + Groups) (a1b5c6d)
  • enterprise: add SIEM webhook forwarding with circuit breaker (d3f30a2)
  • enterprise: add SSO enforcement mode with break-glass admin (0c4468a)
  • enterprise: add tamper-resistant audit mode with HMAC integrity (895e29e)
  • enterprise: add TOTP MFA with enrollment, verification, and recovery codes (1787be3)
  • enterprise: add unified webhook system with admin alerts (d86e458)
  • enterprise: add upgrade management endpoints (version, migrations, readiness) (03e12e6)
  • expand alternatives comparisons (#384) (174001d)
  • expand Prometheus metrics with request duration, storage, and auth counters (fb14f41)
  • extend crash recovery for pre-built bundle artifacts (d1e9536)
  • extend health endpoints with disk space, S3, storage, and backup checks (6237684)
  • extend importBundleArchive for site-packages and fixups (5d5240e)
  • feedback: always-on nav button with GitHub/email handoff when analytics is off (#428) (5dcc06a)
  • feedback: route failed-run Report issue through the offline handoff (#429) (8cdd85a)
  • filter files by modality when importing from tool page (826f1ef)
  • i18n: add repair UI strings for broken AI bundles (8e15fe7)
  • i18n: raise translation coverage across all 20 locales (#332) (ffbf4f9)
  • i18n: raise translation coverage across all 20 locales (round 2) (#453) (44e1f90), closes #428 425/#426
  • Import from Files works, remove pipeline button from files page (b8a6b20)
  • inline error messages with recovery actions (56cd843)
  • landing,docs: SEO fixes and query-matched tool pages (#383) (ec98dfd)
  • landing: add animated shadergradient hero background (#411) (5500fac)
  • landing: auto-refresh live GitHub stars and image-pull stats (#292) (33671d2)
  • landing: enterprise-focused hero redesign and section polish (#239) (f622a4f)
  • landing: generate 301 redirects for old tool URLs; fix robots sitemap reference (0051655)
  • landing: migrate from Next.js to Astro 5 (8403222)
  • landing: one-command Docker quickstart + live-demo CTA in hero (#455) (aaf39a1)
  • landing: refocus hero on privacy-sensitive teams (#431) (8451f9b)
  • landing: section-nested tool routes, section index pages, and section-prefixed links (f158be6)
  • landing: swap Try Demo for Get Started Free CTA in top nav (#418) (ea004a3)
  • landing: warm up the contact CTAs (#412) (3d4a84d)
  • make password policy configurable via admin settings (8b349b0)
  • merge PostHog customer feedback (1d99acf)
  • mobile layout for tool-first flow (896acda)
  • modality-aware file preview in Files library (a70b13a)
  • modality-based URLs (/image/resize, /video/compress-video) (ea83e1c)
  • modality: rename "file" modality label "Data" -> "Files" (71fefc0)
  • move theme toggle and language selector to top nav bar (aff9159)
  • on-demand preview generation with progress messages for non-native formats (d3cd4e4)
  • pin frequently-used tools to the top of the dashboard (#440) (3aaaacc)
  • pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization (63a03d2), closes #355 #354 #356 #353 #351
  • polish home page UI -- card borders, colored icons, 3-col grid, Cmd+K hint (ade79c5)
  • redesign review panel action hierarchy (ed458d4)
  • remove /fullscreen route, add dynamic page titles (f9ebb30)
  • replace sidebar with top nav bar across all pages (71fef43)
  • request a tool when home search finds nothing (#385) (c68297d)
  • rewrite home page as tool-first browser with search and modality tabs (0d751b7)
  • rewrite install_feature.py for pre-built tar bundles (a4fa3ce)
  • scripts: add segment-anchored tool-path rewrite transform (c17a4a4)
  • scripts: add tool-path codemod CLI (0691457)
  • server-side preview generation for non-native video/audio formats (412a21e)
  • shared: add apiToolPath() and section-prefixed routes; drop MODALITY_URL_SLUG (9ca901f)
  • shared: add Section concept and toolSection() partition (7907471)
  • tiered processing feedback and upload progress indicator (433d59c)
  • tool-first workflow polish -- fix tests, lint cleanup (f387e98)
  • tools: 2.0 phase 5 wave 2 - pdf depth (21 tools) (#220) (2f39e38)
  • tools: 2.0 phase 5 wave 3a - video depth (22 tools) (#221) (5f98b48)
  • tools: 2.0 phase 5 wave 3b - audio depth (14 tools) (#222) (638288e)
  • tools: 2.0 phase 5 wave 4 - office, ebooks, data, archives (14 tools) (#224) (fc7c1f8)
  • tools: 2.0 phase 5 wave 5a - image gap-fill (11 tools) (#225) (6e1b986)
  • tools: 2.0 phase 5 wave 5b - ai pool: ocr-pdf, transcription, background composites (5 tools) (#226) (51666cd)
  • web: add data retention settings to admin UI (3016571)
  • web: add MFA login prompt and security settings UI (d397f57)
  • web: add storage dashboard and team retention settings (c7e9b1d)
  • web: apply Otter Orange design system and UI improvements (bcd59c2), closes #E07832 #2563eb
  • web: complete audit log viewer with IP column and all event types (c6f9a29)
  • web: fuzzy search with fuse.js for typo-tolerant tool discovery (22cccd4)
  • web: group home grid, tabs, and breadcrumb by section (8301676)
  • web: icon-only modality tabs, merge documents and files (cc06c80)
  • web: in-canvas zoom & pan for the object eraser and split tools (#320) (95d100c)
  • web: modality filter tabs in sidebar tool panel (8adceaf)
  • web: modality tabs on fullscreen grid page (82fb798)
  • web: section-prefix all tool API calls (22b4b5c)
  • web: show icon + text labels on modality filter tabs (888d243)
  • web: stronger modality section visual hierarchy in tool catalog (3db1b3b)
  • wire AI bundle build into release pipeline (d0732d4)

Reverts

  • deps: keep rembg at 2.0.69 (2.0.75 conflicts with pinned numpy==1.26.4) (4fdd10f)

BREAKING CHANGES

  • SnapOtter 2.0 - the platform re-architecture (Postgres 17 + Redis 8 + BullMQ durable jobs, 157 tools across five modalities) is the 2.0 release line, replacing the 1.x SQLite single-container architecture.

  • SQLite is no longer the runtime database. Deployments now require Postgres (and Redis, used from phase 2). Existing installs migrate with SQLITE_MIGRATE_PATH or 'pnpm --filter @snapotter/api migrate:sqlite'.

  • fix(ci): postgres service + fresh e2e database per run; ignore unfixable torch CVE-2025-3000

1.15.8 (2026-04-17)

Bug Fixes

  • copy Node.js from official image instead of apt-get install (536125e)

1.15.7 (2026-04-17)

Bug Fixes

  • add retry with backoff for apt-get update on CUDA base image (3d6db5a)

1.15.6 (2026-04-17)

Performance Improvements

  • parallelize model downloads and switch to registry cache (79c4ed6)

1.15.5 (2026-04-17)

Bug Fixes

  • exclude e2e-docker tests from Vitest runner (8df18c5)

1.15.4 (2026-04-17)

Bug Fixes

  • verbose error handling, batch processing, and multi-file support (3223960)
  • verbose errors, batch processing, multi-file support (#1) (8b87cf8)

1.15.3 (2026-04-16)

Bug Fixes

  • retry apt-get update on transient mirror sync errors (Acquire::Retries=3) (cec7163)

1.15.2 (2026-04-16)

Bug Fixes

  • use GHCR_TOKEN with write:packages scope for GHCR login (e14414f)

1.15.1 (2026-04-16)

Bug Fixes

  • docker: create /opt/models unconditionally so chown works in CI (93ce289)
  • docker: run frontend builder on BUILDPLATFORM to fix esbuild crash under QEMU (6a3ad0d)
  • resolve runtime model path mismatch for non-root Docker user (f28792a)

1.14.0 (2026-04-10)

Bug Fixes

  • add FILES_STORAGE_PATH to Dockerfile ENV to prevent data loss (b575243)
  • add shutdown timeout and improve health endpoint (986ad37)
  • address code review findings before merge (caf65bc)
  • correct PaddleOCR language codes for model download and OCR (e1ee571)
  • force CPU mode in download_models.py for build-time compatibility (b4b59a7)
  • handle paddlepaddle-gpu CUDA import at build time gracefully (0083a74)
  • install cuda-compat stubs for build-time PaddlePaddle import (d31d665)
  • load RealESRGAN pretrained weights for actual AI upscaling (fa9569c)
  • revert to npx tsx in CMD for pnpm compatibility (e55253d)
  • simplify smoke test to CPU-only imports for build-time compat (3481663)
  • skip RealESRGAN import check on arm64 in smoke test (1e2ef52)
  • split paddlepaddle-gpu and paddleocr installs, use --extra-index-url (74183e8)
  • suppress ML library stdout noise in ocr.py and upscale.py (c0b419d)
  • use PaddlePaddle GPU package index for CUDA wheels (dd9528f)
  • use platform-specific mediapipe version for arm64 compatibility (7face19)

Features

  • expand model pre-download with verification and smoke test (a9e3b96)
  • simplify CI to single unified Docker build (b385a2e)
  • simplify compose to single file, add log rotation (84f7057)
  • unified Docker image with GPU auto-detection (6c3eb3b)

1.13.0 (2026-04-10)

Bug Fixes

  • complete RBAC implementation lost during merge (cc8a272)

Features

  • add backend permission map and requirePermission middleware (1a99571)
  • add permission checks and admin override to API key routes (d776680)
  • add permission checks and admin override to pipeline routes (59f40db)
  • add permission checks and ownership scoping to user-files routes (86ba698)
  • add shared Permission and Role types (2f594e9)
  • add tools:use permission check to tool, batch, pipeline, and upload routes (885ace5)
  • extend useAuth hook with role and permissions from session (e0ba8be)
  • filter settings tabs by user permissions, remove admin fallback (bcbd24a)
  • include permissions and teamName in login/session responses (4943177)
  • replace requireAdmin with requirePermission on all routes (af7f57d)

1.12.0 (2026-04-10)

Bug Fixes

  • a11y: add keyboard support to pdf-to-image upload dropzone (1778f72)
  • use specific selector in pdf-to-image e2e test (b2a2c89)

Features

  • add pdf-to-image backend route with info and processing endpoints (30155c1)
  • add pdf-to-image frontend settings component (44bbfba)
  • register pdf-to-image in frontend tool registry (5fd294c)
  • register pdf-to-image tool in shared constants and i18n (43324c1)
  • unified Docker image with GPU auto-detection (#37) (b0083e2)

1.12.0 (2026-04-10)

Features

  • unified Docker image with GPU auto-detection (#37) (b0083e2)

1.11.0 (2026-04-07)

Features

  • docs: auto-generate llms.txt via vitepress-plugin-llms (ee28ec6)

1.10.0 (2026-04-07)

Features

  • add content-aware resize API route and registration (aa3cc5c)
  • add content-aware resize toggle to resize settings UI (4b4464f)
  • add seam carving AI bridge module (3c0f5b6)
  • add seam carving Python script with face protection (fb833e4)

1.9.0 (2026-04-07)

Features

  • add stitch API route handler (63ea0ba)
  • add stitch settings UI component (6abe893)
  • register stitch component in web tool registry (612f7d9)
  • register stitch route in API tool registry (a37d54f)
  • register stitch tool in shared constants and i18n (b881416)

1.8.1 (2026-04-07)

Bug Fixes

  • add variant diagnostics to health endpoint and lite mode banner (2c6e499)

1.8.0 (2026-04-06)

Bug Fixes

  • filter unsafe round-trip keys server-side in editMetadata (32bde85)

Features

  • add edit-metadata API route with inspect and edit endpoints (ff07b83)
  • add edit-metadata UI component with granular strip support (dcd600d)
  • add EditMetadataOptions type and exif-reader dep to image-engine (39bc5bc)
  • extract shared metadata parsing utilities into image-engine (c075849)
  • implement editMetadata operation in image-engine (f3be1ef)
  • register edit-metadata in shared constants and i18n (4a424d7)

1.7.7 (2026-04-06)

Bug Fixes

  • improve AI tool reliability for face detection and background removal (#25) (1963a80)

1.7.6 (2026-04-06)

Bug Fixes

  • batch SSE progress and non-AI processing UX (#24) (0ce42d1)

1.7.5 (2026-04-06)

Bug Fixes

  • add server-side logging to AI tool routes (#23) (3645de8)

1.7.4 (2026-04-06)

Bug Fixes

  • batch file ordering and format preservation for image tools (#20) (822a078), closes #13 #14

1.7.3 (2026-04-06)

Bug Fixes

  • docs: correct broken llms.txt links on REST API page (5e3a8b3)

1.7.2 (2026-04-05)

Bug Fixes

  • use torch.cuda for GPU detection instead of onnxruntime providers (7185bd5)

1.7.1 (2026-04-05)

Bug Fixes

  • prevent false GPU detection when CUDA image runs without GPU (1efb163)

1.7.0 (2026-04-05)

Bug Fixes

  • web: skip empty Authorization header for forward-auth proxy compatibility (636153f), closes #6

Features

  • add GPU/CUDA acceleration support (:cuda Docker tag) (a5f62f0)

1.6.0 (2026-04-04)

Features

  • lightweight Docker image without AI/ML tools (:lite tag) (3a0b988), closes #1

1.5.3 (2026-04-04)

Bug Fixes

  • use heif-convert for HEIC decoding on Linux (da15a1e)

1.5.2 (2026-04-04)

Bug Fixes

  • install HEVC codec plugins for CI HEIC tests (24e7591)

1.5.1 (2026-04-04)

Bug Fixes

  • install libheif-examples in CI for HEIC tests (d06092c)

1.5.0 (2026-04-04)

Features

  • add HEIC/HEIF format support for input and output (df1dc02)

1.4.0 (2026-04-04)

Features

  • add "Crop to Content" mode to smart crop tool (df479d3), closes #7

1.3.1 (2026-04-04)

Bug Fixes

  • default theme to light instead of following system preference (018fcce)

1.3.0 (2026-04-04)

Bug Fixes

  • add XHR timeout to prevent UI spinning forever (0abacb2)
  • disable worker pool to prevent Docker processing hang (e36cd0c)
  • log volume permission errors instead of swallowing them (a3e6927)
  • replace crypto.randomUUID with generateId in AI tool settings (ed91861)
  • replace crypto.randomUUID with generateId in pipeline/automation (bcbf86c)
  • replace crypto.randomUUID with generateId in use-tool-processor (07cc2d0)
  • replace navigator.clipboard with copyToClipboard utility (1857aeb)
  • resolve multiple API and e2e test bugs (00deafb)
  • restore navigator.clipboard and execCommand mocks in tests (57e71b7)

Features

  • add copyToClipboard() utility with execCommand fallback (8686131)
  • add generateId() utility for non-secure context compatibility (ee7741b)

1.2.1 (2026-04-03)

Bug Fixes

  • handle volume permission issues for bind-mounted /data directory (863a51c)

1.2.0 (2026-04-03)

Features

  • move theme toggle and GitHub button to top-right navbar (0ba9fa5)

1.1.0 (2026-04-03)

Features

  • add GitHub stars button to docs navbar and fix footer license (90030fc)

1.0.1 (2026-03-30)

Bug Fixes

  • allow SVG files in the convert tool (034281b)

1.0.0 (2026-03-30)

Bug Fixes

  • a11y: add aria-hidden to decorative GemLogo SVG (ae185ce)
  • add remove-background settings to pipeline step configurator (ae5ac81)
  • add SSE progress endpoint to public paths (18c3da0)
  • api: allow Scalar docs through auth and CSP (6023109)
  • api: resolve team name lookup and show server error messages (609fc8b)
  • api: use content instead of spec.content for Scalar v1.49 API (dfcb4d5)
  • apply continuous progress bar to erase-object and OCR (196c553)
  • blur-faces: switch from MediaPipe to OpenCV and auto-orient images (dc10f90)
  • bridge.ts ENOENT check for Python venv fallback (92442cd)
  • clear search when adding a step from the tool picker (ae2e63f)
  • continuous progress bar (no 100%→0% reset) (b4abefe)
  • crop: use percentCrop from onChange to fix inflated pixel values (f238820)
  • deduplicate react in Vite to prevent zustand hook errors in monorepo (b3d6947)
  • docker: add build layer caching for faster Docker rebuilds (03ba30d)
  • docker: skip husky prepare script in production install (fdfb0a0)
  • docs: clean up footer llms.txt links (e842cde)
  • docs: ignore localhost dead links in VitePress build (78269d4)
  • docs: remove hero logo from home page (64c0ec8)
  • handle migration race condition in concurrent test workers (d576ab1)
  • make port 1349 the UI port in all modes (20a2637)
  • move health diagnostics behind admin auth (ee9a20f)
  • ocr: update PaddleOCR for v3 API and add Tesseract fallback (e260a93)
  • pipeline only shows compatible tools and displays errors (fe021c1)
  • prevent pipeline step settings from resetting on collapse (d899ef1)
  • prevent stale closure in pipeline step callbacks (c67f002)
  • prevent useAuth infinite loop causing rate limit storms (9624dae)
  • Python bridge fallback only on missing venv, not script errors (79e4116)
  • reject HTML tags in settings API to prevent stored XSS (d5bd011)
  • remove explicit pnpm version from CI to avoid conflict with packageManager (c0f5dad)
  • remove Google Drive coming soon placeholder from files nav (e487fe0)
  • resolve 3 critical UX bugs - home upload, auth, and form submit (97267c7)
  • resolve pipeline step race condition and infinite re-render loop (e0177d4)
  • resolve test failures from shared DB race conditions (1a7116d)
  • resolve tsx not found in AI docs updater workflow (dfbef8d)
  • resolve TypeScript Uint8Array type error with fflate (c1b06b3)
  • restore APP_VERSION import used by health endpoint (2a74b60)
  • setError(null) was overriding setProcessing(true) (2be94b7)
  • show checkerboard behind transparent images in before/after slider (73741e6)
  • simplify public health to static response, add 403 test (9c05da6)
  • streamline CI/CD — remove broken AI docs updater, fix Docker publish (ad2c96d)
  • surface hidden errors and add batch rejection tests (2f8e2ce)
  • switch README Docker references from GHCR to Docker Hub (9e15679)
  • sync stepsRef during render, not useEffect (0c86744)
  • test: add missing PNG fixture files to repo (45c6b9d)
  • test: exclude e2e tests from vitest and fix CI test suite (9d28485)
  • tests: remove temp DB cleanup that races with other test files (498bfb3)
  • trigger browser password save prompt on password change (6b279ad)
  • ui: clean up settings, automate page, fullscreen logo, and README (b3c8ad4)
  • unify project on port 1349, improve strip-metadata and UI components (4912ee3)
  • upscale: auto-orient images before upscaling and improve UI (8a6e665)
  • use BiRefNet-Lite as default model and fix JSON parsing (c8159d3)
  • use two-pass validation in settings PUT to prevent partial writes (2dc39d3)
  • use U2-Net as default model (fast, 2s) with BiRefNet as opt-in (7ebed9a)
  • white screen crash when uploading photos with null GPS EXIF data (c913df9)

Features

  • accept clientJobId in batch endpoint for SSE progress correlation (8ed57f4)
  • add authentication with default admin user (2189628)
  • add automatic workspace file cleanup cron (5af7437)
  • add CSS transform props to ImageViewer for live rotate/flip preview (de3340f)
  • add CSS transform props to ImageViewer for live rotate/flip preview (7627853)
  • add Fastify API server with health check and env config (be73ce9)
  • add forced password change page on first login (e0900a8)
  • add format tools (SVG-to-raster, vectorize, GIF) and optimization (rename, favicon, image-to-PDF) (7b29b04)
  • add generic tool page template with settings panel and dropzone (0f32ba1)
  • add image-engine and ai stub packages (17ac7b8)
  • add layout tools (collage, splitting, border/frame) (e46dbf6)
  • add live preview callback to RotateSettings, rename button to Apply (17be50b)
  • add live preview callback to RotateSettings, rename button to Apply (06844ec)
  • add login page with split layout matching SnapOtter style (2b82f93)
  • add multi-stage Docker build with Python ML dependencies (8d70123)
  • add MultiImageViewer with arrow navigation and filmstrip (1fa8747)
  • add password generator and browser save prompt on change-password page (d56c644)
  • add Phase 4 AI tools with Python bridge and 6 new tools (21df50e)
  • add privacy policy page and fix CSP blocking API docs (3e314f0)
  • add processAllFiles batch method to tool processor hook (cd1e180)
  • add replace-color tool and update tool page routing (d5d09e4)
  • add semantic-release for automated versioning and help dialog (83a0272)
  • add shared package with types, tool definitions, and constants (96ed415)
  • add SideBySideComparison component for resize results (d037305)
  • add SideBySideComparison component for resize results (2d0ba5a)
  • add SQLite database with Drizzle ORM schema and migrations (88c41cf)
  • add SnapOtter-style layout with sidebar, tool panel, dropzone, and theme toggle (90f10f4)
  • add Swagger/OpenAPI documentation at /api/docs (0ef1a5a)
  • add theme system with dark/light/system support and persistence (e35d249)
  • add ThumbnailStrip filmstrip component (9caa613)
  • add utility tools (image info, compare, duplicates, color palette, QR, barcode) (e17992e)
  • add Vite + React SPA with Tailwind CSS and routing (9483ad7)
  • add watermark, text overlay, and image composition tools (b2543d9)
  • add worker threads, persistent Python sidecar, graceful shutdown, and architectural improvements (1274cc1)
  • adjustments: add real-time live preview for all color tools (b5c924e)
  • ai: add emit_progress() calls to all Python AI scripts (eb6f57d)
  • ai: add onProgress callback to all AI wrapper functions (021c9f1)
  • ai: rewrite bridge.ts to stream stderr progress via spawn (9d9c45a)
  • api,web: add batch processing with ZIP download and SSE progress (f8aa5f7)
  • api: add all remaining endpoints to OpenAPI spec (e7b38ba)
  • api: add all tool endpoints to OpenAPI spec (753ba3e)
  • api: add generic tool route factory for all image tools (43555c9)
  • api: add llms.txt and llms-full.txt endpoints (12ba52a)
  • api: add logo upload/serve/delete routes with tests (6063f4d)
  • api: add multipart file upload, workspace management, and download routes (415de2a)
  • api: add OpenAPI 3.1 spec skeleton with common schemas (b2189f5)
  • api: add persistent file management helpers to frontend api module (ecbfcce)
  • api: add pipeline execution, save, and list endpoints (d4f1148)
  • api: add resize, crop, rotate, convert, compress, metadata, and color tool routes (4874701)
  • api: add Scalar docs route and install dependency (6f2c319)
  • api: add SingleFileProgress type and SSE update function (12b85d4)
  • api: add teams CRUD routes and update auth team references (ec22e53)
  • api: add tool filtering and DB-backed cleanup settings (07e7e8d)
  • api: add user files CRUD routes at /api/v1/files/* (6a07007)
  • api: register docs route in server and test helper (bc6b389)
  • api: wire AI route handlers to SSE progress via clientJobId (a3f85da)
  • branding: add faceted gem SVG logo assets (4bc9335)
  • branding: add favicon and meta tags to index.html (2508fd0)
  • branding: add OG social preview image (c6c5b92)
  • branding: add PWA manifest and PNG logo assets (298567d)
  • branding: show gem icon in app header as default logo (dd857fb)
  • conditional result views — side-by-side for resize, live preview for rotate (f0d18be)
  • conditional result views — side-by-side for resize, live preview for rotate (6682649)
  • crop: add CropCanvas component with visual overlay, grid, and keyboard controls (018bbf4)
  • crop: add react-image-crop dependency (b7ecd41)
  • crop: redesign CropSettings with aspect presets, pixel inputs, and grid toggle (d75f458)
  • crop: wire CropCanvas and CropSettings into tool-page with bidirectional state (ea7fb46)
  • db: add teams table and migration (365783b)
  • db: add userFiles table and migration (a2fdbd5)
  • docs: add gem favicon to VitePress site (0918f93)
  • docs: add gem logo to GitHub Pages nav bar and home hero (f0b8162)
  • docs: add llms.txt and llms-full.txt to GitHub Pages (5f6959a)
  • docs: add llms.txt links to GitHub Pages footer (b874445)
  • env: add FILES_STORAGE_PATH config variable (3c737a6)
  • erase-object: replace mask upload with in-browser brush painting (40e3081)
  • extract auto-orient utility and expand test coverage (8622c4a)
  • files: add Files page with nav, list, details, upload, and routing (3f127a4)
  • files: add mobile layout for Files page (e864d1e)
  • files: wire serverFileId for version tracking (8868d3e)
  • harden auth, security headers, SVG sanitization, and pipeline ownership (beaad1d)
  • i18n: add translation keys for settings phase 1 (c5ff80a)
  • image-engine: add Sharp wrapper with 14 image operations (3e7f71c)
  • image-to-pdf: add live PDF page preview with margin visualization (cd666ea)
  • implement Files page with persistent storage and version tracking (f6183d2)
  • initialize Turborepo monorepo with pnpm workspaces (db31cf6)
  • integrate MultiImageViewer and multi-file UX into tool page (52aab1e)
  • make AI tools pipeline-compatible and add search to tool picker (2d46b09)
  • merge multi-image UX — batch processing, filmstrip navigation, resize/rotate redesign (9bfdb75)
  • multi-arch Docker support, security hardening, and test improvements (748d2b7)
  • multi-file metadata display with per-file caching (42b59f3)
  • pipeline: add inline settings configuration for automation steps (827eae8)
  • production Docker, Playwright tests, settings API, and bug fixes (027c515)
  • replace model dropdown with intuitive subject/quality selector in remove-bg (bc26d60)
  • rewrite file-store with FileEntry model for multi-image support (abbb3e4)
  • rewrite resize settings with tab-based UI (presets, custom, scale) (b9f3ac0)
  • rewrite resize settings with tab-based UI (presets, custom, scale) (3b39a8c)
  • rotate: add editable angle input and fine-tune +/- buttons (e1f04c2)
  • serve React SPA from Fastify in production mode (d4ae4d5)
  • storage: add file storage helpers module (7c37213)
  • stores: add Zustand store for Files page state management (fb487be)
  • tool-factory: auto-save results to persistent file store when fileId provided (27d8629)
  • ui: add teams, tools, feature flags, temp files, logo to settings dialog (fbce0dd)
  • upgrade to BiRefNet SOTA background removal model (f53937b)
  • web: add before/after image comparison slider component (64c8f90)
  • web: add fullscreen tool grid view (86b716b)
  • web: add i18n architecture with English translations (994cba7)
  • web: add keyboard shortcuts for tool navigation (e06e44c)
  • web: add mobile responsive layout with bottom navigation (ade6469)
  • web: add pipeline builder UI with saved automations and templates (39a7bf2)
  • web: add ProgressCard component (ed69488)
  • web: add ProgressCard to non-AI tool settings (Group A) (17035e9)
  • web: add settings dialog with general, security, API keys, and about sections (bca8e81)
  • web: add SnapOtter-style file preview, review panel, and tool chaining UX (e12fc57)
  • web: add tool settings UI for all core image tools (f9be6d6)
  • web: migrate AI tool settings to ProgressCard (eed4fc2)
  • web: redesign home page upload flow and add auth guard (915a8cc)
  • web: rewrite useToolProcessor with XHR upload progress and SSE (305f50b)
  • wire up batch processing across tool settings components (1d87091)

0.19.0 (2026-03-29)

Features

  • add privacy policy page and fix CSP blocking API docs (3e314f0)

0.18.0 (2026-03-29)

Features

  • add worker threads, persistent Python sidecar, graceful shutdown, and architectural improvements (1274cc1)

0.17.7 (2026-03-28)

Bug Fixes

  • move health diagnostics behind admin auth (ee9a20f)
  • reject HTML tags in settings API to prevent stored XSS (d5bd011)
  • simplify public health to static response, add 403 test (9c05da6)
  • switch README Docker references from GHCR to Docker Hub (9e15679)
  • use two-pass validation in settings PUT to prevent partial writes (2dc39d3)

0.17.6 (2026-03-28)

Bug Fixes

  • resolve pipeline step race condition and infinite re-render loop (e0177d4)
  • show checkerboard behind transparent images in before/after slider (73741e6)

0.17.5 (2026-03-28)

Bug Fixes

  • sync stepsRef during render, not useEffect (0c86744)

0.17.4 (2026-03-28)

Bug Fixes

  • prevent stale closure in pipeline step callbacks (c67f002)

0.17.3 (2026-03-28)

Bug Fixes

  • clear search when adding a step from the tool picker (ae2e63f)

0.17.2 (2026-03-28)

Bug Fixes

  • prevent pipeline step settings from resetting on collapse (d899ef1)

0.17.1 (2026-03-28)

Bug Fixes

  • add remove-background settings to pipeline step configurator (ae5ac81)

0.17.0 (2026-03-28)

Features

  • make AI tools pipeline-compatible and add search to tool picker (2d46b09)

0.16.4 (2026-03-28)

Bug Fixes

  • surface hidden errors and add batch rejection tests (2f8e2ce)

0.16.3 (2026-03-28)

Bug Fixes

  • remove Google Drive coming soon placeholder from files nav (e487fe0)

0.16.2 (2026-03-28)

Bug Fixes

  • pipeline only shows compatible tools and displays errors (fe021c1)

0.16.1 (2026-03-28)

Bug Fixes

  • trigger browser password save prompt on password change (6b279ad)

0.16.0 (2026-03-28)

Features

  • add password generator and browser save prompt on change-password page (d56c644)

0.15.0 (2026-03-28)

Features

  • add forced password change page on first login (e0900a8)

0.14.2 (2026-03-28)

Bug Fixes

  • tests: remove temp DB cleanup that races with other test files (498bfb3)

0.14.1 (2026-03-28)

Bug Fixes

  • handle migration race condition in concurrent test workers (d576ab1)

0.14.0 (2026-03-28)

Features

  • multi-arch Docker support, security hardening, and test improvements (748d2b7)

0.13.1 (2026-03-27)

Bug Fixes

  • docs: remove hero logo from home page (64c0ec8)

0.13.0 (2026-03-27)

Features

  • docs: add gem logo to GitHub Pages nav bar and home hero (f0b8162)

0.12.1 (2026-03-27)

Bug Fixes

  • docs: clean up footer llms.txt links (e842cde)

0.12.0 (2026-03-27)

Bug Fixes

  • api: resolve team name lookup and show server error messages (609fc8b)

Features

  • docs: add llms.txt links to GitHub Pages footer (b874445)

0.11.1 (2026-03-27)

Bug Fixes

  • docs: ignore localhost dead links in VitePress build (78269d4)

0.11.0 (2026-03-27)

Bug Fixes

  • a11y: add aria-hidden to decorative GemLogo SVG (ae185ce)
  • api: allow Scalar docs through auth and CSP (6023109)
  • api: use content instead of spec.content for Scalar v1.49 API (dfcb4d5)
  • ui: clean up settings, automate page, fullscreen logo, and README (b3c8ad4)

Features

  • api: add all remaining endpoints to OpenAPI spec (e7b38ba)
  • api: add all tool endpoints to OpenAPI spec (753ba3e)
  • api: add llms.txt and llms-full.txt endpoints (12ba52a)
  • api: add OpenAPI 3.1 spec skeleton with common schemas (b2189f5)
  • api: add Scalar docs route and install dependency (6f2c319)
  • api: register docs route in server and test helper (bc6b389)
  • branding: add faceted gem SVG logo assets (4bc9335)
  • branding: add favicon and meta tags to index.html (2508fd0)
  • branding: add OG social preview image (c6c5b92)
  • branding: add PWA manifest and PNG logo assets (298567d)
  • branding: show gem icon in app header as default logo (dd857fb)
  • docs: add gem favicon to VitePress site (0918f93)
  • docs: add llms.txt and llms-full.txt to GitHub Pages (5f6959a)

0.10.0 (2026-03-26)

Bug Fixes

  • ocr: update PaddleOCR for v3 API and add Tesseract fallback (e260a93)

Features

  • erase-object: replace mask upload with in-browser brush painting (40e3081)

0.9.0 (2026-03-26)

Bug Fixes

  • blur-faces: switch from MediaPipe to OpenCV and auto-orient images (dc10f90)
  • docker: add build layer caching for faster Docker rebuilds (03ba30d)
  • upscale: auto-orient images before upscaling and improve UI (8a6e665)

Features

  • adjustments: add real-time live preview for all color tools (b5c924e)
  • image-to-pdf: add live PDF page preview with margin visualization (cd666ea)
  • rotate: add editable angle input and fine-tune +/- buttons (e1f04c2)

0.8.2 (2026-03-25)

Bug Fixes

  • test: add missing PNG fixture files to repo (45c6b9d)
  • test: exclude e2e tests from vitest and fix CI test suite (9d28485)

0.8.1 (2026-03-25)

Bug Fixes

  • resolve test failures from shared DB race conditions (1a7116d)

0.8.0 (2026-03-25)

Bug Fixes

  • docker: skip husky prepare script in production install (fdfb0a0)
  • prevent useAuth infinite loop causing rate limit storms (9624dae)

Features

  • api: add logo upload/serve/delete routes with tests (6063f4d)
  • api: add persistent file management helpers to frontend api module (ecbfcce)
  • api: add teams CRUD routes and update auth team references (ec22e53)
  • api: add tool filtering and DB-backed cleanup settings (07e7e8d)
  • api: add user files CRUD routes at /api/v1/files/* (6a07007)
  • db: add teams table and migration (365783b)
  • db: add userFiles table and migration (a2fdbd5)
  • env: add FILES_STORAGE_PATH config variable (3c737a6)
  • files: add Files page with nav, list, details, upload, and routing (3f127a4)
  • files: add mobile layout for Files page (e864d1e)
  • files: wire serverFileId for version tracking (8868d3e)
  • i18n: add translation keys for settings phase 1 (c5ff80a)
  • implement Files page with persistent storage and version tracking (f6183d2)
  • storage: add file storage helpers module (7c37213)
  • stores: add Zustand store for Files page state management (fb487be)
  • tool-factory: auto-save results to persistent file store when fileId provided (27d8629)
  • ui: add teams, tools, feature flags, temp files, logo to settings dialog (fbce0dd)

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

Added

  • Files page — persistent server-side storage with version tracking and a mobile layout
  • Teams — full CRUD API, database table, and migration
  • Admin settings panel covering teams, tool visibility, feature flags, temp file cleanup, and logo upload
  • Branding API routes (logo upload, serve, delete)
  • Tool filtering and DB-backed cleanup settings on the API side
  • i18n keys for the new settings screens
  • userFiles table for persistent file management
  • FILES_STORAGE_PATH config variable for controlling where uploaded files live
  • Tool results auto-save to persistent storage when a fileId is provided

Changed

  • Renamed Tool.alpha to Tool.experimental everywhere
  • Tightened TypeScript types in tool-factory registry (removed any casts)
  • Bumped login attempt limit from 5 to 10
  • Switched isNaN to Number.isNaN in cleanup interval parsing
  • Null-safe team lookup in auth registration

Removed

  • Internal planning docs (docs/superpowers/) and AI tool config from version control - these stay local only

0.7.0 - 2026-03-24

Added

  • Inline settings configuration for pipeline automation steps, allowing per-step parameter overrides

Security

  • Hardened authentication with stricter session validation
  • Added security headers (HSTS, CSP, X-Content-Type-Options)
  • SVG sanitization on upload to prevent XSS via malicious SVGs
  • Pipeline ownership enforcement — users can only execute their own pipelines

0.6.0 - 2026-03-24

Added

  • Extracted reusable auto-orient utility from image processing pipeline
  • Expanded integration test coverage across tool routes

0.5.2 - 2026-03-23

Fixed

  • Restored APP_VERSION import used by the /health endpoint, fixing version reporting in production

0.5.1 - 2026-03-23

Fixed

  • Crop tool now uses percentCrop from onChange callback, fixing inflated pixel values that produced incorrect crop regions

Changed

  • Removed unused Swagger dependencies, reducing bundle size
  • Parallelized CI jobs for faster pipeline execution

0.5.0 - 2026-03-23

Added

  • Interactive crop tool with visual overlay, grid lines, aspect ratio presets, pixel input fields, and keyboard controls
  • Multi-image support — upload and process multiple files with arrow navigation and filmstrip thumbnail strip
  • Batch processing wired across all tool settings with processAllFiles method
  • clientJobId correlation for SSE progress during batch operations
  • Side-by-side comparison view for resize results
  • Live CSS transform preview for rotate/flip operations
  • Redesigned resize settings with tabbed UI (presets, custom dimensions, scale percentage)
  • Client-side ZIP extraction via fflate for batch result downloads
  • Per-file metadata display with caching

Fixed

  • White screen crash when uploading photos with null GPS EXIF data
  • TypeScript Uint8Array type incompatibility with fflate

0.4.1 - 2026-03-23

Fixed

  • Unified all services on port 1349 (was split across multiple ports)
  • Strip-metadata tool now correctly removes all EXIF data
  • Before/after slider and side-by-side comparison component rendering fixes

0.4.0 - 2026-03-23

Added

  • Resize tool redesign with tabbed settings UI — presets, custom dimensions, and scale percentage
  • Rotate/flip live preview using CSS transforms before server round-trip
  • Side-by-side comparison component for visual before/after on resize
  • Conditional result views — side-by-side for resize, live preview for rotate

Fixed

  • CI/CD pipeline — removed broken AI docs updater workflow, fixed Docker publish job

0.3.1 - 2026-03-23

Fixed

  • CI workflow failure: tsx binary not found in AI docs updater action

0.3.0 - 2026-03-23

Added

  • Real progress bars replacing indeterminate spinners across all tools
  • SSE-based progress streaming from Python AI scripts through the API to the frontend
  • ProgressCard component with determinate progress display for all tool types
  • useToolProcessor hook rewritten with XHR upload progress and SSE event streaming
  • onProgress callback support in all AI wrapper functions (rembg, RealESRGAN, PaddleOCR, MediaPipe, LaMa)
  • emit_progress() calls in all Python AI scripts for granular status updates
  • Intuitive subject/quality selector replacing raw model dropdown in background removal tool

Fixed

  • Progress bar no longer resets from 100% to 0% between processing stages
  • setError(null) no longer overrides setProcessing(true) race condition
  • SSE progress endpoint added to public auth paths (was returning 401)

0.2.1 - 2026-03-22

Added

  • Monorepo foundation — Turborepo with pnpm workspaces (apps/api, apps/web, apps/docs, packages/shared, packages/image-engine, packages/ai)
  • Fastify API server with health check, environment config, and SQLite database via Drizzle ORM
  • Authentication system with default admin user, login page, and session management
  • React SPA with Vite, Tailwind CSS, dark/light/system theme, and sidebar layout
  • 14 Sharp-based image operations — resize, crop, rotate, convert, compress, metadata strip, color adjust, and more
  • Generic tool route factory for declarative API endpoint creation
  • Tool settings UI for all core image tools with before/after comparison slider
  • Batch processing with ZIP download and SSE progress tracking
  • 30+ tools including watermark, text overlay, composition, collage, splitting, border/frame, image info, compare, duplicates, color palette, QR code, barcode, replace-color, SVG-to-raster, vectorize, GIF, favicon, and image-to-PDF
  • 6 AI-powered tools via Python sidecar — background removal, upscaling, OCR, face detection/blur, object erasure (LaMa inpainting)
  • Pipeline system — builder UI with templates, execution/save/list API endpoints
  • i18n architecture with English translations
  • Keyboard shortcuts for tool navigation
  • Mobile responsive layout with bottom navigation
  • Fullscreen tool grid view
  • Settings dialog (general, security, API keys, about)
  • API key management routes
  • Home page redesign with upload flow and auth guard
  • Multi-stage Docker build with Python ML dependencies
  • Playwright end-to-end test suite
  • VitePress documentation site with GitHub Pages deployment
  • GitHub Actions CI pipeline and Docker Hub auto-publish workflow
  • Semantic-release for automated versioning
  • Swagger/OpenAPI documentation at /api/docs
  • Automatic workspace file cleanup cron

Fixed

  • Python bridge ENOENT handling for venv fallback — no longer swallows script errors
  • Port configuration unified to 1349 for the UI across all modes
  • Home upload flow, auth redirect, and form submit handling bugs
  • Background removal defaults to U2-Net (fast, ~2s) instead of slow BiRefNet