openpencil/tools/check-web-server-headless.sh
Kayshen-X b7951fc598 ci(host): build web image from op-host-web-server + headless-boundary guard (Phase 6, Tasks 6.2-6.4)
Dockerfile.web-rust builds -p op-host-web-server (was op-host-desktop) and drops ALL GL/X11
build + runtime apt deps (libegl/libgles/libgbm/libxkbcommon/libwayland/libxcb) — the raster
server links none; only freetype/fontconfig + CJK fonts remain for skia text. COPY + CMD repointed
to /app/op-host-web-server. New tools/check-web-server-headless.sh fails CI if op-host-web-server's
isolated dep graph pulls winit/glutin/casement/muda/accesskit-adapters or skia-safe with gl (bare
accesskit core allowed per Codex Issue 1); wired into rust-check.yml + its paths filter. Stale
web_static.rs path comment fixed (op-host-desktop -> op-web-daemon). Desktop-app build job untouched.
2026-06-19 22:14:56 +08:00

44 lines
1.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# Headless-boundary guard for the web / MCP server binary.
#
# The whole point of `op-host-web-server` (Approach Y) is that it links the
# extracted `op-web-daemon` and NOTHING from the desktop GUI stack: no winit /
# glutin / casement (windowing), no muda (native menus), no accesskit platform
# ADAPTERS (a11y bridges), and skia-safe WITHOUT the `gl` feature (raster only).
# This guard fails the build if any of those leak into the isolated dep graph,
# so the web image stays GUI-free.
#
# Codex Issue 1: the bare `accesskit` CORE crate is allowed — `op-editor-ui`
# pulls it unconditionally for the platform-free `Node` / `TreeUpdate` types
# (no GUI runtime). We grep the platform ADAPTER crates only.
set -euo pipefail
cd "$(dirname "$0")/.."
fail=0
# 1. No windowing / menu / a11y-adapter crates in the feature-resolved tree.
gui=$(cargo tree -p op-host-web-server -e features 2>/dev/null \
| grep -E 'winit|glutin|casement|muda|accesskit_(macos|unix|windows|winit)' || true)
if [ -n "${gui}" ]; then
printf 'FAIL: op-host-web-server links a desktop GUI crate:\n%s\n\n' "${gui}" >&2
fail=1
fi
# 2. skia-safe must be raster — NO `gl` feature. Under Approach Y, gl arrives
# only via the desktop-only `gl-host` edge; its presence in this isolated
# graph means a consumer leaked gl-host into the headless server.
skia_feats=$(cargo tree -p op-host-web-server -f '{p} {f}' 2>/dev/null \
| grep 'skia-safe v' | sed 's/.*skia-safe v[^ ]*//' | head -1)
if printf '%s' "${skia_feats}" | grep -qE '(^| |,)gl(,| |$)'; then
printf 'FAIL: op-host-web-server skia-safe carries the `gl` feature (must be raster):\n features:%s\n\n' "${skia_feats}" >&2
fail=1
fi
if [ "${fail}" -ne 0 ]; then
printf 'FAIL: op-host-web-server headless boundary check\n' >&2
exit 1
fi
echo "PASS: op-host-web-server headless boundary check (no winit/glutin/casement/muda/accesskit-adapter; skia raster, no gl)"