From 0bef9002713f6f0e3f7c4fcbebfeb22551185f63 Mon Sep 17 00:00:00 2001 From: agent-exec-transport Date: Fri, 23 Oct 2026 08:04:28 +0000 Subject: [PATCH] agent-exec transport 7fcb6fe7bcd8c87d45817a4df898a522/a352823d21b0 --- modules/frontend | 2 +- scripts/e2e.sh | 55 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/modules/frontend b/modules/frontend index 279b2d02..807c6568 160000 --- a/modules/frontend +++ b/modules/frontend @@ -1 +1 @@ -Subproject commit 279b2d02a2724a6eeb4557af295b4c7346cb46d1 +Subproject commit 807c6568863ab31bcc60f6b3a0e8d46e5cc9d5a9 diff --git a/scripts/e2e.sh b/scripts/e2e.sh index b597d42d..fe373f1c 100644 --- a/scripts/e2e.sh +++ b/scripts/e2e.sh @@ -99,8 +99,17 @@ log "build base CLI (identity ensure + plain-base serve) from the same pinned ba (cd "$RDM_WT/pins/agent-system-backend" && go build -o "$OUT/agent-system" ./cmd/agent-system) \ || die "backend cli build failed" -log "build frontend dist (contracts + ui deps + bundle, via make frontend)" -make -C "$DEV_ROOT" frontend >/dev/null || die "frontend build failed" +# 直接构建 FE dist:不走 make frontend(其 contracts→test-worktree 要求全部 +# submodule 已物化;本脚本只需 FE+@ui 源码组合)。contracts.ts 以 FE pin 为准。 +log "build frontend dist (npm ci @ui + frontend, vite build)" +[ -f "$DEV_ROOT/modules/ui/package.json" ] \ + || die "modules/ui missing (need gitlink checkout for @ui alias)" +[ -f "$DEV_ROOT/modules/frontend/package.json" ] \ + || die "modules/frontend missing" +(cd "$DEV_ROOT/modules/ui" && npm ci --no-fund --no-audit) >/dev/null \ + || die "ui npm ci failed" +(cd "$DEV_ROOT/modules/frontend" && npm ci --no-fund --no-audit && npm run build) \ + || die "frontend build failed" # ── 2. 种子 ───────────────────────────────────────────── DATA="$OUT/data" @@ -153,16 +162,35 @@ cmd() { # cmd [extra-body-fields] → payload(失败即死 | python3 -c 'import json,sys; d=json.load(sys.stdin); r=(d or {}).get("receipt",{}); sys.exit(1) if r.get("state")=="rejected" else None; print(json.dumps(d.get("payload", d), ensure_ascii=False))' \ || die "command $id rejected" } -admin_create_user() { # admin_create_user [display-name] +admin_create_user() { # admin_create_user [display-name] [isAdmin] # 超管会话 POST /api/admin/users;200 且 mustChangePassword:true(Playwright 首登改密)。 - local owner=$1 password=$2 name=${3:-$1} body + # 第 4 参为 true 时任命基座管理员(admin-user-create 需「系统管理…」入口;仅超管可任命)。 + local owner=$1 password=$2 name=${3:-$1} is_admin=${4:-false} body body=$(curl -sf -b "$JAR" -X POST "$API_BASE/api/admin/users" \ -H 'Content-Type: application/json' \ - -d "{\"owner\":\"$owner\",\"password\":\"$password\",\"profile\":{\"name\":\"$name\"}}") \ + -d "{\"owner\":\"$owner\",\"password\":\"$password\",\"profile\":{\"name\":\"$name\"},\"isAdmin\":$is_admin}") \ || die "admin create user $owner failed" printf '%s' "$body" | python3 -c 'import json,sys; d=json.load(sys.stdin); sys.exit(0 if d.get("mustChangePassword") is True else 1)' \ || die "admin create user $owner: expected mustChangePassword:true" } +# 浏览器用例若不以改密门处理该账号(如 cockpit 的 e2e-reader),种子阶段代完 must-change。 +complete_must_change() { # complete_must_change + local owner=$1 initial=$2 final=$3 jar i + jar="$OUT/${owner}.changepw.jar" + for i in $(seq 1 20); do + if curl -sf -c "$jar" -X POST "$API_BASE/api/auth/login" \ + -H 'Content-Type: application/json' \ + -d "{\"owner\":\"$owner\",\"password\":\"$initial\"}" >/dev/null; then + break + fi + sleep 0.25 + [ "$i" = 20 ] && die "must-change login failed for $owner" + done + curl -sf -b "$jar" -c "$jar" -X POST "$API_BASE/api/auth/password" \ + -H 'Content-Type: application/json' \ + -d "{\"current\":\"$initial\",\"next\":\"$final\"}" >/dev/null \ + || die "must-change password failed for $owner" +} # 正式项目命令(rdm.reqs.*/rdm.review.*/rdm.draft.*/rdm.ingest 等,基座 # cmdbus.RequiresProjectWorkDecision)须带已认证会话来源:conversationId 绑定宿主项目, # anchorMessageId 为该会话中已提交、经 RDM 来源分析放行的用户消息;裸调用被预检拒绝。 @@ -195,9 +223,10 @@ done # Legacy bootstrap-admin is disabled; super admin is established at serve startup # from SUPER_ADMIN_OWNER/SUPER_ADMIN_PASSWORD. Login via the normal session endpoint. login -# Ordinary fixture owner (e2e-auditor):超管会话管理 API 建号;初始密码为 PASSWORD, -# mustChangePassword 由 Playwright 首登改密门处理为 PASSWORD2(不覆盖超管会话 jar)。 -admin_create_user "$OWNER" "$PASSWORD" "$OWNER" +# Fixture owner(默认 e2e-auditor):RDM -bootstrap-admin 已授域管理员;此处再建基座账号 +# 并任命 isAdmin(admin-user-create 需「系统管理…」)。初始密码=PASSWORD,mustChange +# 由 Playwright 首登改密门处理为 PASSWORD2(不覆盖超管会话 jar)。 +admin_create_user "$OWNER" "$PASSWORD" "$OWNER" true log "seed: create projects" read -r PID_MAIN HOST_MAIN < <(cmd rdm.project.create "{\"name\":\"$PROJ_MAIN\"}" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["projectId"], d["hostProjectId"])') [ -n "${HOST_MAIN:-}" ] || die "rdm.project.create: missing projectId/hostProjectId" @@ -288,7 +317,12 @@ cmd rdm.project.member.add "{\"projectId\":\"$PID_MAIN\",\"member\":\"e2e-rev\", cmd rdm.project.member.add "{\"projectId\":\"$PID_MAIN\",\"member\":\"e2e-app\",\"role\":\"member\"}" >/dev/null fcmd rdm.review.assign.doc "{\"projectId\":\"$PID_MAIN\",\"docId\":\"$DOC_MAIN\",\"author\":\"$OWNER\",\"reviewers\":[\"e2e-rev\"],\"approver\":\"e2e-app\"}" >/dev/null log "seed: second account (non-member negative case)" -admin_create_user e2e-reader 'E2eReader#2026' e2e-reader +# cockpit 场景 6 直接以 E2E_READER_PASSWORD 登录(无改密门);种子代完 must-change, +# 使最终密码与 Playwright 缺省 E2eReader#2026 一致。 +READER=${E2E_READER:-e2e-reader} +READER_PASSWORD=${E2E_READER_PASSWORD:-E2eReader#2026} +admin_create_user "$READER" "$READER_PASSWORD" "$READER" +complete_must_change "$READER" "$READER_PASSWORD" "$READER_PASSWORD" # ── 3. 验收 ───────────────────────────────────────────── if [ "$SEED_ONLY" = 1 ]; then @@ -318,7 +352,8 @@ log "playwright (install chromium if missing)" log "run specs" cd "$DEV_ROOT/modules/frontend" export PLAYWRIGHT_BASE_URL="http://127.0.0.1:$UI_PORT" E2E_OWNER="$OWNER" \ - E2E_PASSWORD="${E2E_PASSWORD:-E2eAudit#2026}" E2E_PASSWORD2="$PASSWORD2" \ + E2E_PASSWORD="$PASSWORD" E2E_PASSWORD2="$PASSWORD2" \ + E2E_READER="$READER" E2E_READER_PASSWORD="$READER_PASSWORD" \ E2E_PROJECT_MAIN="$PROJ_MAIN" E2E_PROJECT_ISOLATED="$PROJ_ISO" set +e # 本脚本的种子只覆盖审计工作区。u7 现场验收用例依赖另一套入口,不在这里跑。