fix: release QA hardening across processing, media, security, and CI gates (#649)

A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
This commit is contained in:
SnapOtter
2026-07-27 15:37:30 +08:00
committed by GitHub
parent bc32f86a07
commit d10d0f544f
855 changed files with 54564 additions and 13092 deletions
+19 -7
View File
@@ -1,8 +1,9 @@
---
description: "SnapOtter의 로컬 개발 환경 설정, 명령어, 코드 규칙, 새 도구를 추가하는 방법."
i18n_source_hash: cb03724d2829
i18n_provenance: human
i18n_output_hash: aa17bf7b9d5d
i18n_source_hash: 56acc1bf9a9b
i18n_provenance: machine
i18n_output_hash: 6df1aea31133
i18n_hash_version: 2
---
# 개발자 가이드 {#developer-guide}
@@ -11,12 +12,12 @@ i18n_output_hash: aa17bf7b9d5d
## 사전 요구사항 {#prerequisites}
- [Node.js](https://nodejs.org/) 22+
- [Node.js](https://nodejs.org/) 22.22+
- [pnpm](https://pnpm.io/) 9+ (`corepack enable && corepack prepare pnpm@latest --activate`)
- [Docker](https://www.docker.com/) (로컬 Postgres + Redis, 컨테이너 빌드, AI 기능에 필요)
- Git
Python 3.10+는 AI/ML 사이드카(배경 제거, 업스케일링, OCR)를 작업하는 경우에만 필요합니다.
Python 3.11+는 AI/ML 사이드카(배경 제거, 업스케일링, OCR)를 작업하는 경우에만 필요합니다.
## 설정 {#setup}
@@ -32,10 +33,10 @@ pnpm dev
| 서비스 | URL | 비고 |
|----------|--------------------------|------------------------------------|
| 프론트엔드 | http://localhost:1349 | Vite 개발 서버, /api 프록시 |
| 프론트엔드 | http://localhost:1351 | Vite 개발 서버, /api 프록시 |
| 백엔드 | http://localhost:13490 | Fastify API (프록시를 통해 접근) |
브라우저에서 http://localhost:1349를 여세요. `admin` / `admin`으로 로그인하세요. 첫 로그인 시 비밀번호를 변경하라는 안내가 표시됩니다.
브라우저에서 http://localhost:1351를 여세요. `admin` / `admin`으로 로그인하세요. 첫 로그인 시 비밀번호를 변경하라는 안내가 표시됩니다.
## 프로젝트 구조 {#project-structure}
@@ -220,6 +221,17 @@ docker build -f docker/Dockerfile -t snapotter:latest .
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile -t snapotter:latest .
```
## 릴리스 버전 도메인 {#release-version-domains}
SnapOtter에는 의도적으로 세 가지 버전 도메인이 있습니다. 릴리스 중에는 한 도메인을 다른 도메인으로 복사하지 마십시오.
- 애플리케이션 릴리스 버전에는 루트 매니페스트, 모든 개인 작업 공간 패키지 및 `APP_VERSION`가 포함됩니다. Semantic-release는 이 값을 제공하고 `pnpm version:sync <version>`는 애플리케이션 릴리스 전에 모든 작업 공간을 업데이트합니다.
- OpenAPI `info.version`는 안정적인 공개 API 주요 계약입니다. 모든 현지화된 사양은 호환되는 애플리케이션 릴리스를 위해 `<major>.0.0`에 유지되며 API 계약이 새로운 주요 버전으로 이동하는 경우에만 변경됩니다.
- `docker/feature-manifest.json``imageVersion: 2.0.0`를 불변의 레거시 기능 번들 스토리지 시대로 유지합니다. 해당 v2 아카이브 경로는 애플리케이션 패키지 버전이 아닙니다. Accurate OCR은 런타임 형식 v3을 사용하고 애플리케이션 릴리스 출처를 별도로 기록합니다.
`tests/unit/infra/release-version-policy.test.ts`는 이러한 경계를 적용합니다. 새 버전 도메인 또는 마이그레이션은 해당 계약과 관련 아티팩트 마이그레이션 설계를 함께 업데이트해야 합니다.
독립적인 API 및 레거시 번들 값은 `config/release-version-policy.json`에 있습니다. 애플리케이션 버전 동기화는 해당 정책 파일을 암시적으로 다시 작성해서는 안 됩니다.
## 환경 변수 {#environment-variables}
전체 목록은 [구성 가이드](/ko/guide/configuration)를 참고하세요. 개발에 중요한 것들: