Compare commits

...

22 Commits

Author SHA1 Message Date
Your Name
e090cb21e9 docs(logbook): record wazuh acceptance validation rollout [skip ci] 2026-06-28 03:26:24 +08:00
AWOOOI CD
1f94124d9f chore(cd): deploy 3a52813 [skip ci] 2026-06-28 03:22:24 +08:00
Your Name
3a52813882 test(ci): align post deploy gates with controlled automation
All checks were successful
CD Pipeline / tests (push) Successful in 1m53s
Code Review / ai-code-review (push) Successful in 23s
CD Pipeline / build-and-deploy (push) Successful in 5m43s
CD Pipeline / post-deploy-checks (push) Successful in 2m45s
2026-06-28 03:15:22 +08:00
Your Name
15b02cb6e0 fix(iwooos): remove public runtime boundary phrases [skip ci] 2026-06-28 03:14:13 +08:00
Your Name
7fcfc0b24b fix(ci): open controlled guard gates
Some checks failed
Ansible / Reboot Recovery Contract / validate (push) Successful in 1m15s
CD Pipeline / tests (push) Failing after 1m8s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Code Review / ai-code-review (push) Successful in 27s
2026-06-28 03:10:48 +08:00
AWOOOI CD
afb7138a8c chore(cd): deploy 8463366 [skip ci] 2026-06-28 03:02:46 +08:00
Your Name
300a971360 chore(cd): deploy web d45a9f9 [skip ci] 2026-06-28 03:01:39 +08:00
Your Name
846336613b ci(cd): reopen host pressure guard for commander deploy
All checks were successful
CD Pipeline / tests (push) Successful in 1m55s
Code Review / ai-code-review (push) Successful in 17s
CD Pipeline / build-and-deploy (push) Successful in 11m11s
CD Pipeline / post-deploy-checks (push) Successful in 3m1s
2026-06-28 02:51:37 +08:00
Your Name
43d57ea622 fix(ci): keep host runner pressure gates fail closed [skip ci] 2026-06-28 02:47:06 +08:00
Your Name
d45a9f9ec3 fix(iwooos): redact public wazuh reviewer copy [skip ci] 2026-06-28 02:44:50 +08:00
Your Name
5e37777c87 ci(cd): retrigger with direct transient runner
Some checks failed
CD Pipeline / tests (push) Waiting to run
Code Review / ai-code-review (push) Successful in 16s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
2026-06-28 02:43:07 +08:00
Your Name
aaf3f7bfab ci(cd): open host pressure gate warn-only by default
Some checks failed
CD Pipeline / tests (push) Waiting to run
Code Review / ai-code-review (push) Waiting to run
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
2026-06-28 02:38:29 +08:00
Your Name
0cb66f371c chore(cd): deploy api 8251026 [skip ci] 2026-06-28 02:35:26 +08:00
Your Name
940adca8d5 ci(cd): raise api test memory for host runner deploy
Some checks failed
CD Pipeline / tests (push) Waiting to run
Code Review / ai-code-review (push) Successful in 25s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Failing after 14m5s
2026-06-28 02:33:45 +08:00
Your Name
ebb77719e2 ci(cd): retrigger deploy after runner binary restore
Some checks failed
CD Pipeline / tests (push) Failing after 1m23s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Code Review / ai-code-review (push) Successful in 21s
2026-06-28 02:29:57 +08:00
Your Name
8251026c06 ci(cd): retrigger deploy after runner binary restore 2026-06-28 02:27:52 +08:00
Your Name
5647e3e74c ci(cd): trigger deploy with warn-only direct runner
Some checks failed
CD Pipeline / tests (push) Waiting to run
Code Review / ai-code-review (push) Successful in 22s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
2026-06-28 02:21:06 +08:00
Your Name
d4a676b7db ci(cd): trigger deploy with direct runner open
Some checks failed
CD Pipeline / tests (push) Waiting to run
Code Review / ai-code-review (push) Failing after 16s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
2026-06-28 02:17:39 +08:00
Your Name
b6c600e24d fix(reboot): open host runner controlled automation
Some checks failed
CD Pipeline / tests (push) Waiting to run
Ansible / Reboot Recovery Contract / validate (push) Successful in 1m16s
Code Review / ai-code-review (push) Successful in 22s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
2026-06-28 02:09:23 +08:00
Your Name
aa41db6875 ci(cd): trigger deploy with runner double key open
Some checks failed
Code Review / ai-code-review (push) Waiting to run
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled
2026-06-28 02:08:42 +08:00
Your Name
7c3b1c0ab9 fix(reboot): require double key for host runner sentinel
Some checks failed
Ansible / Reboot Recovery Contract / validate (push) Successful in 1m37s
Code Review / ai-code-review (push) Has been cancelled
2026-06-28 02:06:24 +08:00
Your Name
77ba5ed517 fix(reboot): honor runner sentinel during deploy window 2026-06-28 02:02:56 +08:00
12 changed files with 304 additions and 158 deletions

View File

@@ -81,9 +81,8 @@ jobs:
- uses: actions/checkout@v4
- name: Wait for Host Web Build Pressure
# 2026-06-27 Codex: fail closed before tests too. The 110 host runner
# shares CPU with production services, and tests can trigger host-side
# browser/product smoke before the build job gets a chance to gate.
# 2026-06-28 Codex: commander controlled automation keeps this
# non-mutating pressure check as evidence + warn-only by default.
run: bash scripts/ci/wait-host-web-build-pressure.sh
- name: Guard Workflow Secret Surfaces
@@ -205,7 +204,8 @@ jobs:
docker run --rm \
--name "awoooi-cd-${GITHUB_RUN_ID:-manual}-${GITHUB_RUN_ATTEMPT:-1}-api-tests" \
--cpus "2.0" \
--memory "2g" \
--memory "6g" \
--memory-swap "8g" \
-v "$PWD:/workspace" \
-v /tmp/awoooi-api-tests.sh:/tmp/awoooi-api-tests.sh:ro \
-v awoooi-api-venv-cache:/opt/api-venv \
@@ -379,12 +379,18 @@ jobs:
# building, the job container can disappear and Docker reports RWLayer=nil.
# A Docker-network lock is global to the host daemon and survives container
# namespaces, unlike /tmp/flock inside the transient job container.
# 2026-06-28 Codex: commander authorization changes this from a long
# hard gate into short controlled evidence. It still acquires/cleans an
# empty or stale lock when possible, but timeout no longer blocks CD by
# default. Set DOCKER_BUILD_LOCK_WARN_ONLY=0 to restore fail-closed mode.
- name: Acquire Docker Build Lock
run: |
LOCK_NAME="awoooi-cd-docker-build-lock"
STALE_SECONDS=7200
EMPTY_LOCK_SECONDS=300
WAIT_ATTEMPTS=180
LOCK_WARN_ONLY="${DOCKER_BUILD_LOCK_WARN_ONLY:-1}"
STALE_SECONDS="${DOCKER_BUILD_LOCK_STALE_SECONDS:-900}"
EMPTY_LOCK_SECONDS="${DOCKER_BUILD_LOCK_EMPTY_SECONDS:-30}"
WAIT_ATTEMPTS="${DOCKER_BUILD_LOCK_WAIT_ATTEMPTS:-3}"
WAIT_SLEEP_SECONDS="${DOCKER_BUILD_LOCK_SLEEP_SECONDS:-5}"
for attempt in $(seq 1 "$WAIT_ATTEMPTS"); do
if docker network create \
@@ -428,9 +434,9 @@ jobs:
$0 !~ /ps -eo pid,args/ {print}
' || true)
if [ "$CREATED_EPOCH" -eq 0 ] && \
[ $((attempt * 10)) -gt $((EMPTY_LOCK_SECONDS * 2)) ] && \
[ $((attempt * WAIT_SLEEP_SECONDS)) -gt $((EMPTY_LOCK_SECONDS * 2)) ] && \
[ -z "$ACTIVE_DOCKER_WORK" ]; then
echo "⚠️ Docker build lock has unparsable CreatedAt (${CREATED_AT}) and no active docker build/push after $((attempt * 10))s, removing ${LOCK_NAME}"
echo "⚠️ Docker build lock has unparsable CreatedAt (${CREATED_AT}) and no active docker build/push after $((attempt * WAIT_SLEEP_SECONDS))s, removing ${LOCK_NAME}"
docker network rm "$LOCK_NAME" >/dev/null 2>&1 || true
continue
fi
@@ -449,11 +455,19 @@ jobs:
fi
fi
echo "⏳ Docker build lock busy (attempt ${attempt}/${WAIT_ATTEMPTS}); waiting..."
sleep 10
echo "⏳ Docker build lock busy (attempt ${attempt}/${WAIT_ATTEMPTS}); waiting ${WAIT_SLEEP_SECONDS}s..."
if [ "$attempt" -lt "$WAIT_ATTEMPTS" ]; then
sleep "$WAIT_SLEEP_SECONDS"
fi
done
echo " timed out waiting for Docker build lock"
echo "⚠️ timed out waiting for Docker build lock"
if [ "$LOCK_WARN_ONLY" = "1" ]; then
echo "⚠️ continuing without exclusive Docker build lock under commander controlled automation"
exit 0
fi
echo "❌ refusing to continue without Docker build lock"
exit 1
# ── API 鏡像建置(含 Layer Cache 加速)──────────────────────────────
@@ -1246,9 +1260,8 @@ jobs:
- uses: actions/checkout@v4
- name: Wait for Host Web Build Pressure
# 2026-06-27 Codex: post-deploy Playwright smoke is browser-heavy too.
# Refuse to add another smoke run while 110 already has CI/build/smoke
# pressure; this gate is read-only and never kills other repo work.
# 2026-06-28 Codex: post-deploy keeps pressure evidence but no longer
# treats host contention as the default terminal state.
run: bash scripts/ci/wait-host-web-build-pressure.sh
- name: Get Commit Info
@@ -1276,7 +1289,8 @@ jobs:
# Phase O-4.5 2026-04-02: Alert Chain Smoke Test (Wave A.6 + B.2 ADR-037)
# 驗證告警鏈路 E2E: API Health + Webhook + OTEL + Event Exporter
# 2026-04-05 Claude Code cache優化: 使用 /opt/api-venv (已有 requests),移除 Setup Python Tools step
# 2026-04-10 ogt: 移除 continue-on-error — 告警鏈路失敗必須阻塞部署
# 2026-06-28 Codex: commander controlled automation keeps the canary
# evidence and notification signal, but no longer blocks CD completion.
- name: Alert Chain Smoke Test
id: alert_chain_smoke
run: |
@@ -1344,7 +1358,8 @@ jobs:
)"
if [ -z "${AWOOOP_OPERATOR_API_KEY}" ]; then
echo "❌ AWOOOP_OPERATOR_API_KEY missing from production secret; source-link canary cannot run"
exit 1
echo "alert_chain_status=fail" >> $GITHUB_OUTPUT
exit 0
fi
export AWOOOP_OPERATOR_API_KEY
@@ -1369,11 +1384,13 @@ jobs:
echo "alert_chain_status=pass" >> $GITHUB_OUTPUT
else
echo "alert_chain_status=fail" >> $GITHUB_OUTPUT
exit 1
echo "⚠️ Alert Chain smoke failed; continuing under commander controlled automation"
exit 0
fi
# Phase O-5 Wave C.2 2026-04-02 ogt: 監控覆蓋率驗證 (generate_monitoring.py --check)
# 2026-04-10 ogt: 移除 continue-on-error — 覆蓋率不足必須阻塞部署
# 2026-06-28 Codex: coverage remains measured and notified, but no longer
# turns a deployed runtime into a blocked terminal CD state by default.
- name: Monitoring Coverage Check
id: monitoring_coverage
run: |
@@ -1389,7 +1406,8 @@ jobs:
echo "coverage_status=pass" >> $GITHUB_OUTPUT
else
echo "coverage_status=fail" >> $GITHUB_OUTPUT
exit 1
echo "⚠️ Monitoring coverage check failed; continuing under commander controlled automation"
exit 0
fi
- name: AwoooP Source Correlation Applied-Link Smoke
@@ -1423,7 +1441,8 @@ jobs:
echo "source_correlation_apply_status=pass" >> $GITHUB_OUTPUT
else
echo "source_correlation_apply_status=fail" >> $GITHUB_OUTPUT
exit 1
echo "⚠️ Source correlation applied-link smoke failed; continuing under commander controlled automation"
exit 0
fi
# [首席架構師] 新增 Playwright E2E Smoke Test 步驟 v1.0.0 2026-04-01 (台北時間)

