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
+12 -7
View File
@@ -1,8 +1,9 @@
---
description: "设置 SCIM 2.0 预配以将用户和组从你的身份提供商同步到 SnapOtter。涵盖 Okta、Azure AD / Entra ID 以及自定义集成。"
i18n_source_hash: bbd50119ec12
i18n_source_hash: 06ee702b386e
i18n_provenance: human
i18n_output_hash: 70121241a9af
i18n_output_hash: d318d3799726
i18n_hash_version: 2
---
# SCIM 预配 {#scim-provisioning}
@@ -17,7 +18,7 @@ SCIM 预配需要带有 `scim` 功能的 **enterprise** 许可证。它在 team
- 一个可通过公网 URL 访问的正在运行的 SnapOtter 实例
- 一个带有 `scim` 功能的 enterprise 许可证密钥
- SnapOtter 的管理员访问权限(生成或吊销 SCIM 令牌需要 `users:manage` 权限)
- 内置 SnapOtter `admin` 帐户及其完整的有效权限集。委托的自定义角色或缺少任何管理权限的管理 API 密钥无法生成或撤销全局 SCIM 令牌。
- 你的身份提供商的预配设置的管理员访问权限
## 快速开始 {#quick-start}
@@ -34,7 +35,7 @@ curl -X POST https://photos.example.com/api/v1/enterprise/scim/token \
```json
{
"token": "a1b2c3d4e5f6...",
"token": "so_scim_v2_a1b2c3d4e5f6...",
"message": "Save this token - it cannot be retrieved again"
}
```
@@ -49,15 +50,19 @@ SCIM 端点使用专用的 Bearer 令牌,与用户会话和 API 密钥分开
### 生成令牌 {#generating-a-token}
`POST /api/v1/enterprise/scim/token` 生成一个新的 SCIM 令牌。此端点需要一个具有 `users:manage` 权限的有效会话
`POST /api/v1/enterprise/scim/token` 生成新的 SCIM 代币。由于令牌可以跨实例配置和更改用户,因此此端点需要具有完整有效管理权限集的内置 `admin` 角色。将 `users:manage` 保留在自定义角色中是不够的
令牌以明文形式仅返回一次。SnapOtter 只存储 scrypt 哈希值。如果你丢失了令牌,请吊销它并生成一个新的。
同一时间只有一个 SCIM 令牌处于活动状态。生成新令牌会替换先前的令牌。
::: warning 升级后重新发行令牌
旧版未版本控制的 SCIM 令牌将被拒绝。升级到颁发 `so_scim_v2_...` 令牌的版本后,请生成新令牌并更新您的身份提供商,然后再恢复配置。
:::
### 吊销令牌 {#revoking-a-token}
`DELETE /api/v1/enterprise/scim/token` 会吊销当前的 SCIM 令牌。此端点同样需要 `users:manage`
`DELETE /api/v1/enterprise/scim/token` 销当前的 SCIM 令牌。它具有与令牌生成相同的完整内置管理要求
### 速率限制 {#rate-limiting}
@@ -279,7 +284,7 @@ SCIM 请求未包含 `Authorization: Bearer <token>` 标头。请检查你的 Id
### 401 "Invalid token" {#_401-invalid-token}
令牌与存储的哈希不匹配。如果令牌被吊销并重新生成,就会发生这种情况。请在你的 IdP 的配设置中更新令牌。
令牌格式错误、使用已停用的未版本化格式或与存储的哈希不匹配。生成当前的 `so_scim_v2_...` 令牌并在 IdP 的配设置中更新令牌。
### 401 "SCIM not configured" {#_401-scim-not-configured}