host
|
5dc75128f8
|
fix(chv): 数据盘挂载升格为 oneshot 服务,浏览器启动时重解析 profile
|
2026-11-08 09:45:00 +00:00 |
|
host
|
0bfb00ab1b
|
fix(chv): 快照改走 page.aria_snapshot()
Playwright 1.64.1 已移除 page.accessibility,真实快照一路报
AttributeError(P2 假实现用的旧 API,单测一直没抓到;2026-11-08
构建 #8 驱动 live 抓到)。新版 aria_snapshot() 返回字符串,
超 64KB 截断;旧版 accessibility.snapshot()(dict)只作回落。
驱动的 a11y 断言接受 str 或 dict。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
1188e4b000
|
feat(chv): 阶段 3 浏览器服务化——持久 profile + CDP + 多会话 + JPEG 截图 + 双浏览器
- chv-browser:launch_persistent_context,profile 固定数据盘
/home/chv/workspace/.chv-browser-profile(未挂载回落本机盘并明说);
CDP --remote-debugging-port 9222(op cdp 返回 webSocketDebuggerUrl);
多会话每会话一页;截图 JPEG q70、viewport 宽封顶 1280、diff_only
整帧相同跳过;mount_full/unmount_full 切 full/shell 引擎,full
未装或起不来回落 shell 并明说。
- chv-data-mount:挂载后预建 profile 目录(chv-browser:chv-browser 0700)。
- build.sh:chv-browser 单元 Restart=always、After cloud-final.service。
- chv-execd:codex 环境白名单加 CHV_BROWSER_ 前缀。
- 测试:新增 test_chv_opt_stage3.py(20 项);P2 假实现改为持久
上下文 + JPEG;stage2 的 Restart=always 计数 3→4。
- 全量回归 2032 过 skipped=8。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
1cbaf7c1d5
|
chv-cell: networkd 不管 ve + 单元内 DNS 修复
- systemd-networkd(/usr/lib 80-container-ve.network,匹配 ve-*)
会在 veth 建好后几秒内刷掉静态 10.200.0.1、改 DHCP/链路本地,
致单元网关不可达、TCP/UDP 全灭(FORWARD/NAT 计数器恒 0;
早先一次 curl 403 是刷掉前的窗口期偶发)。修法:镜像内置
/etc/systemd/network/79-chv-cell.network(Unmanaged=yes),
须排在 80 之前(99 会被 80 抢走,已实测);build.sh copy-in
+ 校验、BASE_CONTENTS 与两处 DECLARED_SOURCES 登记。
- run_cell 配网后复核 ve 上确有 10.200.0.1(_iface_has_ip),
不见即大声失败、不跑无网单元(第二道防线)。
- 单元内 DNS:/etc/resolv.conf 是 127.0.0.53 stub,单元独立
netns 里自己的 lo 上没有 resolver;把上游
/run/systemd/resolve/resolv.conf 绑到 /etc/resolv.conf
(解析 symlink 后挂真实目标)。live 验证:DNS-UDP-OK、
getaddrinfo 解析成功、curl https://gitea.tose.top 200。
- 单测:CellResolvTest + _iface_has_ip 真实 lo 断言 + 规约
dns_resolv_conf 字段;P2 + 阶段 2 共 74 项全过。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
4b5f2f124f
|
chv-cell: ns 内 setuid 修复 + 单元内 DNS(上游 resolv.conf 绑定)
- 中间进程不再先 setuid(1000) 再 unshare:真机对照实测那样
后续 unshare(CLONE_NEWNS) 得 EPERM;改为保持 root 外层身份
unshare(creator caps 在),孙进程在 ns 内 setgid/setuid(0)
切到内 0(映射到外层 chv 1000)。
- 单元内 DNS:客机 /etc/resolv.conf 是 127.0.0.53 stub,单元
独立 netns 里自己的 lo 上没有 resolver;把上游
/run/systemd/resolve/resolv.conf 绑到 /etc/resolv.conf
(解析 symlink 后挂真实目标),只在单元私有 mount ns 里。
- 单测:CellResolvTest(bind 参数/symlink 解析/缺失回落)
+ 规约 dns_resolv_conf 字段;P2 + 阶段 2 共 73 项全过。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
afbb7772c5
|
fix(chv): cell 映射改由父进程写,中间进程先 setuid(1000)
两个真机教训(2026-11-07):
- 子进程自己写不进 uid_map:unshare 后 euid 变 overflow,
连 /proc/self/uid_map 的 open 都 EPERM——改由父进程
(仍在初始 ns 的 root)经 /proc/<pid>/uid_map 写。
- 映射按外层 uid 翻译:中间进程外层是 root(0) 时
“0 1000 1” 盖不住它、新 ns 里仍是 overflow——中间进程
须先 setgroups/setgid/setuid(1000) 再 unshare(实测
chv 身份 unshare 在客机上可行,AppArmor 不挡)。
另:中间进程异常加 traceback(调试用);userns 单测改测
父写映射真实路径(映射行按 split 比,内核会多空格对齐)。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
a2a5624736
|
fix(chv): cell 后端由 nspawn 改为纯 stdlib userns 启动器
nspawn --directory=/ 在 systemd 255.4 上走不通(2026-11-07 真机
实测,修一个冒一个):裸 --no-new-privileges 被当成要值吞掉
下一个参数;--directory=/ 被根目录检查挡住;--volatile=state
又要 /run/host/os-release 挂载点与空 /dev(--tmpfs=/dev 不
生效)。cell 从未 live 跑通过(阶段 1 只测参数表纯函数)。
bwrap 作 chv 被 AppArmor userns 门挡住,newuidmap 客机未装。
新后端(同文件、同 CLI、同调用方):root 起进程,中间进程
unshare 用户 ns 并自己写 uid_map/gid_map(内 0 → 外 chv
1000),再进 mount/pid/net ns、挂 fresh /proc、/tmp tmpfs、
遮蔽敏感路径(目录盖 tmpfs、文件绑 /dev/null)、设
no_new_privileges + seccomp(禁 io_uring 三件套)+ 丢
capability,最后 exec payload;父进程配 veth/NAT、等退出码、
清 NAT。veth/NAT/nsenter 流程与旧版一致,seccomp BPF 与
capability 语义与 P2 设计一致。无新依赖、无 sysctl 改动。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
9d77ae55a7
|
feat(chv): 阶段 2 客机运行时三分 daemon/execd/syncd + restore 留 seed.iso + tap 退避
- 客机三分(chv-guest/chv-daemon.py、chv-execd.py、chv-syncd.py,
仅标准库;systemd Restart=always;build.sh 拷入 + 单元 + enable;
buildinfo/check/generate lockfile 登记):
daemon=心跳/资源上报/快照配合(prepare-snapshot 问 execd,
有运行中任务或联系不上即拒绝);execd=shell/文件读写/codex
托管(chv-cell 起 host.py,setsid 脱离,任务登记落盘,
重启按 pid 认领;SO_PEERCRED 只认 uid 0/1000;codex env
白名单);syncd=常驻循环只调 chv-sync pull/push,规则一条
不改(先 pull --ff-only 再 push,分叉即停、不 --force、
不 rebase;仓不存在记 needs-boot 不擅自 clone)。
host.py 仍是唯一任务/codex 引擎,broker/browser/cell 分工
不变,不另起第二套 agent。
- 阶段 1 遗留修复:restore_vm 失败路径 stop_vm(keep_disk=True),
seed.iso 与任务盘都留,重试有输入;vm.boot/restore 的 tap
触点遇 Resource busy 等 tap 空闲后重试一次(_wait_tap_idle
看 ip link state,_ch_remote 报错带 stderr 尾巴以便识别);
诊断不用 pgrep -x(15 字符上限)。
- 单测 cloud/tests/test_chv_opt_stage2.py 25 项;P2 干跑夹具
与 enable 行断言随构建接线更新。
- 全量 cloud/tests 2001 全过(skipped=8)。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
a5f836e9fd
|
feat(chv-guest): 阶段 1 数据盘独立持久(客内挂载)
- 新增 chv-guest/chv-data-mount.sh:按 LABEL=CHVDATA 找盘
(不依赖 /dev/vd? 固定名;seed ISO 与根盘排除),无 fs
即 mkfs.ext4 -L CHVDATA,挂到 /home/chv/workspace,幂等;
无数据盘即静默退出 0(copy 模式旧 VM 不报错)。
- build.sh:缺脚本即失败(与 chv-sync.sh 同款门);拷入
镜像 /usr/local/bin/chv-data-mount;99-chv-sync.cfg
runcmd 在 chv-sync boot 之前调它(工作区先挂好再 clone)。
- buildinfo.py BASE_CONTENTS 与两 lockfile DECLARED_SOURCES
登记 chv-data-mount(repo_commit,随 P2 三脚本先例)。
- tests:test_chv_opt_stage1.DataMountScriptTest(脚本内容、
构建接线、lockfile 登记);P2 干跑夹具补新文件。
回归:discover test_chv_*.py 与 test_cloud_hypervisor.py 全过。
不推、不合、不部署;只本地分支。
|
2026-11-08 09:45:00 +00:00 |
|
host
|
ef206cf554
|
feat(chv-guest): 对齐 Muse P2——nspawn 单元 + broker + 浏览器子代理
- chv-cell:systemd-nspawn 单命令单元,--private-users=1000:65536
(单元 root → 客机 chv),丢 8 项能力(含 SYS_PTRACE/NET_ADMIN),
syscall 过滤扣 io_uring,遮蔽 /etc/chv 与 playwright,
--network-veth(10.200.0.0/24 + NAT),白名单环境透传
- chv-broker:Unix socket + SO_PEERCRED(uid 范围 + pid ns 对照),
白名单 ping/sync/browser;sync 只调 chv-sync(runuser -u chv)
- chv-browser:单元外独立进程,只暴露 open/snapshot/screenshot/
close/ping,返回无障碍树快照(截断);evaluate/content 拒绝
- build.sh:装 systemd-container/iproute2/iptables,拷入三脚本,
建 chv-browser 用户与两个 systemd 单元;vsock_notify 条件拷入
- buildinfo:内容项加 P2 四项,支持可选 extra_contents
- 测试:cloud/tests/test_chv_muse_p2.py 40 项全过;broker/browser
真实 socket 回路冒烟通过(root 连 broker 被拒)
- 差距表:docs/chv-muse-p2-gap.md;真机验证待测试机空闲(round 11)
本地做,不推、不合、不部署
|
2026-11-08 09:44:59 +00:00 |
|