From aa675253ac5319b4302636fcd2a32415364923f2 Mon Sep 17 00:00:00 2001 From: ogt Date: Thu, 2 Jul 2026 01:03:47 +0800 Subject: [PATCH] fix(runner): align controlled cd lane drain guardrails --- docs/LOGBOOK.md | 18 ++++++++++ ops/runner/awoooi-cd-lane-drain.service | 20 +++++++---- .../test_cd_controlled_runtime_profile.py | 35 +++++++++++++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 2c21772b..c7b6a029 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -52071,6 +52071,24 @@ production browser smoke: - 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth;沒有使用 GitHub / gh / GitHub API / GitHub Actions。 - 沒有重啟主機,沒有 Docker / Nginx / K3s / DB / firewall 操作,沒有 workflow_dispatch,沒有 force push。 +## 2026-07-02 — P0 controlled CD lane drain service source guardrail 對齊 + +**完成內容**: +- Production 已讀回 deployed `8cc96973f7`,舊 `remote_ssh_publickey_offer_timeout` 不再是 active control-path blocker;目前 active AI loop item 改為 `controlled_cd_lane_guardrails_blocked`。 +- 110 read-only verifier 完整讀回:legacy fail-closed、root restore-source、host pressure 均 OK;blocker 為 controlled lane config missing、binary 非 ELF、registration missing、service masked/inactive 且 unit guardrails 不符合。 +- 修正 source-of-truth `ops/runner/awoooi-cd-lane-drain.service`:對齊 startup/verifier 要求的 `.runner` condition、data working dir、controlled env、host pressure env、CPU / memory / tasks / IO accounting、`NoNewPrivileges=true` 與 bounded limits。 +- 新增測試防止 service source 回退到缺 guardrails 或泛用重型 label。 + +**本地驗證結果**: +- `python3.11 -m pytest ops/runner/test_cd_controlled_runtime_profile.py ops/runner/test_check_awoooi_110_controlled_cd_lane_readiness.py -q`:`48 passed`。 +- `python3.11 -m py_compile ops/runner/test_cd_controlled_runtime_profile.py`:通過。 +- `git diff --check`:通過。 + +**仍維持**: +- 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth;沒有讀 `.runner` 內容;沒有使用 GitHub / gh / GitHub API。 +- 沒有重啟主機,沒有 Docker / Nginx / K3s / DB / firewall 操作,沒有 workflow_dispatch,沒有 force push。 +- 仍未代輸 runner registration token;registration missing 需要由不暴露 token 的受控流程補齊後才能讓 verifier 全綠。 + ## 2026-07-01 — 23:28 P0 110 sustained CPU pressure alert / controlled quota / alert-chain readback **完成內容**: diff --git a/ops/runner/awoooi-cd-lane-drain.service b/ops/runner/awoooi-cd-lane-drain.service index 9b2ce163..4f39583d 100644 --- a/ops/runner/awoooi-cd-lane-drain.service +++ b/ops/runner/awoooi-cd-lane-drain.service @@ -8,18 +8,26 @@ ConditionPathExists=/home/wooo/awoooi-cd-lane-drain/data/.runner [Service] Type=simple User=wooo -WorkingDirectory=/home/wooo/awoooi-cd-lane-drain +WorkingDirectory=/home/wooo/awoooi-cd-lane-drain/data Environment=HOME=/home/wooo -Environment=AWOOOI_CD_LANE_CONTROLLED=1 +Environment=AWOOOI_CONTROLLED_RUNNER_OPEN=1 +Environment=HOST_WEB_BUILD_PRESSURE_ATTEMPTS=1 +Environment=HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=1 ExecStart=/home/wooo/awoooi-cd-lane-drain/awoooi_cd_lane_controlled daemon --config /home/wooo/awoooi-cd-lane-drain/config.yaml Restart=always -RestartSec=15 +RestartSec=10 KillSignal=SIGINT TimeoutStopSec=3700 -CPUQuota=300% +SuccessExitStatus=0 130 143 +CPUAccounting=true +CPUQuota=250% +MemoryAccounting=true MemoryHigh=8G -MemoryMax=10G -TasksMax=1024 +MemoryMax=12G +TasksAccounting=true +TasksMax=512 +IOAccounting=true +IOWeight=100 NoNewPrivileges=true [Install] diff --git a/ops/runner/test_cd_controlled_runtime_profile.py b/ops/runner/test_cd_controlled_runtime_profile.py index b2439f27..5c67c320 100644 --- a/ops/runner/test_cd_controlled_runtime_profile.py +++ b/ops/runner/test_cd_controlled_runtime_profile.py @@ -16,12 +16,47 @@ PROD_WORKER_DEPLOYMENT = ROOT / "k8s" / "awoooi-prod" / "08-deployment-worker.ya PROD_CANARY_DEPLOYMENT = ( ROOT / "k8s" / "awoooi-prod" / "10-deployment-auto-repair-canary.yaml" ) +CD_LANE_DRAIN_SERVICE = ROOT / "ops" / "runner" / "awoooi-cd-lane-drain.service" def _workflow_text() -> str: return CD_WORKFLOW.read_text(encoding="utf-8") +def test_cd_lane_drain_service_source_keeps_controlled_guardrails() -> None: + text = CD_LANE_DRAIN_SERVICE.read_text(encoding="utf-8") + expected = [ + "ConditionPathExists=/home/wooo/awoooi-cd-lane-drain/data/.runner", + "WorkingDirectory=/home/wooo/awoooi-cd-lane-drain/data", + "Environment=AWOOOI_CONTROLLED_RUNNER_OPEN=1", + "Environment=HOST_WEB_BUILD_PRESSURE_ATTEMPTS=1", + "Environment=HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=1", + "ExecStart=/home/wooo/awoooi-cd-lane-drain/awoooi_cd_lane_controlled daemon --config /home/wooo/awoooi-cd-lane-drain/config.yaml", + "SuccessExitStatus=0 130 143", + "CPUAccounting=true", + "CPUQuota=250%", + "MemoryAccounting=true", + "MemoryHigh=8G", + "MemoryMax=12G", + "TasksAccounting=true", + "TasksMax=512", + "IOAccounting=true", + "IOWeight=100", + "NoNewPrivileges=true", + ] + for line in expected: + assert line in text + forbidden = [ + "ubuntu-latest", + "self-hosted", + "stockplatform", + "headless", + "playwright", + ] + for label in forbidden: + assert label not in text + + def test_web_changes_stay_on_controlled_runtime_profile() -> None: text = _workflow_text() assert "apps/web/*)" in text