feat(browser): ship camofox v1.17.0 in compose, verified on a real instance

- compose: camofox service on by default (internal only, volume umt-camofox,
  healthcheck, CAMOFOX_REPLICAS=0 to skip); app depends on it with
  service_started/required=false and auto-registers camofox-env from
  BROWSER_PROVIDER_URL / BROWSER_ACCESS_KEY / BROWSER_ENABLED
- docker/camofox/Dockerfile: builds upstream tag v1.17.0 (389c996); fixes the
  upstream Dockerfile (missing postinstall.js before npm ci, sh -c not
  forwarding SIGTERM so logins were never persisted on restart)
- adapter fixes from the real container: coordinate click via evaluate +
  selector, focus typing with mode=keyboard, password values redacted from
  ARIA snapshots/extract, downloads field names, 410 after browser restart
  treated as lost tab; navigate reopens a tab in the same session
- verified-capability table keyed by upstream version (1.17.0 all ten);
  other versions stay unverified; probe reports auth failures
- settings: browser providers block (create/edit/delete/probe, capability
  table); API POST/PATCH/DELETE /browser/providers, POST .../probe
- scripts/browser-verify: umtbr stack + mock NexusPHP run of REQ 4.7.4 items
- docs: runbook browser §1/§7 (real-instance record), deploy §2.1

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 00:05:21 +08:00
1 parent b4c9b1ead2
commit 40dd0e69e4
29 files changed
+1661 -73

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
#!/bin/sh
# camofox 真机核验:起临时栈 umtbr → 分阶段跑 verify.ts(阶段间重启 / 杀 camofox)→ 结果写 $OUT_DIR。
# 结束后 `docker compose -p umtbr down -v`(镜像保留)。需要本机已有 camofox-browser:1.17.0 镜像(见 docs/runbook/browser.md §1)。
set -eu
cd "$(dirname "$0")/../.."
export POSTGRES_PASSWORD=umtbr-verify SECRET_MASTER_KEY=umtbr-verify-master-key-0123456789
export CAMOFOX_ACCESS_KEY=${CAMOFOX_ACCESS_KEY:-umtbr-camofox-access-key}
# 空闲回收阶段用短超时
export CAMOFOX_SESSION_TIMEOUT_MS=${CAMOFOX_SESSION_TIMEOUT_MS:-60000}
export CAMOFOX_BROWSER_IDLE_TIMEOUT_MS=${CAMOFOX_BROWSER_IDLE_TIMEOUT_MS:-30000}
export VERIFY_PG=postgres://umt:[email protected]:55447/umt
export OUT_DIR=${OUT_DIR:-$(pwd)/.browser-verify-out}
C="docker compose -p umtbr -f docker-compose.yml -f scripts/browser-verify/compose.yml"
V="deno run -A scripts/browser-verify/verify.ts"
wait_healthy() {
for _ in $(seq 1 60); do
[ "$(docker inspect -f '{{.State.Health.Status}}' umtbr-camofox-1 2>/dev/null)" = healthy ] && return 0
sleep 2
done
echo "camofox 未就绪" >&2; return 1
}
$C up -d --no-build postgres camofox mocknexus
wait_healthy
until docker exec umtbr-postgres-1 pg_isready -U umt -d umt >/dev/null 2>&1; do sleep 1; done
$V setup
$V a
$C restart camofox && wait_healthy
$V b
# 上游每 60 秒扫一次过期会话:超时 + 一个扫描周期 + 余量
echo "等待会话空闲回收(${CAMOFOX_SESSION_TIMEOUT_MS}ms + 60s 扫描周期)…"
sleep $(( CAMOFOX_SESSION_TIMEOUT_MS / 1000 + 75 ))
$V idle
$V c
docker kill -s KILL umtbr-camofox-1 && $C up -d --no-build camofox && wait_healthy
$V d
echo "结果:$OUT_DIR/results-*.json"