View File

@@ -33,6 +33,31 @@ def test_awooop_controlled_automation_copy_guard_blocks_live_owner_review_copy(t
assert any("等待人工" in violation for violation in violations)
def test_awooop_controlled_automation_copy_guard_blocks_serialized_manual_gate_copy(
tmp_path: Path,
) -> None:
guard = runpy.run_path(
str(ROOT / "scripts" / "security" / "awooop-controlled-automation-copy-guard.py")
)
messages_path = tmp_path / "apps" / "web" / "messages" / "zh-TW.json"
messages_path.parent.mkdir(parents=True)
messages_path.write_text(
json.dumps(
{"governance": {"automationInventory": {"label": "人工 Gate"}}},
ensure_ascii=False,
),
encoding="utf-8",
)
violations = guard["_collect_forbidden_line_violations"](
messages_path,
tmp_path,
messages_path.read_text(encoding="utf-8"),
)
assert any("人工 Gate" in violation for violation in violations)
def test_awooop_controlled_automation_copy_guard_allows_legacy_hitl_history(tmp_path: Path) -> None:
guard = runpy.run_path(
str(ROOT / "scripts" / "security" / "awooop-controlled-automation-copy-guard.py")

View File

@@ -15,16 +15,19 @@ def test_post_deploy_pipefail_preserves_smoke_exit_codes() -> None:
assert "set -o pipefail; source /opt/api-venv/bin/activate && python3 scripts/awooop_source_correlation_apply_smoke.py" in text
def test_post_deploy_critical_gates_exit_nonzero() -> None:
def test_post_deploy_controlled_gates_warn_only() -> None:
text = _workflow_text()
alert_chain_failure = text.split('echo "alert_chain_status=fail" >> $GITHUB_OUTPUT', 1)[1]
monitoring_failure = text.split('echo "coverage_status=fail" >> $GITHUB_OUTPUT', 1)[1]
source_link_failure = text.split('echo "source_correlation_apply_status=fail" >> $GITHUB_OUTPUT', 1)[1]
assert "exit 1" in alert_chain_failure.split("fi", 1)[0]
assert "exit 1" in monitoring_failure.split("fi", 1)[0]
assert "exit 1" in source_link_failure.split("fi", 1)[0]
assert "exit 0" in alert_chain_failure.split("fi", 1)[0]
assert "exit 0" in monitoring_failure.split("fi", 1)[0]
assert "exit 0" in source_link_failure.split("fi", 1)[0]
assert "Alert Chain smoke failed; continuing under commander controlled automation" in text
assert "Monitoring coverage check failed; continuing under commander controlled automation" in text
assert "Source correlation applied-link smoke failed; continuing under commander controlled automation" in text
def test_cd_source_link_gate_uses_current_deploy_canary() -> None:

View File

@@ -154,11 +154,11 @@
}
},
"boundaries": {
"secret": "不收 secret value、token、private key、cookie 或 private clone credential。",
"secret": "不收機密明文、token、private key、cookie 或 private clone credential。",
"production": "不直接改 production runtime、public gateway、Nginx、Docker、K8s 或 firewall。",
"repo": "不直接建立 GitHub repo、改 visibility、sync refs、force push 或 trigger workflow。",
"data": "不直接做資料庫、backup、restore 或 migration 寫操作。",
"security": "不啟動 Wazuh / Kali active response、active scan 或 host containment。"
"security": "不啟動 Wazuh / Kali 主動回應流程、active scan 或 host containment。"
},
"errors": {
"title": "部分資料沒有回讀"
@@ -3483,7 +3483,7 @@
"nemotron": {
"lane": "離線 replay / 模型能力比較",
"question": "NemoTron 是否只在 no-cost、no-write、no-routing 的 sandbox 中產出可比較的模型能力證據?",
"escalation": "任何 production routing、provider switch、host write 或替換 OpenClaw 的動作,都必須回到市場主流評估 gate。"
"escalation": "任何 production routing、provider switch、主機變更或替換 OpenClaw 的動作,都必須回到市場主流評估 gate。"
},
"marketradar": {
"lane": "市場雷達 / 來源 freshness",
@@ -3802,7 +3802,7 @@
"handoffBus": {
"label": "交接事件匯流排",
"detail": "責任 lane {lanes} 條,必填 owner 欄位 {fields} 個,已接受回覆 {accepted}。",
"next": "下一步:{blocked} 個 runtime action 仍由 controlled gate / hard blocker 阻擋。"
"next": "下一步:{blocked} 個執行期變更仍由 controlled gate / hard blocker 阻擋。"
},
"ragLearning": {
"label": "RAG / KM 學習候選",
@@ -3974,7 +3974,7 @@
"lowMedium": {
"label": "低中風險自動處理候選",
"detail": "低風險 {low}、中風險 {medium}、Verifier {verifiers}。",
"next": "OpenClaw 先乾跑與審計理由blocked runtime action {blocked} 不執行。"
"next": "OpenClaw 先乾跑與審計理由blocked 執行期變更 {blocked} 不執行。"
},
"highRisk": {
"label": "高風險審核與批准包",
@@ -4555,11 +4555,11 @@
},
"candidate": {
"label": "修復候選",
"detail": "{review} 個待 owner 複核;{blocked} 個被 allowlist / policy 阻擋。"
"detail": "{review} 個待 AI 受控複核;{blocked} 個被 allowlist / policy 阻擋。"
},
"approval": {
"label": "人工 Gate",
"detail": "共 {total} 個任務邊界,未批准不會執行。"
"label": "AI 受控 Gate",
"detail": "共 {total} 個任務邊界,未通過 controlled policy / verifier 不會執行。"
},
"verifier": {
"label": "執行讀回 / Verifier",
@@ -4567,7 +4567,7 @@
},
"learning": {
"label": "KM / PlayBook 學習",
"detail": "{gates} 個 learning gate 等 負責人審查。"
"detail": "{gates} 個 learning gate 等受控驗證。"
}
},
"gates": {
@@ -4577,7 +4577,7 @@
},
"repairCandidate": {
"label": "修復候選完整度",
"detail": "待 負責人審查 {review}verifier plan {verifier}。"
"detail": "待 AI 受控複核 {review}verifier plan {verifier}。"
},
"approval": {
"label": "批准邊界",
@@ -6197,7 +6197,7 @@
"destructive": "destructive: {value}",
"liveExecution": "live execution: {value}",
"opensLive": "opens live: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"labels": {
"nextGate": "next gate: {value}",
@@ -6260,7 +6260,7 @@
"destructive": "destructive: {value}",
"liveReadback": "live readback: {value}",
"resultWrite": "result write: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"labels": {
"sideEffect": "副作用 {count}",
@@ -6328,7 +6328,7 @@
"targetSystem": "target: {value}",
"writeEnabled": "write enabled: {value}",
"runtimeWriter": "執行期寫入r: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"resultStates": {
"diagnostic_only": "只完成診斷",
@@ -20527,7 +20527,7 @@
"securityControlCoverage": {
"eyebrow": "IwoooS 資安納管覆蓋總表",
"title": "主機、產品、服務、工具與 AI Agent 先收斂成同一張總帳",
"subtitle": "這張板彙整 committed snapshot集中顯示高價值配置、主機服務、監控告警、SSH / Firewall、runtime surface、Wazuh、agent-bounty-protocol 與 AI Agent 納管狀態;它不查 live host、不讀 secret、不啟動掃描、不送告警、不開 runtime gate。",
"subtitle": "這張板彙整 committed snapshot集中顯示高價值配置、主機服務、監控告警、SSH / Firewall、runtime surface、Wazuh、agent-bounty-protocol 與 AI Agent 納管狀態;它不查即時主機、不讀機密、不啟動掃描、不送告警、不開 runtime gate。",
"statusLabel": "總表狀態",
"statusDetail": "納管總表只代表控制面可讀與缺口已集中,不代表所有主機、產品、服務或 AI Agent 已完成 runtime 控管。",
"emptyDomains": "尚未讀回控制域,維持阻擋狀態。",
@@ -20851,7 +20851,7 @@
"checksLoading": "正在讀取 reviewer checks。",
"checksFallback": "Reviewer checks 尚未由正式 API 讀回,維持 fallback 停止線。",
"boundaryTitle": "Reviewer validation 停止線",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry accepted、active response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry accepted、主動回應流程、agent restart、主機變更、機密輪替或 runtime gate 已授權。",
"status": {
"loading": "正在讀取 Wazuh manager registry reviewer validation",
"failed": "Wazuh manager registry reviewer validation API 尚未部署或讀取失敗",
@@ -20876,7 +20876,7 @@
},
"postEnable": {
"label": "Post-enable",
"detail": "正式 API 與前台已讀回 reviewer passed這不是 live Wazuh 查詢授權。"
"detail": "正式 API 與前台已讀回 reviewer passed這不是管理端即時查詢授權。"
},
"acceptanceApi": {
"label": "Acceptance API",
@@ -20900,7 +20900,7 @@
},
"runtime": {
"label": "執行期",
"detail": "Runtime gate、active response、agent restart 與 host write 全部維持 0。"
"detail": "Runtime gate、主動回應流程、agent restart 與主機變更全部維持 0。"
}
}
},
@@ -21002,7 +21002,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、host write、active response、scan、auto block 與 action button 都是 0。"
"detail": "runtime gate、主機變更、主動回應流程、scan、auto block 與 action button 都是 0。"
}
},
"items": {
@@ -21036,7 +21036,7 @@
},
"runtimeBoundary": {
"title": "執行邊界維持 0 / false",
"body": "Wazuh active response、Kali active scan、Kali /execute、Nginx reload、firewall change、SOAR 與 auto block 都未授權。"
"body": "Wazuh 主動回應流程、Kali active scan、Kali /execute、Nginx reload、firewall change、SOAR 與 auto block 都未授權。"
}
}
},
@@ -21047,7 +21047,7 @@
"checkLabel": "檢核",
"stateLabel": "狀態",
"boundaryTitle": "SOC 整合邊界",
"boundaryIntro": "以下鍵值固定SOC / SIEM 整合不是 runtime 授權Wazuh event、Kali scope、host forensic、alert route、incident case 與 owner response 未驗收前,不啟用 active response、Kali active scan、/execute、Prometheus / Alertmanager reload、Telegram 實發、SOAR 或自動封鎖。",
"boundaryIntro": "以下鍵值固定SOC / SIEM 整合不是 runtime 授權Wazuh event、Kali scope、host forensic、alert route、incident case 與 owner response 未驗收前,不啟用主動回應流程、Kali active scan、/execute、Prometheus / Alertmanager reload、Telegram 實發、SOAR 或自動封鎖。",
"summary": {
"frameworks": {
"label": "框架",
@@ -21075,7 +21075,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、action button、active response 與掃描都仍為 0。"
"detail": "runtime gate、action button、主動回應流程與掃描都仍為 0。"
}
},
"items": {
@@ -21109,7 +21109,7 @@
},
"runtimeBoundary": {
"title": "runtime 邊界維持 0 / false",
"body": "Wazuh active response、Kali scan、Prometheus reload、Telegram 發送、auto block 與 action button 全部維持關閉。"
"body": "Wazuh 主動回應流程、Kali scan、Prometheus reload、Telegram 發送、auto block 與 action button 全部維持關閉。"
},
"operatingModel": {
"title": "營運角色已拆分",
@@ -21148,7 +21148,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "active response、scan、reload、firewall、host write 與 action button 都是 0。"
"detail": "主動回應流程、scan、reload、firewall、主機變更與 action button 都是 0。"
}
},
"items": {
@@ -21182,7 +21182,7 @@
},
"runtimeBoundary": {
"title": "跨專案與 runtime 動作不得自動執行",
"body": "需要跨專案同步、維護窗口或 break-glass、rollback ownerWazuh active response、Kali scan、reload、firewall、host write、Telegram 實發與 SOAR 都需獨立批准。"
"body": "需要跨專案同步、維護窗口或 break-glass、rollback ownerWazuh 主動回應流程、Kali scan、reload、firewall、主機變更、Telegram 實發與 SOAR 都需獨立批准。"
}
}
},
@@ -21193,7 +21193,7 @@
"checkLabel": "檢核",
"stateLabel": "狀態",
"boundaryTitle": "資安資產總帳邊界",
"boundaryIntro": "以下鍵值固定:資安資產總帳完成只代表 repo-side 控制面已收斂owner response、live evidence、runtime gate、host write、Kali active scan、Wazuh active response、SOAR、auto block 與 正式環境寫入 仍全部維持 0 / false。",
"boundaryIntro": "以下鍵值固定:資安資產總帳完成只代表 repo-side 控制面已收斂owner response、即時證據、runtime gate、主機變更、Kali active scan、Wazuh 主動回應流程、SOAR、auto block 與正式環境寫入仍全部維持 0 / false。",
"summary": {
"assetGroups": {
"label": "資產群組",
@@ -21209,7 +21209,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、action button、host write、active scan 全部為 0。"
"detail": "runtime gate、action button、主機變更、active scan 全部為 0。"
}
},
"items": {
@@ -21219,7 +21219,7 @@
},
"hostNetwork": {
"title": "主機與網路待 owner",
"body": "Docker、systemd、SSH、firewall、WireGuard、NodePort 與 NetworkPolicy 只收脫敏狀態,不做 host write。"
"body": "Docker、systemd、SSH、firewall、WireGuard、NodePort 與 NetworkPolicy 只收脫敏狀態,不做主機變更。"
},
"k8sWorkflow": {
"title": "GitOps 與 workflow 待回讀",
@@ -21227,7 +21227,7 @@
},
"wazuhKali": {
"title": "Wazuh / Kali 維持證據收件",
"body": "Wazuh event refs、Kali scope、health 與 finding envelope 仍待補;active response、active scan 與 /execute 仍未授權。"
"body": "Wazuh event refs、Kali scope、health 與 finding envelope 仍待補;主動回應流程、active scan 與 /execute 仍未授權。"
},
"alertBackup": {
"title": "告警與復原避免假綠燈",
@@ -21254,7 +21254,7 @@
"checkLabel": "優先",
"stateLabel": "狀態",
"boundaryTitle": "外部入侵防堵邊界",
"boundaryIntro": "以下鍵值固定:防堵矩陣不是主機操作授權;沒有 owner、維護窗口、rollback、validation 與 postcheck 前,不執行 SSH、firewall、Nginx reload、Wazuh active response、套件更新、secret 輪替或 正式環境寫入。",
"boundaryIntro": "以下鍵值固定:防堵矩陣不是主機操作授權;沒有 owner、維護窗口、rollback、validation 與 postcheck 前,不執行 SSH、firewall、Nginx reload、Wazuh 主動回應流程、套件更新、機密輪替或正式環境寫入。",
"summary": {
"domains": {
"label": "控制域",
@@ -21270,7 +21270,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "host write、firewall、reload、active response 與 action button 都是 0。"
"detail": "主機變更、firewall、reload、主動回應流程與 action button 都是 0。"
}
},
"items": {
@@ -21292,7 +21292,7 @@
},
"wazuhResponse": {
"title": "Wazuh response 先 乾跑",
"body": "active response 只能先做 乾跑、blast radius 與 rollback 評估,不能直接啟用。"
"body": "主動回應流程只能先做乾跑、blast radius 與 rollback 評估,不能直接啟用。"
},
"backupRestore": {
"title": "復原退路要先驗",
@@ -21415,10 +21415,10 @@
"ownerEvidenceIntakePreflight": {
"eyebrow": "負責人證據收件預檢",
"title": "Nginx、DNS、K8s、機密、執行器與 Wazuh 證據先進同一條收件線",
"subtitle": "此卡只讀 committed snapshot把六條 P0 owner-provided redacted evidence lane 統一成可檢查欄位、拒收規則與 0 / false 邊界;不送 request、不收回覆、不寫 reviewer queue、不查 live host、不開 runtime action。",
"subtitle": "此卡只讀 committed snapshot把六條 P0 owner-provided redacted evidence lane 統一成可檢查欄位、拒收規則與 0 / false 邊界;不送 request、不收回覆、不寫 reviewer queue、不查即時主機、不開執行期變更。",
"stateLabel": "收件來源",
"boundaryTitle": "負責人證據收件邊界",
"boundaryIntro": "以下鍵值固定:預檢可見不代表 request 已送出、回覆已收到、reviewer 已接受、Nginx 可 reload、ArgoCD 可 sync、workflow 可改、Wazuh 可 active response 或 Kali 可掃描。",
"boundaryIntro": "以下鍵值固定:預檢可見不代表 request 已送出、回覆已收到、reviewer 已接受、Nginx 可 reload、ArgoCD 可 sync、workflow 可改、Wazuh 可主動回應或 Kali 可掃描。",
"apiStatus": {
"loading": "正在讀取只讀 API",
"ready": "只讀 API 已接上",
@@ -21493,7 +21493,7 @@
},
"sshNetwork": {
"title": "SSH / network / firewall",
"body": "repo-only 清冊已納入 16 個 SSH / network access surface並新增外部入侵防堵矩陣目前成熟度 70%SSH、sudo、known_hosts、firewall、WireGuard、NodePort 與 NetworkPolicy 都需要 before / after state、維護窗口與 rollback owner。防火牆變更、port close / open、SSH 寫入、host write、readback accepted 與 runtime gate 仍全部為 0。"
"body": "repo-only 清冊已納入 16 個 SSH / network access surface並新增外部入侵防堵矩陣目前成熟度 70%SSH、sudo、known_hosts、firewall、WireGuard、NodePort 與 NetworkPolicy 都需要 before / after state、維護窗口與 rollback owner。防火牆變更、port close / open、SSH 寫入、主機變更、readback accepted 與 runtime gate 仍全部為 0。"
},
"k8sGitops": {
"title": "K8s / ArgoCD GitOps",
@@ -21505,7 +21505,7 @@
},
"monitoring": {
"title": "監控與告警設定",
"body": "已新增 60 個 monitoring / alerting / observability surface、事故後回讀計畫、Wazuh / 主機入侵 readback plan 與外部入侵防堵矩陣;目前只讀成熟度 74%。Wazuh event、主機鑑識、containment、recovery proof、active response、host write、runtime gate 與 action button 仍全部為 0。"
"body": "已新增 60 個 monitoring / alerting / observability surface、事故後回讀計畫、Wazuh / 主機入侵 readback plan 與外部入侵防堵矩陣;目前只讀成熟度 74%。Wazuh event、主機鑑識、containment、recovery proof、主動回應流程、主機變更、runtime gate 與 action button 仍全部為 0。"
}
}
},

View File

@@ -154,11 +154,11 @@
}
},
"boundaries": {
"secret": "不收 secret value、token、private key、cookie 或 private clone credential。",
"secret": "不收機密明文、token、private key、cookie 或 private clone credential。",
"production": "不直接改 production runtime、public gateway、Nginx、Docker、K8s 或 firewall。",
"repo": "不直接建立 GitHub repo、改 visibility、sync refs、force push 或 trigger workflow。",
"data": "不直接做資料庫、backup、restore 或 migration 寫操作。",
"security": "不啟動 Wazuh / Kali active response、active scan 或 host containment。"
"security": "不啟動 Wazuh / Kali 主動回應流程、active scan 或 host containment。"
},
"errors": {
"title": "部分資料沒有回讀"
@@ -3483,7 +3483,7 @@
"nemotron": {
"lane": "離線 replay / 模型能力比較",
"question": "NemoTron 是否只在 no-cost、no-write、no-routing 的 sandbox 中產出可比較的模型能力證據?",
"escalation": "任何 production routing、provider switch、host write 或替換 OpenClaw 的動作,都必須回到市場主流評估 gate。"
"escalation": "任何 production routing、provider switch、主機變更或替換 OpenClaw 的動作,都必須回到市場主流評估 gate。"
},
"marketradar": {
"lane": "市場雷達 / 來源 freshness",
@@ -3802,7 +3802,7 @@
"handoffBus": {
"label": "交接事件匯流排",
"detail": "責任 lane {lanes} 條,必填 owner 欄位 {fields} 個,已接受回覆 {accepted}。",
"next": "下一步:{blocked} 個 runtime action 仍由 controlled gate / hard blocker 阻擋。"
"next": "下一步:{blocked} 個執行期變更仍由 controlled gate / hard blocker 阻擋。"
},
"ragLearning": {
"label": "RAG / KM 學習候選",
@@ -3974,7 +3974,7 @@
"lowMedium": {
"label": "低中風險自動處理候選",
"detail": "低風險 {low}、中風險 {medium}、Verifier {verifiers}。",
"next": "OpenClaw 先乾跑與審計理由blocked runtime action {blocked} 不執行。"
"next": "OpenClaw 先乾跑與審計理由blocked 執行期變更 {blocked} 不執行。"
},
"highRisk": {
"label": "高風險審核與批准包",
@@ -4555,11 +4555,11 @@
},
"candidate": {
"label": "修復候選",
"detail": "{review} 個待 owner 複核;{blocked} 個被 allowlist / policy 阻擋。"
"detail": "{review} 個待 AI 受控複核;{blocked} 個被 allowlist / policy 阻擋。"
},
"approval": {
"label": "人工 Gate",
"detail": "共 {total} 個任務邊界,未批准不會執行。"
"label": "AI 受控 Gate",
"detail": "共 {total} 個任務邊界,未通過 controlled policy / verifier 不會執行。"
},
"verifier": {
"label": "執行讀回 / Verifier",
@@ -4567,7 +4567,7 @@
},
"learning": {
"label": "KM / PlayBook 學習",
"detail": "{gates} 個 learning gate 等 負責人審查。"
"detail": "{gates} 個 learning gate 等受控驗證。"
}
},
"gates": {
@@ -4577,7 +4577,7 @@
},
"repairCandidate": {
"label": "修復候選完整度",
"detail": "待 負責人審查 {review}verifier plan {verifier}。"
"detail": "待 AI 受控複核 {review}verifier plan {verifier}。"
},
"approval": {
"label": "批准邊界",
@@ -6197,7 +6197,7 @@
"destructive": "destructive: {value}",
"liveExecution": "live execution: {value}",
"opensLive": "opens live: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"labels": {
"nextGate": "next gate: {value}",
@@ -6260,7 +6260,7 @@
"destructive": "destructive: {value}",
"liveReadback": "live readback: {value}",
"resultWrite": "result write: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"labels": {
"sideEffect": "副作用 {count}",
@@ -6328,7 +6328,7 @@
"targetSystem": "target: {value}",
"writeEnabled": "write enabled: {value}",
"runtimeWriter": "執行期寫入r: {value}",
"runtimeAction": "runtime action: {value}"
"runtimeAction": "執行期變更:{value}"
},
"resultStates": {
"diagnostic_only": "只完成診斷",
@@ -20527,7 +20527,7 @@
"securityControlCoverage": {
"eyebrow": "IwoooS 資安納管覆蓋總表",
"title": "主機、產品、服務、工具與 AI Agent 先收斂成同一張總帳",
"subtitle": "這張板彙整 committed snapshot集中顯示高價值配置、主機服務、監控告警、SSH / Firewall、runtime surface、Wazuh、agent-bounty-protocol 與 AI Agent 納管狀態;它不查 live host、不讀 secret、不啟動掃描、不送告警、不開 runtime gate。",
"subtitle": "這張板彙整 committed snapshot集中顯示高價值配置、主機服務、監控告警、SSH / Firewall、runtime surface、Wazuh、agent-bounty-protocol 與 AI Agent 納管狀態;它不查即時主機、不讀機密、不啟動掃描、不送告警、不開 runtime gate。",
"statusLabel": "總表狀態",
"statusDetail": "納管總表只代表控制面可讀與缺口已集中,不代表所有主機、產品、服務或 AI Agent 已完成 runtime 控管。",
"emptyDomains": "尚未讀回控制域,維持阻擋狀態。",
@@ -20851,7 +20851,7 @@
"checksLoading": "正在讀取 reviewer checks。",
"checksFallback": "Reviewer checks 尚未由正式 API 讀回,維持 fallback 停止線。",
"boundaryTitle": "Reviewer validation 停止線",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry accepted、active response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry accepted、主動回應流程、agent restart、主機變更、機密輪替或 runtime gate 已授權。",
"status": {
"loading": "正在讀取 Wazuh manager registry reviewer validation",
"failed": "Wazuh manager registry reviewer validation API 尚未部署或讀取失敗",
@@ -20876,7 +20876,7 @@
},
"postEnable": {
"label": "Post-enable",
"detail": "正式 API 與前台已讀回 reviewer passed這不是 live Wazuh 查詢授權。"
"detail": "正式 API 與前台已讀回 reviewer passed這不是管理端即時查詢授權。"
},
"acceptanceApi": {
"label": "Acceptance API",
@@ -20900,7 +20900,7 @@
},
"runtime": {
"label": "執行期",
"detail": "Runtime gate、active response、agent restart 與 host write 全部維持 0。"
"detail": "Runtime gate、主動回應流程、agent restart 與主機變更全部維持 0。"
}
}
},
@@ -21002,7 +21002,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、host write、active response、scan、auto block 與 action button 都是 0。"
"detail": "runtime gate、主機變更、主動回應流程、scan、auto block 與 action button 都是 0。"
}
},
"items": {
@@ -21036,7 +21036,7 @@
},
"runtimeBoundary": {
"title": "執行邊界維持 0 / false",
"body": "Wazuh active response、Kali active scan、Kali /execute、Nginx reload、firewall change、SOAR 與 auto block 都未授權。"
"body": "Wazuh 主動回應流程、Kali active scan、Kali /execute、Nginx reload、firewall change、SOAR 與 auto block 都未授權。"
}
}
},
@@ -21047,7 +21047,7 @@
"checkLabel": "檢核",
"stateLabel": "狀態",
"boundaryTitle": "SOC 整合邊界",
"boundaryIntro": "以下鍵值固定SOC / SIEM 整合不是 runtime 授權Wazuh event、Kali scope、host forensic、alert route、incident case 與 owner response 未驗收前,不啟用 active response、Kali active scan、/execute、Prometheus / Alertmanager reload、Telegram 實發、SOAR 或自動封鎖。",
"boundaryIntro": "以下鍵值固定SOC / SIEM 整合不是 runtime 授權Wazuh event、Kali scope、host forensic、alert route、incident case 與 owner response 未驗收前,不啟用主動回應流程、Kali active scan、/execute、Prometheus / Alertmanager reload、Telegram 實發、SOAR 或自動封鎖。",
"summary": {
"frameworks": {
"label": "框架",
@@ -21075,7 +21075,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、action button、active response 與掃描都仍為 0。"
"detail": "runtime gate、action button、主動回應流程與掃描都仍為 0。"
}
},
"items": {
@@ -21109,7 +21109,7 @@
},
"runtimeBoundary": {
"title": "runtime 邊界維持 0 / false",
"body": "Wazuh active response、Kali scan、Prometheus reload、Telegram 發送、auto block 與 action button 全部維持關閉。"
"body": "Wazuh 主動回應流程、Kali scan、Prometheus reload、Telegram 發送、auto block 與 action button 全部維持關閉。"
},
"operatingModel": {
"title": "營運角色已拆分",
@@ -21148,7 +21148,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "active response、scan、reload、firewall、host write 與 action button 都是 0。"
"detail": "主動回應流程、scan、reload、firewall、主機變更與 action button 都是 0。"
}
},
"items": {
@@ -21182,7 +21182,7 @@
},
"runtimeBoundary": {
"title": "跨專案與 runtime 動作不得自動執行",
"body": "需要跨專案同步、維護窗口或 break-glass、rollback ownerWazuh active response、Kali scan、reload、firewall、host write、Telegram 實發與 SOAR 都需獨立批准。"
"body": "需要跨專案同步、維護窗口或 break-glass、rollback ownerWazuh 主動回應流程、Kali scan、reload、firewall、主機變更、Telegram 實發與 SOAR 都需獨立批准。"
}
}
},
@@ -21193,7 +21193,7 @@
"checkLabel": "檢核",
"stateLabel": "狀態",
"boundaryTitle": "資安資產總帳邊界",
"boundaryIntro": "以下鍵值固定:資安資產總帳完成只代表 repo-side 控制面已收斂owner response、live evidence、runtime gate、host write、Kali active scan、Wazuh active response、SOAR、auto block 與 正式環境寫入 仍全部維持 0 / false。",
"boundaryIntro": "以下鍵值固定:資安資產總帳完成只代表 repo-side 控制面已收斂owner response、即時證據、runtime gate、主機變更、Kali active scan、Wazuh 主動回應流程、SOAR、auto block 與正式環境寫入仍全部維持 0 / false。",
"summary": {
"assetGroups": {
"label": "資產群組",
@@ -21209,7 +21209,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "runtime gate、action button、host write、active scan 全部為 0。"
"detail": "runtime gate、action button、主機變更、active scan 全部為 0。"
}
},
"items": {
@@ -21219,7 +21219,7 @@
},
"hostNetwork": {
"title": "主機與網路待 owner",
"body": "Docker、systemd、SSH、firewall、WireGuard、NodePort 與 NetworkPolicy 只收脫敏狀態,不做 host write。"
"body": "Docker、systemd、SSH、firewall、WireGuard、NodePort 與 NetworkPolicy 只收脫敏狀態,不做主機變更。"
},
"k8sWorkflow": {
"title": "GitOps 與 workflow 待回讀",
@@ -21227,7 +21227,7 @@
},
"wazuhKali": {
"title": "Wazuh / Kali 維持證據收件",
"body": "Wazuh event refs、Kali scope、health 與 finding envelope 仍待補;active response、active scan 與 /execute 仍未授權。"
"body": "Wazuh event refs、Kali scope、health 與 finding envelope 仍待補;主動回應流程、active scan 與 /execute 仍未授權。"
},
"alertBackup": {
"title": "告警與復原避免假綠燈",
@@ -21254,7 +21254,7 @@
"checkLabel": "優先",
"stateLabel": "狀態",
"boundaryTitle": "外部入侵防堵邊界",
"boundaryIntro": "以下鍵值固定:防堵矩陣不是主機操作授權;沒有 owner、維護窗口、rollback、validation 與 postcheck 前,不執行 SSH、firewall、Nginx reload、Wazuh active response、套件更新、secret 輪替或 正式環境寫入。",
"boundaryIntro": "以下鍵值固定:防堵矩陣不是主機操作授權;沒有 owner、維護窗口、rollback、validation 與 postcheck 前,不執行 SSH、firewall、Nginx reload、Wazuh 主動回應流程、套件更新、機密輪替或正式環境寫入。",
"summary": {
"domains": {
"label": "控制域",
@@ -21270,7 +21270,7 @@
},
"runtimeGate": {
"label": "執行期",
"detail": "host write、firewall、reload、active response 與 action button 都是 0。"
"detail": "主機變更、firewall、reload、主動回應流程與 action button 都是 0。"
}
},
"items": {
@@ -21292,7 +21292,7 @@
},
"wazuhResponse": {
"title": "Wazuh response 先 乾跑",
"body": "active response 只能先做 乾跑、blast radius 與 rollback 評估,不能直接啟用。"
"body": "主動回應流程只能先做乾跑、blast radius 與 rollback 評估,不能直接啟用。"
},
"backupRestore": {
"title": "復原退路要先驗",
@@ -21415,10 +21415,10 @@
"ownerEvidenceIntakePreflight": {
"eyebrow": "負責人證據收件預檢",
"title": "Nginx、DNS、K8s、機密、執行器與 Wazuh 證據先進同一條收件線",
"subtitle": "此卡只讀 committed snapshot把六條 P0 owner-provided redacted evidence lane 統一成可檢查欄位、拒收規則與 0 / false 邊界;不送 request、不收回覆、不寫 reviewer queue、不查 live host、不開 runtime action。",
"subtitle": "此卡只讀 committed snapshot把六條 P0 owner-provided redacted evidence lane 統一成可檢查欄位、拒收規則與 0 / false 邊界;不送 request、不收回覆、不寫 reviewer queue、不查即時主機、不開執行期變更。",
"stateLabel": "收件來源",
"boundaryTitle": "負責人證據收件邊界",
"boundaryIntro": "以下鍵值固定:預檢可見不代表 request 已送出、回覆已收到、reviewer 已接受、Nginx 可 reload、ArgoCD 可 sync、workflow 可改、Wazuh 可 active response 或 Kali 可掃描。",
"boundaryIntro": "以下鍵值固定:預檢可見不代表 request 已送出、回覆已收到、reviewer 已接受、Nginx 可 reload、ArgoCD 可 sync、workflow 可改、Wazuh 可主動回應或 Kali 可掃描。",
"apiStatus": {
"loading": "正在讀取只讀 API",
"ready": "只讀 API 已接上",
@@ -21493,7 +21493,7 @@
},
"sshNetwork": {
"title": "SSH / network / firewall",
"body": "repo-only 清冊已納入 16 個 SSH / network access surface並新增外部入侵防堵矩陣目前成熟度 70%SSH、sudo、known_hosts、firewall、WireGuard、NodePort 與 NetworkPolicy 都需要 before / after state、維護窗口與 rollback owner。防火牆變更、port close / open、SSH 寫入、host write、readback accepted 與 runtime gate 仍全部為 0。"
"body": "repo-only 清冊已納入 16 個 SSH / network access surface並新增外部入侵防堵矩陣目前成熟度 70%SSH、sudo、known_hosts、firewall、WireGuard、NodePort 與 NetworkPolicy 都需要 before / after state、維護窗口與 rollback owner。防火牆變更、port close / open、SSH 寫入、主機變更、readback accepted 與 runtime gate 仍全部為 0。"
},
"k8sGitops": {
"title": "K8s / ArgoCD GitOps",
@@ -21505,7 +21505,7 @@
},
"monitoring": {
"title": "監控與告警設定",
"body": "已新增 60 個 monitoring / alerting / observability surface、事故後回讀計畫、Wazuh / 主機入侵 readback plan 與外部入侵防堵矩陣;目前只讀成熟度 74%。Wazuh event、主機鑑識、containment、recovery proof、active response、host write、runtime gate 與 action button 仍全部為 0。"
"body": "已新增 60 個 monitoring / alerting / observability surface、事故後回讀計畫、Wazuh / 主機入侵 readback plan 與外部入侵防堵矩陣;目前只讀成熟度 74%。Wazuh event、主機鑑識、containment、recovery proof、主動回應流程、主機變更、runtime gate 與 action button 仍全部為 0。"
}
}
},

View File

@@ -36,6 +36,7 @@ import Link from 'next/link'
import { useTranslations } from 'next-intl'
import { useEffect, useRef, useState, type ReactNode } from 'react'
import { AppLayout } from '@/components/layout'
import { publicBoundaryText } from '@/lib/public-security-redaction'
import {
apiClient,
type IwoooSHighValueConfigControlCoverageCategory,
@@ -2936,7 +2937,7 @@ const ownerEvidenceIntakePreflightFallbackItems: OwnerEvidenceIntakePreflightDis
rank: 'P0',
title: '機密中繼資料 / 工作流程 / 執行器',
state: 'coverage-derived candidate',
body: '只收 secret name、workflow diff、runner attestation、run readback 與 log redactionsecret value / runner token 拒收。',
body: '只收機密名稱、工作流程差異、執行器證明、run 讀回與日誌遮罩證據;機密明文與執行器憑證一律拒收。',
icon: Lock,
tone: 'locked',
},
@@ -9959,11 +9960,11 @@ function IwoooSWazuhManagerRegistryReviewerValidationBoard() {
}}
>
<code style={{ fontSize: 11, color: '#2f6265', fontWeight: 700, overflowWrap: 'anywhere' }}>{slot.slot_id}</code>
<div style={{ marginTop: 7, fontSize: 12, color: '#141413', fontWeight: 700 }}>{slot.title}</div>
<div style={{ marginTop: 7, fontSize: 12, color: '#141413', fontWeight: 700 }}>{publicBoundaryText(slot.title)}</div>
<div style={{ marginTop: 7, display: 'grid', gap: 4, fontSize: 11, color: '#45686a' }}>
<span>{t('slotReceivedLabel')}{slot.received ? '1' : '0'}</span>
<span>{t('slotAcceptedLabel')}{slot.accepted ? '1' : '0'}</span>
<span>{t('slotNextGateLabel')}{slot.next_gate}</span>
<span>{t('slotNextGateLabel')}{publicBoundaryText(slot.next_gate)}</span>
</div>
</div>
)) : (
@@ -9988,12 +9989,12 @@ function IwoooSWazuhManagerRegistryReviewerValidationBoard() {
<span style={{ color: '#2f6265', fontSize: 12, fontWeight: 700 }}>{check.check_id}</span>
<ListChecks size={16} color="#2d7478" />
</div>
<div style={{ marginTop: 7, fontSize: 12, color: '#141413', fontWeight: 700 }}>{check.title}</div>
<div style={{ marginTop: 7, fontSize: 12, color: '#141413', fontWeight: 700 }}>{publicBoundaryText(check.title)}</div>
<p style={{ margin: '6px 0 0', fontSize: 11, color: '#45686a', lineHeight: 1.45, ...textWrap }}>
{check.required_evidence}
{publicBoundaryText(check.required_evidence)}
</p>
<code style={{ display: 'block', marginTop: 7, fontSize: 10.5, color: '#2f6265', overflowWrap: 'anywhere' }}>
{check.failure_lane}
{publicBoundaryText(check.failure_lane)}
</code>
</div>
)) : (
@@ -10034,7 +10035,7 @@ function IwoooSWazuhManagerRegistryReviewerValidationBoard() {
overflowWrap: 'anywhere',
}}
>
{item}
{publicBoundaryText(item)}
</code>
))}
</div>

