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:
1 parent
b4c9b1ead2
commit
40dd0e69e4
29 files changed
+1661
-73
No files matched your search
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 真机核验用的 mock NexusPHP 站(testkit mock-nexusphp,观众风格),在 compose 网络里以 mocknexus:8080 提供给 camofox。
|
||||
* testkit 的 mock 只监听 127.0.0.1 随机端口,这里在 0.0.0.0:8080 做一层 TCP 转发。
|
||||
* 控制端点(只供核验脚本):POST /__mock/login?v=0|1 切换登录态;GET /__mock/infohash?id= 取种子 infohash;
|
||||
* GET /__mock/stats 取 takelogin 次数。
|
||||
*/
|
||||
import { createServer } from "node:http";
|
||||
import { connect, createServer as createTcp } from "node:net";
|
||||
import { createMockNexusPhpSite } from "../../packages/testkit/src/sites/mock-nexusphp.ts";
|
||||
|
||||
const site = await createMockNexusPhpSite({ siteName: "观众(mock)", loginMode: "redirect" });
|
||||
const upstream = new URL(site.baseUrl);
|
||||
|
||||
const control = createServer((req, res) => {
|
||||
const u = new URL(req.url ?? "/", "http://x");
|
||||
res.setHeader("content-type", "application/json");
|
||||
if (u.pathname === "/__mock/login") {
|
||||
site.setLoggedIn(u.searchParams.get("v") !== "0");
|
||||
return res.end(JSON.stringify({ ok: true }));
|
||||
}
|
||||
if (u.pathname === "/__mock/infohash")
|
||||
return res.end(JSON.stringify({ infohash: site.infoHashOf(u.searchParams.get("id") ?? "") }));
|
||||
if (u.pathname === "/__mock/stats")
|
||||
return res.end(JSON.stringify({ loginAttempts: site.loginAttempts, releases: site.releases.length }));
|
||||
res.statusCode = 404;
|
||||
res.end("{}");
|
||||
});
|
||||
control.listen(8081, "0.0.0.0");
|
||||
|
||||
createTcp((client) => {
|
||||
const up = connect(Number(upstream.port), upstream.hostname);
|
||||
client.pipe(up).pipe(client);
|
||||
client.on("error", () => up.destroy());
|
||||
up.on("error", () => client.destroy());
|
||||
}).listen(8080, "0.0.0.0", () => console.log(`mock nexus ${site.baseUrl} → 0.0.0.0:8080(控制 8081)`));
|
||||
Reference in new issue
Block a user