# [2.0.0](https://github.com/snapotter-hq/snapotter/compare/v1.17.2...v2.0.0) (2026-07-07) * feat!: SnapOtter 2.0.0 ([6205525](https://github.com/snapotter-hq/snapotter/commit/620552569e1b6b163df66ee824a480e6d5750abb)), closes [#254](https://github.com/snapotter-hq/snapotter/issues/254) [#261](https://github.com/snapotter-hq/snapotter/issues/261) * feat(db)!: SnapOtter 2.0 phase 1 foundation: postgres, migrator, compose stack ([#216](https://github.com/snapotter-hq/snapotter/issues/216)) ([1c724d5](https://github.com/snapotter-hq/snapotter/commit/1c724d5d21659be24423a22c7d6737d59b3d6310)) ### Bug Fixes * adopt sharp 0.35.2+ by centralizing the FormatEnum key type ([#362](https://github.com/snapotter-hq/snapotter/issues/362)) ([9052da2](https://github.com/snapotter-hq/snapotter/commit/9052da27f3a298f950a9949a0e0929e72b569b04)) * **ai-bundles:** lock the numpy-1.x ABI closure so the OCR bundle can't strand scipy ([67c5566](https://github.com/snapotter-hq/snapotter/commit/67c55669d610801e8cd07e4d65c5642a08fc0b07)) * **ai-bundles:** lock the numpy-1.x ABI closure so the OCR bundle can't strand scipy ([#437](https://github.com/snapotter-hq/snapotter/issues/437)) ([fd39f66](https://github.com/snapotter-hq/snapotter/commit/fd39f66f464e21836e8cfd72ab38f3d5c6d3528f)) * **ai-bundles:** repair bundle build + publish pipeline (deepsafe repo, CPU provider, manifest) ([3b50bcd](https://github.com/snapotter-hq/snapotter/commit/3b50bcdc5ccb630998c60003d5eddd9803780013)) * **ai:** broaden SSRF pre-scan regex to cover srcset, poster, formaction, [@import](https://github.com/import) ([5397f9b](https://github.com/snapotter-hq/snapotter/commit/5397f9b21c5b8566fed355f13d62378035456981)) * **ai:** detect a paddle-only GPU so OCR uses PaddleOCR-GPU not Tesseract ([#439](https://github.com/snapotter-hq/snapotter/issues/439)) ([7cd514d](https://github.com/snapotter-hq/snapotter/commit/7cd514dd8cdee28b9f600722f43ba63bcdbe2928)) * **ai:** enforce the feature gate on the per-request fallback path ([#331](https://github.com/snapotter-hq/snapotter/issues/331)) ([7a70aff](https://github.com/snapotter-hq/snapotter/commit/7a70affac51153cf0bd6432a7d9bdc4e6c76bc4b)), closes [#327](https://github.com/snapotter-hq/snapotter/issues/327) * **ai:** gate AI tools on per-framework GPU detection, not a shared boolean ([#445](https://github.com/snapotter-hq/snapotter/issues/445)) ([36dde9a](https://github.com/snapotter-hq/snapotter/commit/36dde9ad8784867270bbfe766650b4c4515dbcb9)) * **ai:** pin protobuf<5 on arm64 so mediapipe face landmarks work ([#417](https://github.com/snapotter-hq/snapotter/issues/417)) ([2c2fb65](https://github.com/snapotter-hq/snapotter/commit/2c2fb65fcaaa835ca589e59255366819cece5fdf)) * **ai:** pin rembg to 2.0.69 to keep numpy<2 compatibility ([3726335](https://github.com/snapotter-hq/snapotter/commit/3726335063984bd572a14eea36c532bda74bc1d6)) * **ai:** surface actionable fix for libGL.so.1 missing on headless installs ([7c70c60](https://github.com/snapotter-hq/snapotter/commit/7c70c60b9e3e0912b1f8be6acf87f378f8b9c080)) * **ai:** update arm64 bundle sha256/size after protobuf<5 rebuild ([#421](https://github.com/snapotter-hq/snapotter/issues/421)) ([2a36b3d](https://github.com/snapotter-hq/snapotter/commit/2a36b3dfe0e4388f7bd1c2a8183f7d87e57dc144)), closes [#417](https://github.com/snapotter-hq/snapotter/issues/417) * allow reinstall of AI bundles with broken model files ([#214](https://github.com/snapotter-hq/snapotter/issues/214)) ([27a56c7](https://github.com/snapotter-hq/snapotter/commit/27a56c774bfd8f920355a1f5b70553639ad165df)) * always show NonNativePreview for non-native formats, even after processing ([abaae18](https://github.com/snapotter-hq/snapotter/commit/abaae18669a281a03aeafebec764f9992659c862)) * **analytics:** harden analytics opt-out and feedback surfaces ([#423](https://github.com/snapotter-hq/snapotter/issues/423)) ([23efce9](https://github.com/snapotter-hq/snapotter/commit/23efce9df0f8cedabd9aab033b896f7f3dffc768)) * **api:** batch user-files delete to eliminate N+1 queries ([e2c5714](https://github.com/snapotter-hq/snapotter/commit/e2c57144dd1f8f9a7de629228967725861cb50c7)) * **api:** decode RAW via LibRaw first so DNG processes at full resolution ([#289](https://github.com/snapotter-hq/snapotter/issues/289)) ([#290](https://github.com/snapotter-hq/snapotter/issues/290)) ([3d9ff1e](https://github.com/snapotter-hq/snapotter/commit/3d9ff1e0d2c60a88fdba03c11f45e1422eacf84d)) * **api:** drop app-logger import from media-input; update stale errors mock ([c483897](https://github.com/snapotter-hq/snapotter/commit/c483897452d0769a3a1fbca8758fdc7eaf1b3cc0)) * **api:** fix batch user-files delete recursive CTE query ([82991b6](https://github.com/snapotter-hq/snapotter/commit/82991b6a412f84dd2d1d7295379da3cb189d1440)) * **api:** isolate the factory validation scratch dir from the worker's ([7a205ee](https://github.com/snapotter-hq/snapotter/commit/7a205eeb1239f6fa0d1e3c84c744325b9e953237)) * **api:** log only genuine processing faults at error level ([965501a](https://github.com/snapotter-hq/snapotter/commit/965501aef95fff1f5924e030434ea2688c4f0e8c)) * **api:** make OpenAPI spec ASCII-only so Schemathesis can load it ([#344](https://github.com/snapotter-hq/snapotter/issues/344)) ([c2ae334](https://github.com/snapotter-hq/snapotter/commit/c2ae334c81e18561931247db8f8e68ab08c1ef74)) * **api:** narrow friendlyError matching to avoid collapsing valid messages ([6220885](https://github.com/snapotter-hq/snapotter/commit/6220885e0cfd61b57186136aba174f0042dc6457)) * **api:** propagate lenient structural-validation flag to batch + pipeline ([e52e0bb](https://github.com/snapotter-hq/snapotter/commit/e52e0bb3d53bed90a58d0daca15c9aef633d7d02)), closes [#244](https://github.com/snapotter-hq/snapotter/issues/244) * **api:** reject non-PDF inputs in pdf-to-image ([37b9c6d](https://github.com/snapotter-hq/snapotter/commit/37b9c6d7bf0d38ffc48febc324e96288b5f59fd4)) * **api:** respect RATE_LIMIT_PER_MIN for tool routes ([#272](https://github.com/snapotter-hq/snapotter/issues/272)) ([ce02ce1](https://github.com/snapotter-hq/snapotter/commit/ce02ce13486989d51314d2afabbdcaf8e0d2a9f9)), closes [#280](https://github.com/snapotter-hq/snapotter/issues/280) * **api:** return user-safe processing errors, keep raw stderr in logs ([4af4bfa](https://github.com/snapotter-hq/snapotter/commit/4af4bfa8eba5ba059e804af33581ada7250a7d1c)) * **api:** section override for backwards-compat alias routes (adjust-colors) ([fc205c7](https://github.com/snapotter-hq/snapotter/commit/fc205c7428f3d27d542065a70c4a948e4e9742fd)) * **api:** stop leaking raw ffprobe stderr in media validation errors ([3fc4149](https://github.com/snapotter-hq/snapotter/commit/3fc41491437a2968b2ebfd79447d59e68da7ec1d)) * **api:** support sharp 0.35 types ([6f85b3d](https://github.com/snapotter-hq/snapotter/commit/6f85b3d12acac73caf747313511c49c7bdc6c257)) * **api:** wrap role rename and delete in transactions ([b564932](https://github.com/snapotter-hq/snapotter/commit/b5649320833ad0c5d6c57c887ef8587d74564dcb)) * apply processedFileName fallback everywhere processedFilename is used ([857aa75](https://github.com/snapotter-hq/snapotter/commit/857aa75562816dbcc0827eda93125605c495af7c)) * **audio:** low-samplerate ogg encode + post-2.0 QA hygiene ([19d9ed1](https://github.com/snapotter-hq/snapotter/commit/19d9ed181ae0051e0df6a01585036628dd31700a)) * **benchmark:** use section-prefixed tool URLs for 2.0 route scheme ([76fc695](https://github.com/snapotter-hq/snapotter/commit/76fc695233eae54c803ae1730cefb9acd161db45)) * build script venv handling and lint fixes ([b1e94bd](https://github.com/snapotter-hq/snapotter/commit/b1e94bd98851d3cc6da57b343ac8d2528dfda890)) * cache useSyncExternalStore snapshot to prevent infinite re-render ([f68fcb8](https://github.com/snapotter-hq/snapotter/commit/f68fcb8ca6724be0ca83a42593192608cde1a784)) * **ci:** address spec review findings in verify-bundle.sh ([4b5b351](https://github.com/snapotter-hq/snapotter/commit/4b5b35186d925f95566b7d36c9d3994255fc95e2)) * **ci:** deploy landing from dist, not the stale Next.js out path ([#240](https://github.com/snapotter-hq/snapotter/issues/240)) ([44bfca1](https://github.com/snapotter-hq/snapotter/commit/44bfca105fc4bfa1d5d2bfc0da861ed4e0a1e496)) * **ci:** grant ai-bundles reusable call its required token scopes ([03c1a5e](https://github.com/snapotter-hq/snapotter/commit/03c1a5e36f9dd7f904882b7cb19fc27006a61f5d)) * **ci:** harden smoke tests against set -e and fix parameter issues ([efac88c](https://github.com/snapotter-hq/snapotter/commit/efac88c20517c22b3a18a9cb227350cd10bdd3c1)) * **ci:** resolve pre-existing failures making main red ([#250](https://github.com/snapotter-hq/snapotter/issues/250)) ([622c9f9](https://github.com/snapotter-hq/snapotter/commit/622c9f98a5772eae05343407b8408cd7d7539ef9)), closes [#249](https://github.com/snapotter-hq/snapotter/issues/249) [246/#248](https://github.com/snapotter-hq/snapotter/issues/248) * **ci:** revert rembg to 2.0.62 (2.0.75 requires numpy>=2.3) ([3b8d529](https://github.com/snapotter-hq/snapotter/commit/3b8d529b4422deb4d0782a5e4d536328563afd1e)) * clean file info cards for non-native video/media formats on tool page ([511e941](https://github.com/snapotter-hq/snapotter/commit/511e941da0516e27237621be1eeaf6beb64b2d89)) * clear file store when navigating between tools ([f32b3bd](https://github.com/snapotter-hq/snapotter/commit/f32b3bd51f2107040c081d0d9bee5ac5b0450157)) * correct SAML idpCert property name for @node-saml/node-saml v5 ([b9dac59](https://github.com/snapotter-hq/snapotter/commit/b9dac597362e2fbdd90447bfd7889f85dddfff90)) * critical first-login soft-lock in usage survey overlay ([#392](https://github.com/snapotter-hq/snapotter/issues/392)) ([ca076f9](https://github.com/snapotter-hq/snapotter/commit/ca076f91fde252fd98d3014a260d8ae7534481f0)) * **deps:** close js-yaml DoS alert + document rembg non-reachability ([#286](https://github.com/snapotter-hq/snapotter/issues/286)) ([5d5117a](https://github.com/snapotter-hq/snapotter/commit/5d5117acf729d3b2c00119eede9ba20f0aa17a28)) * **deps:** drop undici override (broke jsdom@29) ([5662532](https://github.com/snapotter-hq/snapotter/commit/56625325013b6c8ac47e159a4d517f7eef29a056)) * **deps:** patch Dependabot security alerts ([8792080](https://github.com/snapotter-hq/snapotter/commit/87920809820cb0179c029ccb7234370431abff67)) * **doc-engine:** treat qpdf exit code 3 (warnings) as success, not failure ([2a2151d](https://github.com/snapotter-hq/snapotter/commit/2a2151d7dd19faa1e4d43d49540729dab33a8eed)) * **docker:** copy patches/ before pnpm install so cold builds succeed ([#300](https://github.com/snapotter-hq/snapotter/issues/300)) ([f74f648](https://github.com/snapotter-hq/snapotter/commit/f74f648e47fb76a30b9fa34cd6dc84f4c0295972)) * **docker:** make storage writable under non-root/foreign UIDs (TrueNAS, OpenShift) ([#299](https://github.com/snapotter-hq/snapotter/issues/299)) ([1fec971](https://github.com/snapotter-hq/snapotter/commit/1fec97111bf4cf4620131e38651b8e114c7b0566)), closes [#230](https://github.com/snapotter-hq/snapotter/issues/230) * **docker:** make venv bootstrap upgrade-aware with pip-freeze stamp ([39543d6](https://github.com/snapotter-hq/snapotter/commit/39543d651219d4741868ec7ebe34186aa038a914)), closes [#85](https://github.com/snapotter-hq/snapotter/issues/85) * **docker:** patch OS + pip image CVEs, document accepted Trivy residuals ([#288](https://github.com/snapotter-hq/snapotter/issues/288)) ([c203267](https://github.com/snapotter-hq/snapotter/commit/c203267866aa87994de80d2214f70deff72b7b5f)) * **docker:** repair copied AI venv paths ([#390](https://github.com/snapotter-hq/snapotter/issues/390)) ([7e01d36](https://github.com/snapotter-hq/snapotter/commit/7e01d3637edec10c4b7c73cd6c9d54c6414972f6)), closes [#127](https://github.com/snapotter-hq/snapotter/issues/127) [#127](https://github.com/snapotter-hq/snapotter/issues/127) * **docker:** restore Postgres/Redis in GPU compose stack + pause image publishing ([9b64a96](https://github.com/snapotter-hq/snapotter/commit/9b64a96bcd2e60ce8e3e051a9d2b57811e98a223)) * **e2e,landing:** robust path escaping (CodeQL) + unique file-tools card ([a6837b6](https://github.com/snapotter-hq/snapotter/commit/a6837b687a096b754367223b4472481071a450b7)) * **e2e:** disable Astro Dev Toolbar during landing e2e tests ([2927e0d](https://github.com/snapotter-hq/snapotter/commit/2927e0d4be063353abb9d23494158849ac3a191a)) * **e2e:** wait for post-login redirect before forcing navigation ([#341](https://github.com/snapotter-hq/snapotter/issues/341)) ([5b75d81](https://github.com/snapotter-hq/snapotter/commit/5b75d813b8523fd378c731de76c429fe900d9d28)), closes [#340](https://github.com/snapotter-hq/snapotter/issues/340) * **editor:** apply layer effects + object flip, add Beta badge, repair e2e specs ([3120e67](https://github.com/snapotter-hq/snapotter/commit/3120e6708dd4e0eb39c2d3af01623e8f1e9c4473)), closes [#259](https://github.com/snapotter-hq/snapotter/issues/259) * **editor:** capture document pixels without the zoom/pan transform ([#259](https://github.com/snapotter-hq/snapotter/issues/259)) ([81e16d7](https://github.com/snapotter-hq/snapotter/commit/81e16d7ce6648e3d7acace0b1915fd42774d1096)), closes [#258](https://github.com/snapotter-hq/snapotter/issues/258) * **editor:** fill canvas viewport, fix black rulers, add resizable panel ([#258](https://github.com/snapotter-hq/snapotter/issues/258)) ([063a2e4](https://github.com/snapotter-hq/snapotter/commit/063a2e47e298e41d1115f4e6e92a96922a607ce6)) * enforce file type filtering using tool's acceptedInputs ([adfa532](https://github.com/snapotter-hq/snapotter/commit/adfa53246ae228eebe2fdd071f23a83400f1296c)) * **enterprise:** SCIM token generation, GDPR job cancellation, MFA replay, config redaction, encryption validation, SCIM rate limit ([29dd675](https://github.com/snapotter-hq/snapotter/commit/29dd675f4262ac0380df3113ae140b4fc7330d21)) * **enterprise:** ship enterprise package in prod image + S3, analytics, tracing, queue fixes ([#342](https://github.com/snapotter-hq/snapotter/issues/342)) ([8f4235d](https://github.com/snapotter-hq/snapotter/commit/8f4235d2c664337f3b970b1be5acc6f92474aeb6)), closes [#82](https://github.com/snapotter-hq/snapotter/issues/82) * fetch settings on home page mount so tools are visible ([cf543f6](https://github.com/snapotter-hq/snapotter/commit/cf543f6976166b179deb1e5c0fa993bb9e037f0e)) * file library upload accepts all file types, not just images ([6bcee1e](https://github.com/snapotter-hq/snapotter/commit/6bcee1e0739daaad8c66abcc4a4e1bc00bb40735)) * **files:** record the source tool in toolChain on Save to Files ([#435](https://github.com/snapotter-hq/snapotter/issues/435)) ([47a60e7](https://github.com/snapotter-hq/snapotter/commit/47a60e7fad229a9bb9c8e4f33f152cacb3f3dfb4)) * first-run QA sweep of the single-container image ([#413](https://github.com/snapotter-hq/snapotter/issues/413)) ([bf417a5](https://github.com/snapotter-hq/snapotter/commit/bf417a509e529ee6b39d2d5a13a308172b4d08aa)) * GPU deployment robustness (6 fixes from end-to-end testing on an RTX 4070) ([#334](https://github.com/snapotter-hq/snapotter/issues/334)) ([35e18d8](https://github.com/snapotter-hq/snapotter/commit/35e18d8b79861b4aba46d4cb022be868d4d3e757)) * grey out incompatible files in library instead of hiding them ([3a5d55c](https://github.com/snapotter-hq/snapotter/commit/3a5d55cf268301df158163acbeaeaf50c6625a10)) * handle non-image modalities across uploads, previews, and filenames ([#255](https://github.com/snapotter-hq/snapotter/issues/255)) ([8eee17a](https://github.com/snapotter-hq/snapotter/commit/8eee17aeea41577a55b30ead97ca36224b387c04)) * harden against three production Sentry crashes ([#328](https://github.com/snapotter-hq/snapotter/issues/328)) ([8952e9b](https://github.com/snapotter-hq/snapotter/commit/8952e9ba475000da9d2d8e0959c63f3cf2b4506e)) * harden Docker image and async job responses ([f3342a1](https://github.com/snapotter-hq/snapotter/commit/f3342a1e571db5a12f5d8f659903ffe590fa2044)) * harden install queue/dispatcher lifecycle and repair review-sweep regressions ([#395](https://github.com/snapotter-hq/snapotter/issues/395)) ([b4375e5](https://github.com/snapotter-hq/snapotter/commit/b4375e558dfc5ccf34ee6736b886e90f662b1688)), closes [#388](https://github.com/snapotter-hq/snapotter/issues/388) [#390](https://github.com/snapotter-hq/snapotter/issues/390) [#391](https://github.com/snapotter-hq/snapotter/issues/391) [#392](https://github.com/snapotter-hq/snapotter/issues/392) [#393](https://github.com/snapotter-hq/snapotter/issues/393) [#394](https://github.com/snapotter-hq/snapotter/issues/394) [#392](https://github.com/snapotter-hq/snapotter/issues/392) * **i18n:** complete and correct Italian translation ([#231](https://github.com/snapotter-hq/snapotter/issues/231)) ([#298](https://github.com/snapotter-hq/snapotter/issues/298)) ([c0a8b36](https://github.com/snapotter-hq/snapotter/commit/c0a8b36dcbf56f49fa2e58c8d040171e9e6b63e3)) * **i18n:** complete the Italian feedback translations ([#426](https://github.com/snapotter-hq/snapotter/issues/426)) ([3ae48cc](https://github.com/snapotter-hq/snapotter/commit/3ae48cc76ad4021854a805fcea486f58b045f595)), closes [#425](https://github.com/snapotter-hq/snapotter/issues/425) * **i18n:** complete the Italian translation update ([#438](https://github.com/snapotter-hq/snapotter/issues/438)) ([#450](https://github.com/snapotter-hq/snapotter/issues/450)) ([0fafeb2](https://github.com/snapotter-hq/snapotter/commit/0fafeb26766ed49014d13b649f9b43ffc2fffca5)) * **i18n:** restore accents in Italian loading-message arrays ([#322](https://github.com/snapotter-hq/snapotter/issues/322)) ([29fcc87](https://github.com/snapotter-hq/snapotter/commit/29fcc8770887b981e73a17e43bea79a2f13da1e5)), closes [#298](https://github.com/snapotter-hq/snapotter/issues/298) * **i18n:** translate Arabic (ar) UI strings ([#314](https://github.com/snapotter-hq/snapotter/issues/314)) ([ab37505](https://github.com/snapotter-hq/snapotter/commit/ab37505e681602d67ad447e3ad49588e905d48d9)) * **i18n:** translate Brazilian Portuguese (pt-BR) UI strings ([#307](https://github.com/snapotter-hq/snapotter/issues/307)) ([3900350](https://github.com/snapotter-hq/snapotter/commit/3900350ad56d63e9b8ed119539c94c54faf971e0)) * **i18n:** translate Dutch (nl) UI strings ([#309](https://github.com/snapotter-hq/snapotter/issues/309)) ([d036ff6](https://github.com/snapotter-hq/snapotter/commit/d036ff6d44fa9fd8025d3c38b382127066b248c3)) * **i18n:** translate French (fr) UI strings ([#306](https://github.com/snapotter-hq/snapotter/issues/306)) ([fe5c7c8](https://github.com/snapotter-hq/snapotter/commit/fe5c7c8c8667a24cebcd0af8b68f031ddc01ef15)) * **i18n:** translate German (de) UI strings ([#308](https://github.com/snapotter-hq/snapotter/issues/308)) ([4de24b8](https://github.com/snapotter-hq/snapotter/commit/4de24b8c9e4e703b4fd51965ccb9387e1e09fa59)) * **i18n:** translate Hindi (hi) UI strings ([#316](https://github.com/snapotter-hq/snapotter/issues/316)) ([00c89e4](https://github.com/snapotter-hq/snapotter/commit/00c89e4ae9060c1cc4100340f5db223bfd768e0f)) * **i18n:** translate Indonesian (id) UI strings ([#318](https://github.com/snapotter-hq/snapotter/issues/318)) ([8a8a4f9](https://github.com/snapotter-hq/snapotter/commit/8a8a4f99a431ec10ccfdbb472672e976b5b86db2)) * **i18n:** translate Japanese (ja) UI strings ([#304](https://github.com/snapotter-hq/snapotter/issues/304)) ([d8b037c](https://github.com/snapotter-hq/snapotter/commit/d8b037c8c6e8c6cde9c4c6900c1d5689143f5d5d)) * **i18n:** translate Korean (ko) UI strings ([#305](https://github.com/snapotter-hq/snapotter/issues/305)) ([e7b412f](https://github.com/snapotter-hq/snapotter/commit/e7b412fc097d6c745037781e7478414a33d6db25)) * **i18n:** translate Polish (pl) UI strings ([#312](https://github.com/snapotter-hq/snapotter/issues/312)) ([7ce9c64](https://github.com/snapotter-hq/snapotter/commit/7ce9c64b50c5b1fa1eb153c8635384eb5ae0e03b)) * **i18n:** translate Russian (ru) UI strings ([#311](https://github.com/snapotter-hq/snapotter/issues/311)) ([eb9a14a](https://github.com/snapotter-hq/snapotter/commit/eb9a14a226824047cdf00ac94ef647e2bfdcf23a)) * **i18n:** translate Simplified Chinese (zh-CN) UI strings ([#302](https://github.com/snapotter-hq/snapotter/issues/302)) ([26d8a06](https://github.com/snapotter-hq/snapotter/commit/26d8a0685c6b2a216fd72b9431d18543abfa89ee)) * **i18n:** translate Spanish (es) UI strings ([#301](https://github.com/snapotter-hq/snapotter/issues/301)) ([b3ff8ac](https://github.com/snapotter-hq/snapotter/commit/b3ff8accec5494d2fe97a27355257b3c5fa2f91d)) * **i18n:** translate Swedish (sv) UI strings ([#310](https://github.com/snapotter-hq/snapotter/issues/310)) ([c4ce5f9](https://github.com/snapotter-hq/snapotter/commit/c4ce5f96dfe6daf8e560de34cd748b1795ed12ff)) * **i18n:** translate Thai (th) UI strings ([#319](https://github.com/snapotter-hq/snapotter/issues/319)) ([5a6368d](https://github.com/snapotter-hq/snapotter/commit/5a6368db89df5419885b3f8dc568eeaa16cd8206)) * **i18n:** translate Traditional Chinese (zh-TW) UI strings ([#303](https://github.com/snapotter-hq/snapotter/issues/303)) ([de4d2ed](https://github.com/snapotter-hq/snapotter/commit/de4d2ed166d858530dcbbb0634ddcb9c7536ab07)) * **i18n:** translate Turkish (tr) UI strings ([#315](https://github.com/snapotter-hq/snapotter/issues/315)) ([8c1c2c3](https://github.com/snapotter-hq/snapotter/commit/8c1c2c310eac95d5a75fcfd563b9026dba9a4fae)) * **i18n:** translate Ukrainian (uk) UI strings ([#313](https://github.com/snapotter-hq/snapotter/issues/313)) ([6ee1b0f](https://github.com/snapotter-hq/snapotter/commit/6ee1b0f7a1b58dd7ae113fc4268067e0ac1e0b3c)) * **i18n:** translate Vietnamese (vi) UI strings ([#317](https://github.com/snapotter-hq/snapotter/issues/317)) ([4702721](https://github.com/snapotter-hq/snapotter/commit/470272169d947e27ff826e2c0e24e1553eda0543)) * **image-engine:** support sharp 0.35 types ([2137be4](https://github.com/snapotter-hq/snapotter/commit/2137be479e1a23e163587acd1609e77058e9e134)) * **jobs:** pre-warm QueueEvents to kill first-sync-wait flake ([#285](https://github.com/snapotter-hq/snapotter/issues/285)) ([dba8a85](https://github.com/snapotter-hq/snapotter/commit/dba8a85a8013231945741a8fabd09ed86db0d963)) * **jobs:** strip internal paths from all worker SSE error frames ([fc718c1](https://github.com/snapotter-hq/snapotter/commit/fc718c168487de1213c978797c3fc84288f26513)) * **landing:** add www redirect, noindex JS chunks, and website badge ([47b6984](https://github.com/snapotter-hq/snapotter/commit/47b6984be0c8d8de07e0770a34d61a9795b71eaf)) * **lint:** biome-format tool-factory and json-xml to green apps/api lint ([#252](https://github.com/snapotter-hq/snapotter/issues/252)) ([7865339](https://github.com/snapotter-hq/snapotter/commit/7865339fc8c3b8696af5919212ddba4120c07f23)), closes [#251](https://github.com/snapotter-hq/snapotter/issues/251) * **lint:** clear remaining biome errors (unused code, optional chains, non-null assertions, effect deps) ([19dc6ba](https://github.com/snapotter-hq/snapotter/commit/19dc6ba554a05f531db01f23ce3e71297f651f81)) * **lint:** make husky hook executable; rename backend useS3 to isS3Enabled (clears 17 false-positive useHookAtTopLevel) ([7561f2a](https://github.com/snapotter-hq/snapotter/commit/7561f2a8c3a92c412f0d38b9f1323aa8bcfcf4a4)) * **lint:** resolve [#280](https://github.com/snapotter-hq/snapotter/issues/280) Lint failures (route formatting + landing import sort) ([6e1b9cd](https://github.com/snapotter-hq/snapotter/commit/6e1b9cd3cc3b33b18724eb071f3ad4023ab1ee80)) * make search bar full-width to align with tabs and grid ([207c1c3](https://github.com/snapotter-hq/snapotter/commit/207c1c348be5af23c793a96bf07b9f7b7c26ce31)) * **media:** encode gif-to-video WebM as yuv420p ([e96c314](https://github.com/snapotter-hq/snapotter/commit/e96c314ab9b049c3b01d49ff2622d2a351962cd9)) * **migrator:** correct and harden the 1.x to 2.0 SQLite import ([#434](https://github.com/snapotter-hq/snapotter/issues/434)) ([dadf766](https://github.com/snapotter-hq/snapotter/commit/dadf76689933faa8208de9730525409e2497518f)) * **nightly:** de-flake matrix timeouts, exclude browser tool from fuzz ([#349](https://github.com/snapotter-hq/snapotter/issues/349)) ([bbad953](https://github.com/snapotter-hq/snapotter/commit/bbad953e79a132007490c17dab2b774c4b8ae697)), closes [#347](https://github.com/snapotter-hq/snapotter/issues/347) * **nightly:** qpdf in test image, NUL-byte settings, AI sub-path fuzz exclude ([#348](https://github.com/snapotter-hq/snapotter/issues/348)) ([078743d](https://github.com/snapotter-hq/snapotter/commit/078743d6b28aa4078f213cae4c39a3b99e515d8d)), closes [#346](https://github.com/snapotter-hq/snapotter/issues/346) [#346](https://github.com/snapotter-hq/snapotter/issues/346) * **normalize-audio:** preserve source sample rate after loudnorm ([#248](https://github.com/snapotter-hq/snapotter/issues/248)) ([1548d47](https://github.com/snapotter-hq/snapotter/commit/1548d475ca3d1ace0f14d24ecc5e9a13ca5770a2)) * offline CodeFormer face-enhance (ship RealESRGAN_x2plus in upscale-enhance bundle) ([#433](https://github.com/snapotter-hq/snapotter/issues/433)) ([cf884b5](https://github.com/snapotter-hq/snapotter/commit/cf884b52cdf4e8852e0cd24215b22ed2220230da)) * **passport-photo:** require the face-detection bundle, not just background-removal ([#329](https://github.com/snapotter-hq/snapotter/issues/329)) ([32c1192](https://github.com/snapotter-hq/snapotter/commit/32c1192d635898012af2ff14cdbd68c0acd6a3e1)), closes [#327](https://github.com/snapotter-hq/snapotter/issues/327) [#327](https://github.com/snapotter-hq/snapotter/issues/327) * PDF tool QA sweep - library auto-save versioning, AI fileId threading, modality polish ([#251](https://github.com/snapotter-hq/snapotter/issues/251)) ([08961fc](https://github.com/snapotter-hq/snapotter/commit/08961fcc8941bada2608e386bfa6d6b12e996f35)) * post-2.0 audit bug fixes (404 route, worker logging, outpaint gate, pandoc path) ([2bd3e23](https://github.com/snapotter-hq/snapotter/commit/2bd3e2302ad11b306971d0f651f8ad1ee1e9b785)) * prevent double scrollbar by locking html/body overflow ([914ff1b](https://github.com/snapotter-hq/snapotter/commit/914ff1b1aab345237f325cd152bd3ebc693bab52)) * preview generation works for processed results too ([b93dc95](https://github.com/snapotter-hq/snapotter/commit/b93dc95bcaa197cfd4b29c030a04decaa7babcf8)) * QA sweep - tool routes, security, i18n, a11y, + AI bundle install hardening ([#393](https://github.com/snapotter-hq/snapotter/issues/393)) ([b37faed](https://github.com/snapotter-hq/snapotter/commit/b37faed95fc3d2f51c78f40954fdbb5c7b94779d)), closes [hi#resolution](https://github.com/hi/issues/resolution) [hi#severity](https://github.com/hi/issues/severity) * reassign 4 tools to correct display modes ([619f61b](https://github.com/snapotter-hq/snapotter/commit/619f61b4700c9fd3b21f90b7c9512672fae57dab)) * release-acceptance QA follow-ups (upload crash, scipy ABI conflict, rate limit, OCR fallback) ([#458](https://github.com/snapotter-hq/snapotter/issues/458)) ([60d01ab](https://github.com/snapotter-hq/snapotter/commit/60d01ab2ddfad4bf837d30369c2f39e9734cb571)), closes [#413](https://github.com/snapotter-hq/snapotter/issues/413) [#437](https://github.com/snapotter-hq/snapotter/issues/437) * remove all legacy redirects from routes ([fd26fa3](https://github.com/snapotter-hq/snapotter/commit/fd26fa35868b75ca7fd352115396ec9b23dd4280)) * remove automatic third-party egress of user data + optional strict offline mode (OSM tiles, Scalar fonts, editor fonts, AI model downloads) ([#422](https://github.com/snapotter-hq/snapotter/issues/422)) ([6e3a14e](https://github.com/snapotter-hq/snapotter/commit/6e3a14ec6bfc15f18aef3c7aa20cde6d4823dc29)) * remove double scrollbar on home page ([ae95976](https://github.com/snapotter-hq/snapotter/commit/ae959760e3fec115021e2ada7af579ecd13f181c)) * remove duplicated 1.x migration callout in README ([#456](https://github.com/snapotter-hq/snapotter/issues/456)) ([2a899ef](https://github.com/snapotter-hq/snapotter/commit/2a899ef9041c3c637380a91e532273a3581a19d1)), closes [#448](https://github.com/snapotter-hq/snapotter/issues/448) [#454](https://github.com/snapotter-hq/snapotter/issues/454) * remove redundant Getting Started section from home page ([287f6f1](https://github.com/snapotter-hq/snapotter/commit/287f6f15ded4b84e9d0f019522915ccac822d083)) * repair docker validation QA tooling, dispatcher crash-accounting, and image-enhancement RAW hang ([#391](https://github.com/snapotter-hq/snapotter/issues/391)) ([bd1838e](https://github.com/snapotter-hq/snapotter/commit/bd1838e40b0d11715eaf9eff6b4152a707a29b5b)) * repair URL import (DNS-pinned fetch on Node 22 + non-image modalities) ([#246](https://github.com/snapotter-hq/snapotter/issues/246)) ([8f6312c](https://github.com/snapotter-hq/snapotter/commit/8f6312c521246215ef1a27c65475aa2005e409e0)) * resolve 18 QA-discovered bugs across tools, previews, and the AI pipeline ([#242](https://github.com/snapotter-hq/snapotter/issues/242)) ([d8cf979](https://github.com/snapotter-hq/snapotter/commit/d8cf979d4ba31b802c254f7eeb5ef50b424a56b7)) * resolve 6 bugs from enterprise audit (SIEM cursor, legal hold join, SCIM role, GDPR self-purge, export OOM, quota check) ([7f62b1b](https://github.com/snapotter-hq/snapotter/commit/7f62b1bf12d2cf1baaf5586b201458eab100a111)) * resolve hardcoded /app paths and loosen mediapipe pin for native installs ([60e3ac2](https://github.com/snapotter-hq/snapotter/commit/60e3ac2210f93a350729246cf2b4bb303ab2ebc7)), closes [community-scripts/ProxmoxVE#14720](https://github.com/community-scripts/ProxmoxVE/issues/14720) * resolve Sharp 0.35.1 and BullMQ type incompatibilities after dep bumps ([b76dc68](https://github.com/snapotter-hq/snapotter/commit/b76dc68682c664d4c6a22cf921e786d4c010b757)) * Save to Files shows green success state with checkmark after saving ([f4061fe](https://github.com/snapotter-hq/snapotter/commit/f4061fe4b0417ba896de138a791cfc869d3b33f3)) * **security:** basename-sanitize file-preview paths (CodeQL js/path-injection) ([7a3b4e6](https://github.com/snapotter-hq/snapotter/commit/7a3b4e6b3bbdee7c382bd4ad739485b37bb45f46)) * **security:** close file-preview path-injection + tighten subtitle detection ([c1cd871](https://github.com/snapotter-hq/snapotter/commit/c1cd8712f45d9defd5321f2d683cf207ee9d3740)) * **security:** close remaining high-severity CodeQL alerts ([bdadb84](https://github.com/snapotter-hq/snapotter/commit/bdadb843d8238d738e9f849f1754765f5de82411)), closes [hi#severity](https://github.com/hi/issues/severity) * **security:** explicit per-route rate limits (CodeQL js/missing-rate-limiting) ([ae4fc1d](https://github.com/snapotter-hq/snapotter/commit/ae4fc1decf006b15a2f747cde07d4c1e35c5de13)) * **security:** harden auth and outbound fetches ([c6319cf](https://github.com/snapotter-hq/snapotter/commit/c6319cf8a9efe8745a29339613002c22f82e5393)) * **security:** harden rate limits, Redis auth, resource caps, and error sanitization ([d612264](https://github.com/snapotter-hq/snapotter/commit/d61226496b5745ff7f57ee8138009d4f81826095)) * **security:** numeric CIDR matching for IPv6 SSRF allow/deny ([f75cc32](https://github.com/snapotter-hq/snapotter/commit/f75cc328acd18b4714291400ac348058db6d28d8)) * send auth token with preview generation request ([6090688](https://github.com/snapotter-hq/snapotter/commit/609068870842629e085a77d9d5144c5102beae19)) * set a writable HOME for the app user so PaddleOCR works in non-root deployments ([#430](https://github.com/snapotter-hq/snapotter/issues/430)) ([e0dbf2a](https://github.com/snapotter-hq/snapotter/commit/e0dbf2a5c3cc9622218d31698452697957936e00)) * settings dialog and settings API correctness bugs ([8e9452e](https://github.com/snapotter-hq/snapotter/commit/8e9452e65073c500098fde040ce021e3b1c39639)) * show all tools on All tab, remove Popular and Browse sections ([b166f47](https://github.com/snapotter-hq/snapotter/commit/b166f47de515739d87a14ae408a351f81dd37c00)) * show image viewer for video-to-gif/webp results instead of broken video player ([90acd5b](https://github.com/snapotter-hq/snapotter/commit/90acd5bcd905f461f28a5b511c619d896d4a6724)) * show modality starting points in landing command center ([#387](https://github.com/snapotter-hq/snapotter/issues/387)) ([852f6ce](https://github.com/snapotter-hq/snapotter/commit/852f6cecba106eb9d000f95fc1ae9863157a5d3b)) * show tool-specific accepted formats in dropzone, remove privacy note ([5241ccd](https://github.com/snapotter-hq/snapotter/commit/5241ccd1247bda2d9e634576354f3b14a4077c63)) * sort enterprise exports for Biome lint compliance ([3b7f44e](https://github.com/snapotter-hq/snapotter/commit/3b7f44e50e450bff62560b9f21cb12330b0b2b82)) * stamp SnapOtter as Producer on generated PDFs ([#416](https://github.com/snapotter-hq/snapotter/issues/416)) ([8b3f1e6](https://github.com/snapotter-hq/snapotter/commit/8b3f1e6884361ef080c0165059bd8fdb4a14fd79)) * sync demo theme with app ([f6f7b5a](https://github.com/snapotter-hq/snapotter/commit/f6f7b5a4bc2867f680441a91a9af9e1bd148edf4)) * test server registration gaps, Redis subscriber cleanup, atomic settings upsert ([954cfb0](https://github.com/snapotter-hq/snapotter/commit/954cfb01a657ec49293a4e10e72e23eb69e4d9b2)) * **test:** align analytics-env test with ANALYTICS_ENABLED=true default ([96764ec](https://github.com/snapotter-hq/snapotter/commit/96764ec375189ebec396d0397b116407bfd75e05)) * **test:** mock db/index.js in unit tests that import API modules ([5b3b3c7](https://github.com/snapotter-hq/snapotter/commit/5b3b3c76329d62636c886dfa798b9e14acd7cc90)) * **test:** repair integration suite after analytics column/endpoint removal ([#340](https://github.com/snapotter-hq/snapotter/issues/340)) ([6917a8b](https://github.com/snapotter-hq/snapotter/commit/6917a8b0c7864fc9b244ecda23dcdbcbf02f9733)), closes [#336](https://github.com/snapotter-hq/snapotter/issues/336) * **test:** resolve CI failures from the overhaul ([34b006d](https://github.com/snapotter-hq/snapotter/commit/34b006ded772b96d7b4336e5ffcc67e1039253c3)) * **tests:** section-prefix tool API URLs across overhauled suite ([d4dc2ea](https://github.com/snapotter-hq/snapotter/commit/d4dc2eae5db66b098d8a4e735ab61053ddb50635)), closes [#280](https://github.com/snapotter-hq/snapotter/issues/280) * **test:** update import paths for cleanup.test.ts after move to integration ([78679c5](https://github.com/snapotter-hq/snapotter/commit/78679c57f46d11d89dcb384373a63e28e1a75635)) * **tools:** honest content-type for edit-metadata pass-through ([#350](https://github.com/snapotter-hq/snapotter/issues/350)) ([88af8d4](https://github.com/snapotter-hq/snapotter/commit/88af8d46fb001dd019de54e48dd7c73c5feaea73)) * **tools:** surface chars count in pdf-to-text result payload ([3c44335](https://github.com/snapotter-hq/snapotter/commit/3c4433583b836e53ee2a35b79c8d9be07760992e)) * top nav respects dark mode theme ([43b1901](https://github.com/snapotter-hq/snapotter/commit/43b190134e8858301fa3bffd1882260d6928c441)) * **ui:** constrain preview dropzone height in pipeline builder ([931e15a](https://github.com/snapotter-hq/snapotter/commit/931e15a6bd04fc84d236b41dbbd7df0feefe29a9)) * **ui:** show repair UI when AI bundle models are broken ([#214](https://github.com/snapotter-hq/snapotter/issues/214)) ([edea82b](https://github.com/snapotter-hq/snapotter/commit/edea82ba27cd92aa5188144e525f9889b6ba1b9d)) * update privacy policy to reference PostgreSQL instead of SQLite ([5af1ac4](https://github.com/snapotter-hq/snapotter/commit/5af1ac4dcf0c8ff17bdcc0efc6c179afc8543168)) * use media-player for all video/audio tools that had no-comparison or side-by-side ([69300b5](https://github.com/snapotter-hq/snapotter/commit/69300b5c83f43ebde213473f66d9f255e33cf9dc)) * use processedFileName fallback for non-native format detection after processing ([14ded6f](https://github.com/snapotter-hq/snapotter/commit/14ded6fbd0babb43de8a544527bb2293b9d83b2d)) * validate non-image inputs by modality (batch + pipeline) ([#244](https://github.com/snapotter-hq/snapotter/issues/244)) ([03e7123](https://github.com/snapotter-hq/snapotter/commit/03e71236f93853e28d7ad8428fe8a9b918849773)) * **web:** add modality to fuse search keys, merge docs+files in fullscreen grid ([3114323](https://github.com/snapotter-hq/snapotter/commit/3114323d07a941cfcb261bc245250a8f3f6e8222)) * **web:** point tool keyboard shortcuts at section routes ([0689ae5](https://github.com/snapotter-hq/snapotter/commit/0689ae554fa353a231f01e4dffd3ac362afcb3ba)) * **web:** resolve feature install status sync and mutual exclusivity ([#214](https://github.com/snapotter-hq/snapotter/issues/214)) ([492da82](https://github.com/snapotter-hq/snapotter/commit/492da820f8ce298addd3038dad2f55e91cdb12bd)) * **web:** restore preview panel rendering for all file types ([1181b1f](https://github.com/snapotter-hq/snapotter/commit/1181b1fe22c7f5a998f8954f9e02a184a3513cf8)) * **web:** show modality thumbnails for non-image files in the strip ([#245](https://github.com/snapotter-hq/snapotter/issues/245)) ([aa3ae6e](https://github.com/snapotter-hq/snapotter/commit/aa3ae6ec915821d664cef0c1537e2b64d9a6fcee)) * **web:** update dropzone to accept all file types, not just images ([b8b6b0a](https://github.com/snapotter-hq/snapotter/commit/b8b6b0a44ada1670e4e41bcf6cd22f713d14c512)) * **web:** wrap modality tabs to prevent overflow in narrow sidebar ([dab31d6](https://github.com/snapotter-hq/snapotter/commit/dab31d6e32c7eee95199d7a686d507a98d58138f)) ### Features * add a Keep it free sponsor button to the top nav ([#427](https://github.com/snapotter-hq/snapotter/issues/427)) ([7b04317](https://github.com/snapotter-hq/snapotter/commit/7b04317ed20e062c273fe60a19cdcaac2b50e651)) * add AES-256-GCM encryption at rest for sensitive settings ([2520cdd](https://github.com/snapotter-hq/snapotter/commit/2520cdd556c8a5946b4eb6426aebc8811944e8d9)) * add audio waveform visualization with wavesurfer.js ([d8a8e05](https://github.com/snapotter-hq/snapotter/commit/d8a8e055906eeab9d1f9a048c4f8d5517cff8f80)) * add backup status tracking endpoints ([2aea351](https://github.com/snapotter-hq/snapotter/commit/2aea351f70cfd171befad164bc553e7feb998884)) * add bundle build script for CI ([52b9405](https://github.com/snapotter-hq/snapotter/commit/52b940585afa1788119dc50f6d44e98f32192ad3)) * add CI workflow for building and publishing AI bundles ([7dabfe2](https://github.com/snapotter-hq/snapotter/commit/7dabfe293dd171bb7b7ec6909ced85b178e67961)) * add Cmd+Enter (process) and Cmd+S (download) keyboard shortcuts ([7c9ca85](https://github.com/snapotter-hq/snapotter/commit/7c9ca85952bc155580becc8f95125482875a3ed5)) * add enterprise Phase 1-4 feature flags and new permissions ([86d6f50](https://github.com/snapotter-hq/snapotter/commit/86d6f50ea6696032bed8f24ba0fd58fe54af5887)) * add full-width dropzone state and tool branding to tool page ([f2ac057](https://github.com/snapotter-hq/snapotter/commit/f2ac05747e1f3ffde4f2e3b3bf321237ef699e85)) * add GET /api/v1/tools/popular endpoint ([1107005](https://github.com/snapotter-hq/snapotter/commit/110700520cfaf4c70e54ff11e7cdee7f7cf50f66)) * add landing tool command center ([#386](https://github.com/snapotter-hq/snapotter/issues/386)) ([3b1d484](https://github.com/snapotter-hq/snapotter/commit/3b1d484b4d4cc9e9da843ceeb442c6dbf7c8066c)) * add OpenTelemetry distributed tracing (enterprise) ([#232](https://github.com/snapotter-hq/snapotter/issues/232)) ([3fb8164](https://github.com/snapotter-hq/snapotter/commit/3fb8164fa539ef952fddcef89bcec01097db991e)) * add page-level drop overlay and paste handler on tool page ([6ea515c](https://github.com/snapotter-hq/snapotter/commit/6ea515ccdd7cd35f3727d0cf4137b81e9bdea050)) * add per-tool permission model with category and per-tool modes ([9fa23f4](https://github.com/snapotter-hq/snapotter/commit/9fa23f454322808d8c791b9d26b6bdbd1a5e9e73)) * add per-user rate limiting and concurrent job limits ([239f85f](https://github.com/snapotter-hq/snapotter/commit/239f85f098c5c6d3576531e915f57f6128bec357)) * add PostHog customer feedback ([649e65b](https://github.com/snapotter-hq/snapotter/commit/649e65b035c6efbfbe32e4b1db040aa0f9f6ac81)) * add recent tools tracking via localStorage ([6c61ae4](https://github.com/snapotter-hq/snapotter/commit/6c61ae47f496b1aaf937228fe7c55058b0b0756f)) * add request correlation IDs to audit logs and response headers ([1cf1f47](https://github.com/snapotter-hq/snapotter/commit/1cf1f47d6f0554853a501ae1220dbdc0678820cb)) * add session idle timeout and concurrent session limit ([3cc4ef6](https://github.com/snapotter-hq/snapotter/commit/3cc4ef6895ddfc904252e4e99c48d5df41b4c17e)) * add settings slide-in, review panel with size delta, start-over preserving settings ([45121c1](https://github.com/snapotter-hq/snapotter/commit/45121c1a1e8f8f4ab8cbf9601c50faf4a2237803)) * add Sign PDF tool (draw/type/upload signatures, place on a PDF) ([#370](https://github.com/snapotter-hq/snapotter/issues/370)) ([0cdd560](https://github.com/snapotter-hq/snapotter/commit/0cdd560ac46827f7e103e9f1921aec58d226a7db)) * add storage usage tracking with DB counters and reconciliation ([aaa8a37](https://github.com/snapotter-hq/snapotter/commit/aaa8a37c9b3b490a8455311be89a0bd4b858a897)) * add team-level storage quotas with enforcement on upload and save ([d064286](https://github.com/snapotter-hq/snapotter/commit/d0642865590a56769adbc2d7bc6741a12800af52)) * add TopNav and AvatarDropdown components ([f79958a](https://github.com/snapotter-hq/snapotter/commit/f79958a6229015ad64149dadc1fe27909f314a57)) * add usage onboarding survey overlay ([#388](https://github.com/snapotter-hq/snapotter/issues/388)) ([a0d1c70](https://github.com/snapotter-hq/snapotter/commit/a0d1c70172f24af0d4656b6256fc1bfcb9256e69)) * add webhook delivery module with retry and backoff ([ab88b9a](https://github.com/snapotter-hq/snapotter/commit/ab88b9ad0d9104ae69862309f9d2b35c0251d6bc)) * **ai:** add a Reset AI Environment admin feature for the upgrade gap ([#459](https://github.com/snapotter-hq/snapotter/issues/459)) ([fb96cf8](https://github.com/snapotter-hq/snapotter/commit/fb96cf874364b331f152d414b69f8831d0004d07)) * All tab groups tools by modality with collapsible sections ([e7126f9](https://github.com/snapotter-hq/snapotter/commit/e7126f92931e1c0277aca6c56ef06276d961ef64)) * all-in-one embedded single-container mode ([#377](https://github.com/snapotter-hq/snapotter/issues/377)) ([084a9c9](https://github.com/snapotter-hq/snapotter/commit/084a9c9faa48a0b090b1d74be97297a3d5d6f727)) * **analytics:** build-time bake + telemetry depth ([#336](https://github.com/snapotter-hq/snapotter/issues/336)) ([5d36ac0](https://github.com/snapotter-hq/snapotter/commit/5d36ac06d88fc4ca3dbf48294c132249921207d9)) * **analytics:** inject Sentry DSN + PostHog key from build env ([#367](https://github.com/snapotter-hq/snapotter/issues/367)) ([9819c58](https://github.com/snapotter-hq/snapotter/commit/9819c5885eab3ea9857dc3b4ca4465fb4b0994f9)), closes [#336](https://github.com/snapotter-hq/snapotter/issues/336) * **analytics:** upload web source maps to Sentry + tie release to build ([#369](https://github.com/snapotter-hq/snapotter/issues/369)) ([1c202c6](https://github.com/snapotter-hq/snapotter/commit/1c202c6ef08943f05d31fd4d83dff817e1c1503b)) * **api:** section-prefix all custom tool route literals ([10bb73f](https://github.com/snapotter-hq/snapotter/commit/10bb73ffc116814f4dc6ba9c33ed32d8d32d912d)) * **api:** section-prefix factory + batch routes via apiToolPath (+section validation) ([68dd7da](https://github.com/snapotter-hq/snapotter/commit/68dd7dabaa7a9e6d87017b257b5c8cb0f34ae90e)) * arrow key navigation in Files list ([52693fc](https://github.com/snapotter-hq/snapotter/commit/52693fc843143b9ac2d788fb9b5321ee3a52409f)) * **audit:** add TOOL_EXECUTED logging with opt-in setting ([36f083b](https://github.com/snapotter-hq/snapotter/commit/36f083ba64bfa2063c724223c3d59ffadb626cb5)) * **audit:** capture IP address, make TRUST_PROXY configurable ([5d2f520](https://github.com/snapotter-hq/snapotter/commit/5d2f520d7823969578945acfd3e6799bfd6ff3f7)) * **audit:** extensible event type system with shared constants ([37b2b9c](https://github.com/snapotter-hq/snapotter/commit/37b2b9c2eef0e2926dbee03f6b24f16eb53f544e)) * **automate:** make the pipeline builder fully multi-modal ([#335](https://github.com/snapotter-hq/snapotter/issues/335)) ([a53038e](https://github.com/snapotter-hq/snapotter/commit/a53038ed9610a964090a98f6973a25449a1e4a9f)) * bump feature manifest to v2 with archive metadata ([a4ac7cf](https://github.com/snapotter-hq/snapotter/commit/a4ac7cf7d66240f64fc7c394711a4ab5b5036056)) * **ci:** add verify job to ai-bundles workflow ([7d09927](https://github.com/snapotter-hq/snapotter/commit/7d099274c120c28845ab40fa8b00754015552901)) * **ci:** add verify-bundle.sh for AI bundle smoke testing ([5ee948d](https://github.com/snapotter-hq/snapotter/commit/5ee948d36a998f8a39b92d31cc9e3def331535e8)) * clean preview button with progress bar, add document preview support ([3decfaa](https://github.com/snapotter-hq/snapotter/commit/3decfaae3ea0180415851cacfc88674b50418c01)) * clean tool page nav, add Import from Files on dropzone ([b5eef64](https://github.com/snapotter-hq/snapotter/commit/b5eef644e3c932b18884141055b65a7904d57665)) * copy-primary for data tools, download-all label for multi-output, batch failure display ([bc3ad2b](https://github.com/snapotter-hq/snapotter/commit/bc3ad2b008e789b92597688923690f28d5cf54ed)) * **db:** add audit integrity/requestId columns, user_preferences table, audit indexes ([cafd2d8](https://github.com/snapotter-hq/snapotter/commit/cafd2d8b6547eccdb9735acf344207534c13aeae)) * **db:** add data lifecycle columns (deleteAfter, legalHold, quotas, retention) ([7e5843c](https://github.com/snapotter-hq/snapotter/commit/7e5843cd403b2d59d844d5a1d8d3a9ccb0618899)) * **db:** add identity columns (lastActivity, toolPermissions, TOTP) ([7ed043e](https://github.com/snapotter-hq/snapotter/commit/7ed043ec5301106ad64ec0accc7ce411d818a469)) * disable auto-save, add Save to Files button, accept all file types in library ([d0795b6](https://github.com/snapotter-hq/snapotter/commit/d0795b69eaecf61cdb65377ee5561fca64c1de26)) * **docs:** Two-Doors home, otter-orange brand, Pagefind search, and enterprise SSO/SCIM/roles guides ([91ac583](https://github.com/snapotter-hq/snapotter/commit/91ac583e873d70fed01ecdb337c60a0234ebdc1d)) * **enterprise:** add audit log archival with crash-safe state machine ([c1dc27f](https://github.com/snapotter-hq/snapotter/commit/c1dc27f2484120f7f4571c8472fccd292e43f259)) * **enterprise:** add audit log export endpoint (CSV/JSON) ([913dd6b](https://github.com/snapotter-hq/snapotter/commit/913dd6bbe1518e7b709dd002329417789e103f49)) * **enterprise:** add configuration export/import with dry-run and dependency validation ([0f883fe](https://github.com/snapotter-hq/snapotter/commit/0f883fe853fb818275bcdb44248f99e24ca33083)) * **enterprise:** add GDPR user data export (async) ([b6a8226](https://github.com/snapotter-hq/snapotter/commit/b6a82268377bc331e38e65dcf80fe60aec6a2ff2)) * **enterprise:** add GDPR user/team data purge with audit redaction ([dd2a507](https://github.com/snapotter-hq/snapotter/commit/dd2a50799a255a05e732de5943a7481b91b2c86d)) * **enterprise:** add IP allowlisting with CIDR matching and Redis cache ([db6f7bf](https://github.com/snapotter-hq/snapotter/commit/db6f7bf38af677f896a69ea75c2cd68ec05bffb7)) * **enterprise:** add legal hold with cleanup bypass ([fa7da7c](https://github.com/snapotter-hq/snapotter/commit/fa7da7ce0c3bf480a59b429c1ad39ab23fe7cf18)) * **enterprise:** add per-team retention overrides with deleteAfter ([b60f550](https://github.com/snapotter-hq/snapotter/commit/b60f550b3fa54c4b10681e6281e989678b6c955a)) * **enterprise:** add SAML 2.0 SSO with SP-initiated login ([54132d1](https://github.com/snapotter-hq/snapotter/commit/54132d1833439425825954c4c55fba7975e24d0a)) * **enterprise:** add SCIM 2.0 provisioning (Users + Groups) ([a1b5c6d](https://github.com/snapotter-hq/snapotter/commit/a1b5c6d2c30c8a195a17b534a18c5fb93733135a)) * **enterprise:** add SIEM webhook forwarding with circuit breaker ([d3f30a2](https://github.com/snapotter-hq/snapotter/commit/d3f30a2f5d1d846bb4d56a3d2f0c208065258ba8)) * **enterprise:** add SSO enforcement mode with break-glass admin ([0c4468a](https://github.com/snapotter-hq/snapotter/commit/0c4468a004c228e860912dd8e3e662d270d3d113)) * **enterprise:** add tamper-resistant audit mode with HMAC integrity ([895e29e](https://github.com/snapotter-hq/snapotter/commit/895e29e93fb141a279dcd090ad0199f248faed2f)) * **enterprise:** add TOTP MFA with enrollment, verification, and recovery codes ([1787be3](https://github.com/snapotter-hq/snapotter/commit/1787be35fe4b6d3b1f313511cc36c2277df64034)) * **enterprise:** add unified webhook system with admin alerts ([d86e458](https://github.com/snapotter-hq/snapotter/commit/d86e4585e4e1069fa95aa49de951827fbdccf8f3)) * **enterprise:** add upgrade management endpoints (version, migrations, readiness) ([03e12e6](https://github.com/snapotter-hq/snapotter/commit/03e12e6f0b92308dc311a33a848cf09cd7e74bfd)) * expand alternatives comparisons ([#384](https://github.com/snapotter-hq/snapotter/issues/384)) ([174001d](https://github.com/snapotter-hq/snapotter/commit/174001d3844172fbc8d7dad8282ef1d83a8e4d7f)) * expand Prometheus metrics with request duration, storage, and auth counters ([fb14f41](https://github.com/snapotter-hq/snapotter/commit/fb14f41512e8d65417b6a7dee129d48f05285459)) * extend crash recovery for pre-built bundle artifacts ([d1e9536](https://github.com/snapotter-hq/snapotter/commit/d1e9536cffb7a53a291627bd36d173d850082a41)) * extend health endpoints with disk space, S3, storage, and backup checks ([6237684](https://github.com/snapotter-hq/snapotter/commit/6237684ec86289fdfab5ed982dd2af6a9a5e37d1)) * extend importBundleArchive for site-packages and fixups ([5d5240e](https://github.com/snapotter-hq/snapotter/commit/5d5240e48131653e3a64917fae312a044326992c)) * **feedback:** always-on nav button with GitHub/email handoff when analytics is off ([#428](https://github.com/snapotter-hq/snapotter/issues/428)) ([5dcc06a](https://github.com/snapotter-hq/snapotter/commit/5dcc06a99ea18a6b5448b3a7a1e54b40158c8b07)) * **feedback:** route failed-run Report issue through the offline handoff ([#429](https://github.com/snapotter-hq/snapotter/issues/429)) ([8cdd85a](https://github.com/snapotter-hq/snapotter/commit/8cdd85a49339c2cce3c916b756e4c6da1fe2abfc)) * filter files by modality when importing from tool page ([826f1ef](https://github.com/snapotter-hq/snapotter/commit/826f1efc087d1708ee1171b145f710e57a9d7ed2)) * **i18n:** add repair UI strings for broken AI bundles ([8e15fe7](https://github.com/snapotter-hq/snapotter/commit/8e15fe7a3f633771ba05e1b4cb2f3eae15b5bed0)) * **i18n:** raise translation coverage across all 20 locales ([#332](https://github.com/snapotter-hq/snapotter/issues/332)) ([ffbf4f9](https://github.com/snapotter-hq/snapotter/commit/ffbf4f9e10f5e8f4fde9be286e0e7a024dde7a15)) * **i18n:** raise translation coverage across all 20 locales (round 2) ([#453](https://github.com/snapotter-hq/snapotter/issues/453)) ([44e1f90](https://github.com/snapotter-hq/snapotter/commit/44e1f90e4a847b7059869cd5750280f472ef3a05)), closes [#428](https://github.com/snapotter-hq/snapotter/issues/428) [425/#426](https://github.com/snapotter-hq/snapotter/issues/426) * Import from Files works, remove pipeline button from files page ([b8a6b20](https://github.com/snapotter-hq/snapotter/commit/b8a6b2018ed1736ab4f9f234b435bce666c10d90)) * inline error messages with recovery actions ([56cd843](https://github.com/snapotter-hq/snapotter/commit/56cd843482ab93d59f26fc360fa48d11f161c815)) * **landing,docs:** SEO fixes and query-matched tool pages ([#383](https://github.com/snapotter-hq/snapotter/issues/383)) ([ec98dfd](https://github.com/snapotter-hq/snapotter/commit/ec98dfde9a63590f513c1448a18a57f836ad1515)) * **landing:** add animated shadergradient hero background ([#411](https://github.com/snapotter-hq/snapotter/issues/411)) ([5500fac](https://github.com/snapotter-hq/snapotter/commit/5500facc5d8d38437bd976663a10b41ba71bee10)) * **landing:** auto-refresh live GitHub stars and image-pull stats ([#292](https://github.com/snapotter-hq/snapotter/issues/292)) ([33671d2](https://github.com/snapotter-hq/snapotter/commit/33671d2d9227ffbb3580e8b7d40fd260c06d7853)) * **landing:** enterprise-focused hero redesign and section polish ([#239](https://github.com/snapotter-hq/snapotter/issues/239)) ([f622a4f](https://github.com/snapotter-hq/snapotter/commit/f622a4f691dce066adcc31bd8838b1f4014b92e0)) * **landing:** generate 301 redirects for old tool URLs; fix robots sitemap reference ([0051655](https://github.com/snapotter-hq/snapotter/commit/0051655bbf0201642f97436adf5c3130af8131c0)) * **landing:** migrate from Next.js to Astro 5 ([8403222](https://github.com/snapotter-hq/snapotter/commit/8403222d08034362382a902feec509665cb32bcb)) * **landing:** one-command Docker quickstart + live-demo CTA in hero ([#455](https://github.com/snapotter-hq/snapotter/issues/455)) ([aaf39a1](https://github.com/snapotter-hq/snapotter/commit/aaf39a1b7221e6581b681e776513063aed39eed3)) * **landing:** refocus hero on privacy-sensitive teams ([#431](https://github.com/snapotter-hq/snapotter/issues/431)) ([8451f9b](https://github.com/snapotter-hq/snapotter/commit/8451f9be0883dc58ac4413bc00c6e6edd082a896)) * **landing:** section-nested tool routes, section index pages, and section-prefixed links ([f158be6](https://github.com/snapotter-hq/snapotter/commit/f158be6aaa1e4ce907e0abe93a20f6791168b310)) * **landing:** swap Try Demo for Get Started Free CTA in top nav ([#418](https://github.com/snapotter-hq/snapotter/issues/418)) ([ea004a3](https://github.com/snapotter-hq/snapotter/commit/ea004a3308de489efa45fa77585ec4da9da82180)) * **landing:** warm up the contact CTAs ([#412](https://github.com/snapotter-hq/snapotter/issues/412)) ([3d4a84d](https://github.com/snapotter-hq/snapotter/commit/3d4a84d06865f0d790d39fee50809633cc6892c8)) * make password policy configurable via admin settings ([8b349b0](https://github.com/snapotter-hq/snapotter/commit/8b349b0341b8cde518558c8ef83523263a95abae)) * merge PostHog customer feedback ([1d99acf](https://github.com/snapotter-hq/snapotter/commit/1d99acf9ee30e0fe9528b02761a3eed5e808f0b8)) * mobile layout for tool-first flow ([896acda](https://github.com/snapotter-hq/snapotter/commit/896acda7ed033a13817d3556c50cea35ec884c3c)) * modality-aware file preview in Files library ([a70b13a](https://github.com/snapotter-hq/snapotter/commit/a70b13ad3207617c794fd90bf5c5dcd85c4a90ec)) * modality-based URLs (/image/resize, /video/compress-video) ([ea83e1c](https://github.com/snapotter-hq/snapotter/commit/ea83e1c8b4af7e613b4a5184b7b3e816ba1f1376)) * **modality:** rename "file" modality label "Data" -> "Files" ([71fefc0](https://github.com/snapotter-hq/snapotter/commit/71fefc05b08bdfc344de6beb16963b7cc632fac2)) * move theme toggle and language selector to top nav bar ([aff9159](https://github.com/snapotter-hq/snapotter/commit/aff9159ae0ef251a5be46bbae5a8a20ede2c419a)) * on-demand preview generation with progress messages for non-native formats ([d3cd4e4](https://github.com/snapotter-hq/snapotter/commit/d3cd4e41b5c8fab1732c16243c0a6c5c46b0b63e)) * pin frequently-used tools to the top of the dashboard ([#440](https://github.com/snapotter-hq/snapotter/issues/440)) ([3aaaacc](https://github.com/snapotter-hq/snapotter/commit/3aaaacc7a1830d748a3f6602cc6a81efbc9a9f32)) * pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization ([63a03d2](https://github.com/snapotter-hq/snapotter/commit/63a03d26f2f627578420dc4b7011e1078635651a)), closes [#355](https://github.com/snapotter-hq/snapotter/issues/355) [#354](https://github.com/snapotter-hq/snapotter/issues/354) [#356](https://github.com/snapotter-hq/snapotter/issues/356) [#353](https://github.com/snapotter-hq/snapotter/issues/353) [#351](https://github.com/snapotter-hq/snapotter/issues/351) * polish home page UI -- card borders, colored icons, 3-col grid, Cmd+K hint ([ade79c5](https://github.com/snapotter-hq/snapotter/commit/ade79c53a59cd3a991224f5e82b9a6e3861457bf)) * redesign review panel action hierarchy ([ed458d4](https://github.com/snapotter-hq/snapotter/commit/ed458d4bbdfaeb7054fa15c1fbaf2616ed19f45f)) * remove /fullscreen route, add dynamic page titles ([f9ebb30](https://github.com/snapotter-hq/snapotter/commit/f9ebb304db1b71ad0e6149d094dd7f6cac8777db)) * replace sidebar with top nav bar across all pages ([71fef43](https://github.com/snapotter-hq/snapotter/commit/71fef439a0d41bce34890d637c40a670fb2ce443)) * request a tool when home search finds nothing ([#385](https://github.com/snapotter-hq/snapotter/issues/385)) ([c68297d](https://github.com/snapotter-hq/snapotter/commit/c68297d5a49e659645b510da245241aa26a40cb6)) * rewrite home page as tool-first browser with search and modality tabs ([0d751b7](https://github.com/snapotter-hq/snapotter/commit/0d751b7d143a9102b3fe24e94c4e49ce616ee310)) * rewrite install_feature.py for pre-built tar bundles ([a4fa3ce](https://github.com/snapotter-hq/snapotter/commit/a4fa3ce2a71930a8b57fd3f17181c51f703a2081)) * **scripts:** add segment-anchored tool-path rewrite transform ([c17a4a4](https://github.com/snapotter-hq/snapotter/commit/c17a4a422582594c6e2127429a7373c2e0ade11c)) * **scripts:** add tool-path codemod CLI ([0691457](https://github.com/snapotter-hq/snapotter/commit/0691457f94dd63a53285107ab56d9ba73c1b3b47)) * server-side preview generation for non-native video/audio formats ([412a21e](https://github.com/snapotter-hq/snapotter/commit/412a21ee4d9a68baadef817509a5cc1a675a5143)) * **shared:** add apiToolPath() and section-prefixed routes; drop MODALITY_URL_SLUG ([9ca901f](https://github.com/snapotter-hq/snapotter/commit/9ca901f8d5b23b0a03060b3384af58c60cfbbaa0)) * **shared:** add Section concept and toolSection() partition ([7907471](https://github.com/snapotter-hq/snapotter/commit/790747188afe4fa0347579d6ce2db80d68bcfd2b)) * tiered processing feedback and upload progress indicator ([433d59c](https://github.com/snapotter-hq/snapotter/commit/433d59c726d196c7b51ea2cc29b0e2d44fa11feb)) * tool-first workflow polish -- fix tests, lint cleanup ([f387e98](https://github.com/snapotter-hq/snapotter/commit/f387e98fff6049a4869cebd4e4d7a717e7c1f28e)) * **tools:** 2.0 phase 5 wave 2 - pdf depth (21 tools) ([#220](https://github.com/snapotter-hq/snapotter/issues/220)) ([2f39e38](https://github.com/snapotter-hq/snapotter/commit/2f39e3816209fe81fac4620dd1233921e5de90d4)) * **tools:** 2.0 phase 5 wave 3a - video depth (22 tools) ([#221](https://github.com/snapotter-hq/snapotter/issues/221)) ([5f98b48](https://github.com/snapotter-hq/snapotter/commit/5f98b485935f07e40c0a6e57548892b2e17fc03b)) * **tools:** 2.0 phase 5 wave 3b - audio depth (14 tools) ([#222](https://github.com/snapotter-hq/snapotter/issues/222)) ([638288e](https://github.com/snapotter-hq/snapotter/commit/638288e196f05d889b5d818c0c8a11b0697ec49c)) * **tools:** 2.0 phase 5 wave 4 - office, ebooks, data, archives (14 tools) ([#224](https://github.com/snapotter-hq/snapotter/issues/224)) ([fc7c1f8](https://github.com/snapotter-hq/snapotter/commit/fc7c1f850e36fd01db9f08caf574f6f48d606b93)) * **tools:** 2.0 phase 5 wave 5a - image gap-fill (11 tools) ([#225](https://github.com/snapotter-hq/snapotter/issues/225)) ([6e1b986](https://github.com/snapotter-hq/snapotter/commit/6e1b9865f10c50badddb693a09ec20557379fe63)) * **tools:** 2.0 phase 5 wave 5b - ai pool: ocr-pdf, transcription, background composites (5 tools) ([#226](https://github.com/snapotter-hq/snapotter/issues/226)) ([51666cd](https://github.com/snapotter-hq/snapotter/commit/51666cdd5fd207ceee4da38b63d998af9a044809)) * **web:** add data retention settings to admin UI ([3016571](https://github.com/snapotter-hq/snapotter/commit/3016571c2b2925e8fc7677d9d2daae2bd8191db1)) * **web:** add MFA login prompt and security settings UI ([d397f57](https://github.com/snapotter-hq/snapotter/commit/d397f576676d127ee23c49a2948b041a6a6a777e)) * **web:** add storage dashboard and team retention settings ([c7e9b1d](https://github.com/snapotter-hq/snapotter/commit/c7e9b1ddc6189f847633399a982ce88cb6ae4a85)) * **web:** apply Otter Orange design system and UI improvements ([bcd59c2](https://github.com/snapotter-hq/snapotter/commit/bcd59c20c7da6208e937cac0a9b9f02ecf73b4f1)), closes [#E07832](https://github.com/snapotter-hq/snapotter/issues/E07832) [#2563eb](https://github.com/snapotter-hq/snapotter/issues/2563eb) * **web:** complete audit log viewer with IP column and all event types ([c6f9a29](https://github.com/snapotter-hq/snapotter/commit/c6f9a29687562c929d708a110eb0b7145c4dab11)) * **web:** fuzzy search with fuse.js for typo-tolerant tool discovery ([22cccd4](https://github.com/snapotter-hq/snapotter/commit/22cccd46c44c386aed5303efbd608105ddc1b30f)) * **web:** group home grid, tabs, and breadcrumb by section ([8301676](https://github.com/snapotter-hq/snapotter/commit/8301676e139fa0ed1d2423e133b11e0214bfe4cd)) * **web:** icon-only modality tabs, merge documents and files ([cc06c80](https://github.com/snapotter-hq/snapotter/commit/cc06c802c13b4d229fa2a97c3493aef4a555b1e6)) * **web:** in-canvas zoom & pan for the object eraser and split tools ([#320](https://github.com/snapotter-hq/snapotter/issues/320)) ([95d100c](https://github.com/snapotter-hq/snapotter/commit/95d100c20bd9b41cca3190a7791807516d2a17e4)) * **web:** modality filter tabs in sidebar tool panel ([8adceaf](https://github.com/snapotter-hq/snapotter/commit/8adceaf92d3effd8b4a2f15d6f8ecfc0f6c1ab8d)) * **web:** modality tabs on fullscreen grid page ([82fb798](https://github.com/snapotter-hq/snapotter/commit/82fb798142663b22d23bda69bf66d0d8cb56def9)) * **web:** section-prefix all tool API calls ([22b4b5c](https://github.com/snapotter-hq/snapotter/commit/22b4b5c3c17ea28712e2e9bf06ca35b6c5a23bd3)) * **web:** show icon + text labels on modality filter tabs ([888d243](https://github.com/snapotter-hq/snapotter/commit/888d243a653b7ecfab20830be2ea8baa961f8e71)) * **web:** stronger modality section visual hierarchy in tool catalog ([3db1b3b](https://github.com/snapotter-hq/snapotter/commit/3db1b3bafd9bfcde86c9d74037a30114437e4f71)) * wire AI bundle build into release pipeline ([d0732d4](https://github.com/snapotter-hq/snapotter/commit/d0732d4a586be25231be93e51e94db7ae05ae8ca)) ### Reverts * **deps:** keep rembg at 2.0.69 (2.0.75 conflicts with pinned numpy==1.26.4) ([4fdd10f](https://github.com/snapotter-hq/snapotter/commit/4fdd10f488642eabe671aa111796d343d0e2d358)) ### 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
Note
SnapOtter 2.0 is here. 200+ tools across five modalities (image, video, audio, PDF, and files), durable background jobs, on-demand local AI, and a one-command
docker run. See the release notes and the 1.x upgrade guide.
Important
Coming from 1.x? Many of you have trusted SnapOtter since day one, and your feedback and suggestions shaped everything that followed. 2.0 is a big step, and we worked to make sure it doesn't break what you already depend on. Your accounts, saved files, settings, API keys, and pipelines carry over automatically on first boot, and your old database is never modified. We wrote a full migration guide so the move is safe and boring. Thank you for being here.
Self-hosted file toolkit. 200+ tools across image, video, audio, PDF, and files.
The open-source alternative to Smallpdf, iLovePDF, TinyPNG, TinyWow, and CloudConvert, in one stack you host yourself.
Stirling-PDF stops at PDFs. ConvertX stops at conversions. SnapOtter runs all five, and your files never leave your server. Edit images, convert video, transcribe audio, repair PDFs, batch your files: one Docker stack, on hardware you own.
Quick Start
One command, no setup. An embedded Postgres 17 + Redis 8 boot inside the container, so there's nothing else to wire up:
docker run -d --name SnapOtter -p 1349:1349 -v SnapOtter-data:/data snapotter/snapotter:latest
Open http://localhost:1349 and log in with admin / admin. That's the whole install.
For the production Compose stack, NVIDIA GPU acceleration, and configuration, see Deployment below.
Key Features
- 200+ tools across 5 modalities:
- Image (105): resize, crop, compress, convert, watermark, color adjust, beautify screenshots, generate memes, vectorize, GIF tools, find duplicates, passport photos, plus dedicated format converters (JPG to PNG, HEIC to JPG, WebP to PNG, image to PDF, and more). Supports 55+ input formats (including 23 camera RAW formats) and 14 output formats
- Video (57): convert, compress, trim, resize, crop, merge, video-to-GIF, extract audio, stabilize, change FPS, burn/extract subtitles, plus dedicated converters (MOV to MP4, MKV to MP4, MP4 to MP3, and more)
- Audio (27): convert, trim, normalize, volume, fade, pitch shift, silence removal, noise reduction, merge/split, waveform, plus dedicated converters (M4A to MP3, AAC to MP3, OGG to WAV, and more)
- PDF (29): merge, split, compress, convert, protect/unlock, redact, sign, watermark, page numbers, OCR, plus PDF to JPG/PNG/TIFF
- Files (23): CSV/JSON/XML/YAML conversion, CSV merge/split, Excel to CSV, chart maker, ZIP create/extract
- Image editor: Layer-based editor with brushes, shapes, adjustments, filters, curves, and keyboard shortcuts. Runs in your browser, processes on your hardware
- Local AI: Remove backgrounds, upscale images, restore and colorize old photos, erase objects, blur faces, enhance faces, extract text (OCR from images and PDFs), transcribe audio, auto-generate video subtitles, expand canvas, and fix transparency. All on your hardware, no internet required
- OIDC / SSO: Login with Google, GitHub, Okta, or any OpenID Connect provider
- 21 languages: English, Arabic, Chinese (Simplified & Traditional), Dutch, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Swedish, Thai, Turkish, Ukrainian, Vietnamese. RTL support for Arabic
- Pipelines: Chain tools into reusable workflows with 20 steps by default. Import/export as JSON. Batch process up to 100 files by default
- REST API: Every tool available via API with API key auth. Interactive docs at
/api/docs - Self-hosted: one
docker runfor a single-container quick start (embedded Postgres 17 + Redis 8), or the same Postgres 17 + Redis 8 as a Compose stack for production. No external SaaS dependencies - Multi-arch: Runs on AMD64 and ARM64 (Intel, Apple Silicon, Raspberry Pi)
- Privacy first: Your files never leave your network. Basic analytics help us catch bugs and improve tools -- disable at build time with
SNAPOTTER_ANALYTICS=offor at runtime with the in-app admin opt-out (Here's how to do it)
Deployment
The Quick Start one-liner above is all most people need. For production, run the 3-container Compose stack (app + Postgres 17 + Redis 8). Save this as compose.yaml:
services:
snapotter:
image: snapotter/snapotter:latest
ports: ["1349:1349"]
environment:
DATABASE_URL: postgres://snapotter:snapotter@postgres:5432/snapotter
REDIS_URL: redis://redis:6379
volumes:
- SnapOtter-data:/data
depends_on: [postgres, redis]
restart: unless-stopped
postgres:
image: postgres:17-alpine
environment:
POSTGRES_USER: snapotter
POSTGRES_PASSWORD: snapotter
POSTGRES_DB: snapotter
volumes: ["SnapOtter-pgdata:/var/lib/postgresql/data"]
restart: unless-stopped
redis:
image: redis:8-alpine
volumes: ["SnapOtter-redisdata:/data"]
restart: unless-stopped
volumes:
SnapOtter-data:
SnapOtter-pgdata:
SnapOtter-redisdata:
Then start the stack:
docker compose up -d
Have an NVIDIA GPU? Click here for CUDA acceleration.
Use the GPU Compose file for NVIDIA CUDA-accelerated background removal, upscaling, transcription, and OCR. Intel/AMD iGPU acceleration through VA-API, Quick Sync, or OpenCL is not supported for AI inference today; those systems run AI tools on CPU. See Docker Tags for the GPU Compose example and benchmarks.
Default credentials:
| Field | Value |
|---|---|
| Username | admin |
| Password | admin |
You will be asked to change your password on first login.
For Docker Compose, persistent storage, and other setup options, see the Getting Started Guide. For NVIDIA CUDA acceleration and tag details, see Docker Tags.
Documentation
- Getting Started
- Upgrading from 1.x to 2.0
- Configuration
- OIDC / SSO
- Deployment
- Supported Formats
- Docker Tags
- REST API
- AI Engine
- Image Engine
- Architecture
- Database
- Developer Guide
- Contributing
- Translation Guide
Contributing
We welcome bug reports, feature ideas, and pull requests. See CONTRIBUTING.md for the full guide, or jump in:
- Open an issue
- Submit a PR
- Join Discord for help and discussion
- Sponsor the project to keep SnapOtter free for everyone
Support SnapOtter
SnapOtter is built and maintained independently with no venture capital or corporate backing. Sponsorships fund infrastructure, keep releases flowing, and ensure the project stays free and open for everyone.
If SnapOtter has replaced a paid subscription or two in your workflow, a small sponsorship helps keep it that way:
License
This project is dual-licensed under the AGPLv3 and a commercial license.
- AGPLv3 (free): You may use, modify, and distribute this software under the AGPLv3. If you run a modified version as a network service, you must make your source code available under the AGPLv3.
- Commercial license (paid): For use in proprietary software or SaaS products where AGPLv3 source-disclosure is not suitable, a commercial license is available. Contact us for pricing and terms.
See LICENSING.md for full details on the open-core boundary between AGPLv3 and commercial code.