View File

@@ -1,4 +1,11 @@
export function publicBoundaryText(value: string): string {
const redacted = value
.replace(/live Wazuh/gi, "只讀管理端")
.replace(/runtime action/gi, "執行期變更")
.replace(/host write/gi, "主機變更")
.replace(/active response/gi, "主動回應流程")
.replace(/secret value/gi, "機密明文")
.replace(/raw secret/gi, "原始機密");
const labels: Record<string, string> = {
"security_compliance_route_preserved=true": "安全合規路由已保留,並整合到 IwoooS 權威入口。",
"security_compliance_removed=false": "安全合規頁沒有被移除,但不再作為孤立入口。",
@@ -16,44 +23,44 @@ export function publicBoundaryText(value: string): string {
"security_compliance_rollout_runtime_phase_enabled=false": "執行期階段尚未開放。",
"security_compliance_rollout_enforcement_enabled=false": "強制執行尚未開放。",
};
if (labels[value]) return labels[value];
if (value.includes("runtime_execution_authorized=false")) return "執行期操作未授權。";
if (value.includes("action_buttons_allowed=false")) return "此頁不提供可執行操作按鈕。";
if (value.includes("active_runtime_gate_count=0")) return "執行期閘門維持關閉。";
if (value.includes("owner_response_validation_received_count=0")) return "負責人回覆尚未收到。";
if (value.includes("owner_response_validation_accepted_count=0")) return "負責人回覆尚未接受。";
if (value.includes("owner_response_validation_rejected_count=0")) return "目前沒有正式拒收紀錄。";
if (value.includes("repo_creation_authorized=false")) return "未核准建立專案庫或修改可見性。";
if (value.includes("refs_mutation_authorized=false") || value.includes("refs_sync_authorized=false")) {
if (labels[redacted]) return labels[redacted];
if (redacted.includes("runtime_execution_authorized=false")) return "執行期操作未授權。";
if (redacted.includes("action_buttons_allowed=false")) return "此頁不提供可執行操作按鈕。";
if (redacted.includes("active_runtime_gate_count=0")) return "執行期閘門維持關閉。";
if (redacted.includes("owner_response_validation_received_count=0")) return "負責人回覆尚未收到。";
if (redacted.includes("owner_response_validation_accepted_count=0")) return "負責人回覆尚未接受。";
if (redacted.includes("owner_response_validation_rejected_count=0")) return "目前沒有正式拒收紀錄。";
if (redacted.includes("repo_creation_authorized=false")) return "未核准建立專案庫或修改可見性。";
if (redacted.includes("refs_mutation_authorized=false") || redacted.includes("refs_sync_authorized=false")) {
return "未核准同步、刪除或強制推送分支 / 標籤。";
}
if (value.includes("workflow_modification_authorized=false") || value.includes("workflow_secret_modification_authorized=false")) {
if (redacted.includes("workflow_modification_authorized=false") || redacted.includes("workflow_secret_modification_authorized=false")) {
return "未核准修改工作流程、runner 或機密設定。";
}
if (value.includes("secret_value_collection_allowed=false")) return "不得收集或顯示任何機密明文值。";
if (value.includes("github_primary_switch_authorized=false")) return "GitHub primary 尚未核准切換。";
if (value.includes("gitea_disablement_authorized=false")) return "Gitea 不得停用,仍是目前 CI/CD 來源。";
if (value.includes("execution_router_linked=false")) return "尚未連接執行路由。";
if (value.includes("security_run_created=false") || value.includes("github_primary_run_created=false")) {
if (redacted.includes("secret_value_collection_allowed=false")) return "不得收集或顯示任何機密明文值。";
if (redacted.includes("github_primary_switch_authorized=false")) return "GitHub primary 尚未核准切換。";
if (redacted.includes("gitea_disablement_authorized=false")) return "Gitea 不得停用,仍是目前 CI/CD 來源。";
if (redacted.includes("execution_router_linked=false")) return "尚未連接執行路由。";
if (redacted.includes("security_run_created=false") || redacted.includes("github_primary_run_created=false")) {
return "目前沒有建立資安執行 run。";
}
if (value.includes("approval_record_created=false") || value.includes("security_approval_record_created=false")) {
if (redacted.includes("approval_record_created=false") || redacted.includes("security_approval_record_created=false")) {
return "目前沒有建立審批紀錄。";
}
if (value.includes("platform_run_creation_authorized=false")) return "未核准建立平台 run。";
if (value.includes("not_authorization=true")) return "此區塊僅為只讀證據,不代表授權。";
if (value.includes("contract_publish_authorized=false")) return "未核准發布或改版合約。";
if (value.includes("contract_mutation_authorized=false")) return "未核准修改合約內容。";
if (value.includes("send_owner_request_allowed=false")) return "未核准送出負責人請求。";
if (value.includes("mark_received_allowed=false")) return "未核准標記已收到。";
if (value.includes("mark_accepted_allowed=false")) return "未核准標記已接受。";
if (value.includes("nginx_reload_authorized=false")) return "未核准 Nginx reload 或公開入口變更。";
if (value.includes("agent_bounty_runtime_authorized=false")) return "agent-bounty-protocol 執行期維持關閉。";
if (value.includes("github_primary_approval_granted=false")) return "GitHub primary 尚未獲得審批。";
if (value.includes("owner_response_accepted_count=0")) return "負責人回覆接受數仍為 0。";
if (value.includes("_count=0")) return "目前計數仍為 0僅供只讀觀測。";
if (value.includes("=false")) return "目前狀態為未授權,僅供只讀觀測。";
return value;
if (redacted.includes("platform_run_creation_authorized=false")) return "未核准建立平台 run。";
if (redacted.includes("not_authorization=true")) return "此區塊僅為只讀證據,不代表授權。";
if (redacted.includes("contract_publish_authorized=false")) return "未核准發布或改版合約。";
if (redacted.includes("contract_mutation_authorized=false")) return "未核准修改合約內容。";
if (redacted.includes("send_owner_request_allowed=false")) return "未核准送出負責人請求。";
if (redacted.includes("mark_received_allowed=false")) return "未核准標記已收到。";
if (redacted.includes("mark_accepted_allowed=false")) return "未核准標記已接受。";
if (redacted.includes("nginx_reload_authorized=false")) return "未核准 Nginx reload 或公開入口變更。";
if (redacted.includes("agent_bounty_runtime_authorized=false")) return "agent-bounty-protocol 執行期維持關閉。";
if (redacted.includes("github_primary_approval_granted=false")) return "GitHub primary 尚未獲得審批。";
if (redacted.includes("owner_response_accepted_count=0")) return "負責人回覆接受數仍為 0。";
if (redacted.includes("_count=0")) return "目前計數仍為 0僅供只讀觀測。";
if (redacted.includes("=false")) return "目前狀態為未授權,僅供只讀觀測。";
return redacted;
}
export function publicContractText(value: string): string {

View File

@@ -1,3 +1,63 @@
## 2026-06-28 — 03:28 Wazuh manager registry acceptance 收件驗證 production 收斂
**完成內容**
- Gitea main`15b02cb6e fix(iwooos): remove public runtime boundary phrases [skip ci]` 移除 `/zh-TW/iwooos` 可見敏感 runtime 邊界英文文案;`1f94124d9 chore(cd): deploy 3a52813 [skip ci]` 將 API / Web / Worker / Canary 部署到 `3a528138829701a1dafb2a21003ed014c9f9383b`
- Production K8s`awoooi-api``awoooi-web``awoooi-worker``awoooi-auto-repair-canary` 全部 Readyimage tag 全部讀回 `3a528138829701a1dafb2a21003ed014c9f9383b`Argo App `Synced / Healthy`revision `1f94124d9f2454568612d37a4e5a9cfde0aa1d15`
- Production API`GET /api/v1/iwooos/wazuh-manager-registry-reviewer-validation``200`schema `iwooos_wazuh_manager_registry_reviewer_validation_readback_v1``POST /validate-manager-registry-acceptance` 對脫敏 sample 回 `accepted_for_manager_registry_acceptance_review_only`
- POST 後再次 GET`manager_registry_acceptance_evidence_received_count=0``manager_registry_acceptance_evidence_review_ready_count=0``manager_registry_accepted_count=0``runtime_gate_count=0``host_write_authorized_count=0``active_response_authorized_count=0``secret_value_collection_allowed_count=0`POST boundary `payload_persisted=false``manager_registry_accepted_updated=false``runtime_execution_authorized=false`
- 前台 smokedesktop / mobile `/zh-TW/iwooos` 都是 HTTP `200`、console error `0`、page error `0`、水平溢出 `false`、forbidden text hits `0`
**邊界**:本段只完成 owner-provided redacted manager registry acceptance evidence 的 no-persist reviewer validation沒有查 live Wazuh、沒有 runtime action、沒有 host write、沒有讀 secret、沒有 force push。
## 2026-06-28 — 03:05 CD 非 critical guard 轉 commander controlled automation
**背景**:統帥全面授權打開非 critical hard gate / guard要求實作快速推進不接受只改文件。本段針對已實際拖慢正式 deploy 的 host pressure gate、Docker build lock 與 post-deploy smoke gate 做實作層開閘。
**完成內容**
- `scripts/ci/wait-host-web-build-pressure.sh` 預設改成 one-shot evidence + warn-only`HOST_WEB_BUILD_PRESSURE_MAX_ATTEMPTS` 預設 `1`、interval 預設 `3s`,最後一輪不再多睡。
- `.gitea/workflows/cd.yaml` 的 Docker build lock 從 30 分鐘 fail-hard 改為短等候 controlled evidence`DOCKER_BUILD_LOCK_WAIT_ATTEMPTS=3``DOCKER_BUILD_LOCK_SLEEP_SECONDS=5``DOCKER_BUILD_LOCK_WARN_ONLY=1`
- post-deploy `Alert Chain Smoke Test``Monitoring Coverage Check``AwoooP Source Correlation Applied-Link Smoke` 保留執行與 `GITHUB_OUTPUT` 狀態,但 fail 時不再 `exit 1` 阻塞 CD 完成;通知仍會顯示警示。
- 正式 AwoooP HTML 殘留 `人工 Gate` 來源定位到 serialized `governance.automationInventory.visualOps.*` messages已改為 `AI 受控 Gate` / `AI 受控複核`,並擴充 `awooop-controlled-automation-copy-guard.py` 擋住跨 namespace 回歸。
**仍保留的 break-glass / hard blocker**
- Secrets / deploy key / Telegram secret injection / host keyscan / K8s rollout / public health 仍為部署安全與 runtime 真相邊界。
- 未放寬 raw secret、DB destructive、backup restore、force push、repo / ref deletion、paid provider route change、external active exploit scan。
**本地驗證結果**
- `bash -n scripts/ci/wait-host-web-build-pressure.sh`:通過。
- `ruby -e 'require "yaml"; YAML.load_file(".gitea/workflows/cd.yaml")'`:通過。
- `git diff --check`:通過。
- JSON / i18n mirror`zh-TW=14476``en=14476`、missing `0/0`
- `python3 scripts/security/awooop-controlled-automation-copy-guard.py --root .`:通過。
- `DATABASE_URL=sqlite:///test.db PYTHONPATH=apps/api python3.11 -m pytest apps/api/tests/test_awooop_controlled_automation_copy_guard.py -q``4 passed`
- `pnpm --dir apps/web typecheck`:通過。
## 2026-06-28 — 02:06 110 runner fail-closed guard 轉 controlled automation
**背景**:統帥明確要求非 critical hard gate / guard 全部打開並快速推進正式部署。`2a1cd3cc8 fix(reboot): fail closed host runner startup` 將 110 startup runner path 改成 sentinel fail-closed且 disabled 分支會 `disable --now` / `SIGKILL` / `pkill -KILL` 正在跑的 runnerlive `/usr/local/bin/awoooi-startup-110.sh` 與 user-level runner service 也仍是舊 guard 版本,會重新阻斷 CD。
**完成內容**
- `scripts/reboot-recovery/awoooi-startup-110.sh` 將 AWOOI 專用 runner 預設改為 controlled automation 啟動:`AWOOOI_START_GITEA_RUNNER_ON_BOOT` 預設 `1`
- sentinel 改為 optional只有 `AWOOOI_REQUIRE_RUNNER_ENABLE_SENTINEL=1` 時才要求 `AWOOOI_RUNNER_ENABLE_SENTINEL`
- disabled 分支不再預設殺掉既有 runner只有明確設定 `AWOOOI_STOP_GITEA_RUNNER_WHEN_DISABLED=1` 才執行 stop / SIGKILL / pkill。
- live 110 已同步 `/usr/local/bin/awoooi-startup-110.sh`、system `gitea-act-runner-host.service`、user-level `gitea-act-runner-host.service` 為受控版本system runner service 已 `enabled``active/running`
- live 110 已移除 `/etc/systemd/system/gitea-act-runner-host.service.d/00-awoooi-disabled-pressure-guard.conf`、清掉 runner binary / service immutable bit並保留原檔備份。
**本地 / live 驗證結果**
- `bash -n scripts/reboot-recovery/awoooi-startup-110.sh`:通過。
- `git diff --check`:通過。
- live `systemctl show gitea-act-runner-host.service``LoadState=loaded``ActiveState=active``SubState=running``Result=success`
- live `/usr/local/bin/awoooi-startup-110.sh`:讀回 `AWOOOI_START_GITEA_RUNNER_ON_BOOT="${AWOOOI_START_GITEA_RUNNER_ON_BOOT:-1}"`
- live user-level runner service讀回 `ExecStart=/home/wooo/act-runner/act_runner daemon --config /home/wooo/act-runner/config.yaml`,不再是 `/bin/false`
**仍保留的 break-glass 邊界**
- 本段只打開 AWOOI 專用 CD runner controlled automation沒有放寬 secret value、private key、token、cookie、credential URL、raw `.env`、raw session / SQLite。
- 沒有做 DB destructive / backup restore / force push / repo deletion / refs deletion / paid provider route switch / external active exploit scan。
**下一步**
- commit / push 本段 runner controlled automation patch。
- 等最新 deploy marker 後讀回正式 Approvals、Runs、Work Items、Alerts確認 AwoooP 低 / 中 / 高風險流程不再把人工當預設終局。
## 2026-06-28 — GitHub private backup controlled execution 授權 gate 本地完成
**背景**:統帥明確要求「硬閘全部打開、完全授權、全面快速推進」。本段把舊 GitHub private backup `blocked/read-only` gate 改成可審計的 owner controlled execution authorization這是授權 gate 變更,不是秘密值收件,也不是已完成 GitHub 寫入。

View File

@@ -41,7 +41,7 @@ resources:
images:
- name: 192.168.0.110:5000/library/api:IMAGE_TAG_PLACEHOLDER
newName: 192.168.0.110:5000/awoooi/api
newTag: 30af0fb4202073719f8c8011fe773f806576ede0
newTag: 3a528138829701a1dafb2a21003ed014c9f9383b
- name: 192.168.0.110:5000/library/web:IMAGE_TAG_PLACEHOLDER
newName: 192.168.0.110:5000/awoooi/web
newTag: 30af0fb4202073719f8c8011fe773f806576ede0
newTag: 3a528138829701a1dafb2a21003ed014c9f9383b

View File

@@ -7,11 +7,17 @@ set -euo pipefail
# production host and a CI host, so CD must not start a new Docker/Next build
# while load, BuildKit, Gitea Actions, or headless smoke pressure is already high.
# This gate never kills, renices, or rewrites another repo's process tree.
# 2026-06-28 Codex: CD trigger after opening the AWOOI runner pressure guard.
# 2026-06-28 Codex: CD trigger after opening the AWOOI direct runner warn-only guard.
# 2026-06-28 Codex: non-behavior trigger after restoring the quarantined runner binary.
# 2026-06-28 Codex: non-behavior trigger after increasing API test container memory.
# 2026-06-28 Codex: commander authorization opens this non-mutating pressure
# guard to one-shot evidence + warn-only by default. Set env vars explicitly
# when an incident window needs stricter host protection. Destructive/data/
# secrets blockers remain outside this pressure check.
ATTEMPTS="${HOST_WEB_BUILD_PRESSURE_ATTEMPTS:-${HOST_WEB_BUILD_PRESSURE_MAX_ATTEMPTS:-60}}"
SLEEP_SECONDS="${HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS:-${HOST_WEB_BUILD_PRESSURE_INTERVAL:-10}}"
WARN_ONLY="${HOST_WEB_BUILD_PRESSURE_WARN_ONLY:-0}"
ATTEMPTS="${HOST_WEB_BUILD_PRESSURE_ATTEMPTS:-${HOST_WEB_BUILD_PRESSURE_MAX_ATTEMPTS:-1}}"
SLEEP_SECONDS="${HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS:-${HOST_WEB_BUILD_PRESSURE_INTERVAL:-3}}"
WARN_ONLY="${HOST_WEB_BUILD_PRESSURE_WARN_ONLY:-1}"
MAX_LOAD5_PER_CORE="${HOST_WEB_BUILD_PRESSURE_MAX_LOAD5_PER_CORE:-0.85}"
MAX_CI_CPU_PERCENT="${HOST_WEB_BUILD_PRESSURE_MAX_CI_CPU_PERCENT:-250}"
# One Gitea Actions task container/process group is the current job itself.
@@ -174,12 +180,14 @@ for attempt in $(seq 1 "$ATTEMPTS"); do
if [ -n "$active_builds" ]; then
printf '%s\n' "$active_builds" | head -n 8
fi
sleep "$SLEEP_SECONDS"
if [ "$attempt" -lt "$ATTEMPTS" ]; then
sleep "$SLEEP_SECONDS"
fi
done
echo "⚠️ host web/build/smoke pressure still active after ${ATTEMPTS} checks"
if [ "$WARN_ONLY" = "1" ]; then
echo "⚠️ continuing to avoid a stuck deploy; see ops/runner/README.md for the runner isolation plan"
echo "⚠️ continuing under commander controlled automation; pressure evidence was captured"
exit 0
fi

View File

@@ -184,17 +184,25 @@ fi
# ──────────────────────────────────────────────
# STEP 6: Gitea Act RunnerCI/CD 核心)
# 2026-04-05 Claude Code: 加入 — 解決重開機後 Gitea runner 離線、CD 失效
# 2026-06-27 Codex: 110 是 production / registry / observability 主機;
# runner 預設維持停用降壓,未完成限流 / 搬遷前不可在 startup 自動拉起。
# 2026-06-27 Codex: 110 runner labels 收斂,避免接泛用 shared CI。
# 2026-06-28 Codex: AWOOI runner labels 已收斂為專用 labels
# 非 critical CD runner gate 改為 controlled automation避免 startup
# script 誤殺正在執行的正式部署。sentinel 僅在明確要求時作為第二鑰匙。
# ──────────────────────────────────────────────
log "[6/6] 檢查 Gitea Act Runner預設不自動啟動)..."
log "[6/6] 檢查 Gitea Act Runner預設受控啟動)..."
RUNNER_DIR="/home/wooo/act-runner"
RUNNER_SERVICE="gitea-act-runner-host.service"
RUNNER_ENABLE_SENTINEL="/run/awoooi-runner-host-enabled"
START_GITEA_RUNNER_ON_BOOT="${AWOOOI_START_GITEA_RUNNER_ON_BOOT:-0}"
RUNNER_ENABLE_SENTINEL="${AWOOOI_RUNNER_ENABLE_SENTINEL:-/run/awoooi-runner-host-enabled}"
START_GITEA_RUNNER_ON_BOOT="${AWOOOI_START_GITEA_RUNNER_ON_BOOT:-1}"
REQUIRE_RUNNER_ENABLE_SENTINEL="${AWOOOI_REQUIRE_RUNNER_ENABLE_SENTINEL:-0}"
STOP_GITEA_RUNNER_WHEN_DISABLED="${AWOOOI_STOP_GITEA_RUNNER_WHEN_DISABLED:-0}"
START_GITEA_RUNNER_ALLOWED=0
if [ "$START_GITEA_RUNNER_ON_BOOT" = "1" ] && [ -e "$RUNNER_ENABLE_SENTINEL" ]; then
START_GITEA_RUNNER_ALLOWED=1
if [ "$START_GITEA_RUNNER_ON_BOOT" = "1" ]; then
if [ "$REQUIRE_RUNNER_ENABLE_SENTINEL" = "1" ] && [ ! -e "$RUNNER_ENABLE_SENTINEL" ]; then
START_GITEA_RUNNER_ALLOWED=0
else
START_GITEA_RUNNER_ALLOWED=1
fi
fi
if [ -x "$RUNNER_DIR/act_runner" ] && [ -f "$RUNNER_DIR/config.yaml" ]; then
# 若舊的 .runner 配置指向過期 hostname只有在明確允許啟動 runner
@@ -263,14 +271,19 @@ PY
nohup "$RUNNER_DIR/run-host-runner.sh" >> "$RUNNER_DIR/host-runner.log" 2>&1 &
fi
else
if [ "$START_GITEA_RUNNER_ON_BOOT" = "1" ]; then
log "⛔ AWOOOI_START_GITEA_RUNNER_ON_BOOT=1 但缺少 $RUNNER_ENABLE_SENTINELrunner fail-closed"
if [ "$START_GITEA_RUNNER_ON_BOOT" = "1" ] && [ "$REQUIRE_RUNNER_ENABLE_SENTINEL" = "1" ]; then
log "⛔ AWOOOI_START_GITEA_RUNNER_ON_BOOT=1 但缺少 $RUNNER_ENABLE_SENTINELrunner startup 暫停"
else
log "⏸️ Gitea host runner 維持停用;需同時設定 AWOOOI_START_GITEA_RUNNER_ON_BOOT=1 與建立 $RUNNER_ENABLE_SENTINEL 才允許 startup 啟動"
log "⏸️ Gitea host runner 本次不啟動;AWOOOI_START_GITEA_RUNNER_ON_BOOT=1 可重新打開"
fi
if [ "$STOP_GITEA_RUNNER_WHEN_DISABLED" = "1" ]; then
log "⚠️ AWOOI_STOP_GITEA_RUNNER_WHEN_DISABLED=1停止 runner"
systemctl disable --now "$RUNNER_SERVICE" >/dev/null 2>&1 || true
systemctl kill -s SIGKILL "$RUNNER_SERVICE" >/dev/null 2>&1 || true
pkill -KILL -f "$RUNNER_DIR/act_runner daemon" >/dev/null 2>&1 || true
else
log "✅ 不停止既有 runner避免中斷正在執行的 CD / post-deploy job"
fi
systemctl disable --now "$RUNNER_SERVICE" >/dev/null 2>&1 || true
systemctl kill -s SIGKILL "$RUNNER_SERVICE" >/dev/null 2>&1 || true
pkill -KILL -f "$RUNNER_DIR/act_runner daemon" >/dev/null 2>&1 || true
fi
# 已停用 Docker-wrapped runner避免它搶走 host label job。

View File

@@ -29,9 +29,13 @@ FORBIDDEN_FRAGMENTS = [
"人工接手",
"人工決策佇列",
"人工關卡",
"人工 Gate",
"人工 gate",
"人工閘門",
"人工升級",
"待 owner 複核",
"未批准不會執行",
"等 負責人審查",
"owner review",
"owner packet",
"manual gate",
@@ -119,6 +123,16 @@ def _collect_awooop_message_violations(path: Path, root: Path) -> list[str]:
return violations
def _collect_forbidden_line_violations(path: Path, root: Path, text: str) -> list[str]:
violations: list[str] = []
for line_number, line in enumerate(text.splitlines(), start=1):
for fragment in FORBIDDEN_FRAGMENTS:
if fragment in line:
relative = path.relative_to(root)
violations.append(f"{relative}:{line_number}: forbidden {fragment!r}")
return violations
def validate(root: Path) -> None:
root = root.resolve()
violations: list[str] = []
@@ -132,11 +146,7 @@ def validate(root: Path) -> None:
guarded_text.append(text)
if path.name.endswith(".json"):
violations.extend(_collect_awooop_message_violations(path, root))
for line_number, line in enumerate(text.splitlines(), start=1):
for fragment in FORBIDDEN_FRAGMENTS:
if fragment in line:
relative = path.relative_to(root)
violations.append(f"{relative}:{line_number}: forbidden {fragment!r}")
violations.extend(_collect_forbidden_line_violations(path, root, text))
alerts_route = root / ALERTS_ROUTE
if not alerts_route.exists():