diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json
index aeb46f57..51941fb0 100644
--- a/apps/web/messages/en.json
+++ b/apps/web/messages/en.json
@@ -7212,11 +7212,11 @@
"timelineMissing": "品質總覽仍指出 時間線 / 稽核記錄缺口",
"iwooosSecurityMirror": "整體 {headline};框架 {framework};落地 {runtime};主動執行閘門={gates}",
"iwooosSecurityMirrorOwner": "AwoooP 正式只讀落地 已驗證;負責人回覆仍等待",
- "iwooosSecurityMirrorBoundary": "execution_router_linked=false;runtime_execution_authorized=false;action_buttons_allowed=false",
+ "iwooosSecurityMirrorBoundary": "尚未連接執行路由;執行期操作未授權;此頁不提供可執行操作按鈕。",
"githubPrimaryReadiness": "候選專案庫={candidates};範圍內={inScope};主要來源就緒={ready}",
"githubPrimaryOwnerResponses": "負責人回覆仍為 0/22;請求可送出不等於已接受",
"githubPrimaryWorkflowNames": "工作流程 / 機密名稱清冊完成=0/7;只收名稱不收機密明文值",
- "githubPrimaryBoundary": "repo_creation=false;refs_mutation=false;github_primary_switch=false;disable_gitea=false",
+ "githubPrimaryBoundary": "未核准建立專案庫、同步 refs、切換 GitHub primary 或停用 Gitea。",
"ownerResponseValidation": "回覆包={packets};範本={templates};已收到={received};已接受={accepted};已拒收={rejected}",
"ownerResponseValidationChecks": "跨包驗收={crossPacket};證據路由={routing};顯示區塊={sections}",
"ownerResponseValidationBoundary": "不建立審批紀錄、不切主要來源、不開執行期閘門"
@@ -9312,27 +9312,27 @@
"validationRollup": {
"title": "S4.13 驗收彙整",
"detail": "固定四包、跨包驗收、證據路由、審查清單與結果分流,但不產生審批紀錄。",
- "contract": "來源_control_owner_response_validation_rollup_v1"
+ "contract": "負責人回覆驗收彙整"
},
"giteaAttestation": {
"title": "S4.9 Gitea 清冊負責人證明",
"detail": "5 個範本仍等待負責人回覆;目前只能顯示下一個收件焦點。",
- "contract": "gitea_inventory_owner_attestation_response_v1"
+ "contract": "Gitea 清冊負責人證明"
},
"githubTarget": {
"title": "S4.10 GitHub 目標負責人決策",
"detail": "9 個目標負責人 / 可見性 / 標準回覆仍未接受,不得自動建立專案庫。",
- "contract": "github_target_owner_decision_response_v1"
+ "contract": "GitHub 目標負責人決策"
},
"refsTruth": {
"title": "S4.11 分支 / 標籤真相負責人回覆",
"detail": "5 類真相判定仍等待脫敏回覆,不得同步、刪除或強制推送分支 / 標籤參照。",
- "contract": "來源_control_ref_truth_owner_response_v1"
+ "contract": "分支 / 標籤真相負責人回覆"
},
"workflowSecret": {
"title": "S4.12 工作流程 / 機密名稱負責人回覆",
"detail": "5 類名稱與脫敏證據仍等待回覆;只允許名稱清冊,不允許機密明文值。",
- "contract": "來源_control_workflow_secret_name_owner_response_v1"
+ "contract": "工作流程 / 機密名稱負責人回覆"
}
}
}
@@ -11497,7 +11497,7 @@
"stageCompletionReport": {
"title": "階段完成回報",
"subtitle": "每一輪完成後都把正式證據、進度邊界與下一步固定在首頁,讓管理與維運角色可直接理解目前資安工作狀態。",
- "boundary": "本階段只更新可見回報與證據索引:headline_percent=64;framework=92%;runtime_landing=40-45%;active_執行期_閘門_count=0;runtime_execution_authorized=false;repo_creation_authorized=false。",
+ "boundary": "本階段只更新可見回報與證據索引:整體 64%;框架 92%;runtime landing 40-45%;執行期閘門維持 0;不授權 runtime 或專案庫變更。",
"items": {
"stageClosed": {
"title": "本階段已收斂",
@@ -11522,7 +11522,7 @@
"subtitle": "將 64% 往下一階段推進需要的工作拆成四件事;此區僅顯示任務與完成條件,不送出請求、不啟動掃描、不建立執行。",
"stepLabel": "任務",
"doneLabel": "完成條件",
- "boundary": "固定邊界:負責人_response_已收到_count=0;負責人_response_已接受_count=0;active_執行期_閘門_count=0;runtime_execution_authorized=false;action_buttons_allowed=false;repo_creation_authorized=false;github_primary_switch_authorized=false。",
+ "boundary": "固定邊界:負責人回覆尚未收到或接受;執行期閘門維持 0;不提供操作按鈕;不建立專案庫;不切 GitHub primary。",
"items": {
"s49OwnerResponse": {
"title": "先收 S4.9 負責人回覆",
@@ -13446,13 +13446,13 @@
"awooopProductionLandingProof": {
"title": "AwoooP 正式只讀消費證據",
"body": "AwoooP 主線已在正式站只讀消費 IwoooS / security 鏡像的 重點、證據參照、守門 result與forbidden action。",
- "acceptance": "已有 Gitea main commit、CD 成功與正式站路由驗證;execution_router_linked=false、runtime_execution_authorized=false。",
+ "acceptance": "已有 Gitea main commit、CD 成功與正式站路由驗證;執行路由與 runtime 授權仍維持關閉。",
"guard": "只讀落地不是 批准、操作按鈕、執行路由或阻擋控制。"
},
"kali112ReadOnlyProof": {
"title": "Kali host:kali-readonly 今日只讀證據",
"body": "2026-06-04 08:55 已完成 Kali host:kali-readonly SSH只讀快照、掃描ner 8080 /health、待更新套件 1994、networking.service與服務硬化 0/4的正式站可見證據。",
- "acceptance": "已有 Gitea CD run 3623、正式站 desktop / mobile 驗證與維護闖關路徑;runtime_execution_authorized=false。",
+ "acceptance": "已有 Gitea CD run 3623、正式站 desktop / mobile 驗證與維護闖關路徑;runtime 授權仍維持關閉。",
"guard": "只讀證據不是 主動掃描、/execute、SSH 變更、更新、重啟或服務硬化授權。"
},
"nextHeadlineReviewRecord": {
@@ -14946,7 +14946,7 @@
"title": "鏡像路由群組已知",
"body": "`security_鏡像_route_v1` 已定義操作控制台、執行期 state、channel event、audit 證據、批准 佇列的只讀目的地。",
"requirement": "AwoooP只能依 route group 顯示與分類,不新增掃描、執行、修復、專案庫、參照或部署動作。",
- "guard": "action_buttons_allowed=false;runtime_execution_authorized=false"
+ "guard": "不提供操作按鈕;runtime 授權仍維持關閉。"
},
"forbiddenOutputsLocked": {
"title": "禁止輸出已鎖住",
@@ -16794,7 +16794,7 @@
"detail": "目前 IwoooS 是低摩擦框架與只讀證據網;掃描、修復、部署、主機更新與版本來源變更都要獨立人工閘門。",
"evidence": "守門、快照、LOGBOOK 與邊界鍵都已鎖住。",
"next": "等 負責人證據或人工決策後,再另開 follow-up 執行期閘門。",
- "locked": "runtime_execution_authorized=false;active_runtime_gate_count=0。"
+ "locked": "runtime 授權仍維持關閉;執行期閘門維持 0。"
}
}
},
@@ -17598,7 +17598,7 @@
"title": "執行期 禁止動作",
"body": "Kali /execute、SSH、主機更新、主動掃描、憑證掃描、阻擋控制、專案庫 / 參照 / 工作流程 動作仍未授權。",
"handoff": "平行工作線只能新增只讀證據、介面投影、文件、快照與守門結果。",
- "guard": "runtime_execution_authorized=false;action_buttons_allowed=false"
+ "guard": "runtime 授權仍維持關閉;不提供操作按鈕。"
},
"awooopReadOnlyInputs": {
"title": "AwoooP只讀輸入",
diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json
index aeb46f57..51941fb0 100644
--- a/apps/web/messages/zh-TW.json
+++ b/apps/web/messages/zh-TW.json
@@ -7212,11 +7212,11 @@
"timelineMissing": "品質總覽仍指出 時間線 / 稽核記錄缺口",
"iwooosSecurityMirror": "整體 {headline};框架 {framework};落地 {runtime};主動執行閘門={gates}",
"iwooosSecurityMirrorOwner": "AwoooP 正式只讀落地 已驗證;負責人回覆仍等待",
- "iwooosSecurityMirrorBoundary": "execution_router_linked=false;runtime_execution_authorized=false;action_buttons_allowed=false",
+ "iwooosSecurityMirrorBoundary": "尚未連接執行路由;執行期操作未授權;此頁不提供可執行操作按鈕。",
"githubPrimaryReadiness": "候選專案庫={candidates};範圍內={inScope};主要來源就緒={ready}",
"githubPrimaryOwnerResponses": "負責人回覆仍為 0/22;請求可送出不等於已接受",
"githubPrimaryWorkflowNames": "工作流程 / 機密名稱清冊完成=0/7;只收名稱不收機密明文值",
- "githubPrimaryBoundary": "repo_creation=false;refs_mutation=false;github_primary_switch=false;disable_gitea=false",
+ "githubPrimaryBoundary": "未核准建立專案庫、同步 refs、切換 GitHub primary 或停用 Gitea。",
"ownerResponseValidation": "回覆包={packets};範本={templates};已收到={received};已接受={accepted};已拒收={rejected}",
"ownerResponseValidationChecks": "跨包驗收={crossPacket};證據路由={routing};顯示區塊={sections}",
"ownerResponseValidationBoundary": "不建立審批紀錄、不切主要來源、不開執行期閘門"
@@ -9312,27 +9312,27 @@
"validationRollup": {
"title": "S4.13 驗收彙整",
"detail": "固定四包、跨包驗收、證據路由、審查清單與結果分流,但不產生審批紀錄。",
- "contract": "來源_control_owner_response_validation_rollup_v1"
+ "contract": "負責人回覆驗收彙整"
},
"giteaAttestation": {
"title": "S4.9 Gitea 清冊負責人證明",
"detail": "5 個範本仍等待負責人回覆;目前只能顯示下一個收件焦點。",
- "contract": "gitea_inventory_owner_attestation_response_v1"
+ "contract": "Gitea 清冊負責人證明"
},
"githubTarget": {
"title": "S4.10 GitHub 目標負責人決策",
"detail": "9 個目標負責人 / 可見性 / 標準回覆仍未接受,不得自動建立專案庫。",
- "contract": "github_target_owner_decision_response_v1"
+ "contract": "GitHub 目標負責人決策"
},
"refsTruth": {
"title": "S4.11 分支 / 標籤真相負責人回覆",
"detail": "5 類真相判定仍等待脫敏回覆,不得同步、刪除或強制推送分支 / 標籤參照。",
- "contract": "來源_control_ref_truth_owner_response_v1"
+ "contract": "分支 / 標籤真相負責人回覆"
},
"workflowSecret": {
"title": "S4.12 工作流程 / 機密名稱負責人回覆",
"detail": "5 類名稱與脫敏證據仍等待回覆;只允許名稱清冊,不允許機密明文值。",
- "contract": "來源_control_workflow_secret_name_owner_response_v1"
+ "contract": "工作流程 / 機密名稱負責人回覆"
}
}
}
@@ -11497,7 +11497,7 @@
"stageCompletionReport": {
"title": "階段完成回報",
"subtitle": "每一輪完成後都把正式證據、進度邊界與下一步固定在首頁,讓管理與維運角色可直接理解目前資安工作狀態。",
- "boundary": "本階段只更新可見回報與證據索引:headline_percent=64;framework=92%;runtime_landing=40-45%;active_執行期_閘門_count=0;runtime_execution_authorized=false;repo_creation_authorized=false。",
+ "boundary": "本階段只更新可見回報與證據索引:整體 64%;框架 92%;runtime landing 40-45%;執行期閘門維持 0;不授權 runtime 或專案庫變更。",
"items": {
"stageClosed": {
"title": "本階段已收斂",
@@ -11522,7 +11522,7 @@
"subtitle": "將 64% 往下一階段推進需要的工作拆成四件事;此區僅顯示任務與完成條件,不送出請求、不啟動掃描、不建立執行。",
"stepLabel": "任務",
"doneLabel": "完成條件",
- "boundary": "固定邊界:負責人_response_已收到_count=0;負責人_response_已接受_count=0;active_執行期_閘門_count=0;runtime_execution_authorized=false;action_buttons_allowed=false;repo_creation_authorized=false;github_primary_switch_authorized=false。",
+ "boundary": "固定邊界:負責人回覆尚未收到或接受;執行期閘門維持 0;不提供操作按鈕;不建立專案庫;不切 GitHub primary。",
"items": {
"s49OwnerResponse": {
"title": "先收 S4.9 負責人回覆",
@@ -13446,13 +13446,13 @@
"awooopProductionLandingProof": {
"title": "AwoooP 正式只讀消費證據",
"body": "AwoooP 主線已在正式站只讀消費 IwoooS / security 鏡像的 重點、證據參照、守門 result與forbidden action。",
- "acceptance": "已有 Gitea main commit、CD 成功與正式站路由驗證;execution_router_linked=false、runtime_execution_authorized=false。",
+ "acceptance": "已有 Gitea main commit、CD 成功與正式站路由驗證;執行路由與 runtime 授權仍維持關閉。",
"guard": "只讀落地不是 批准、操作按鈕、執行路由或阻擋控制。"
},
"kali112ReadOnlyProof": {
"title": "Kali host:kali-readonly 今日只讀證據",
"body": "2026-06-04 08:55 已完成 Kali host:kali-readonly SSH只讀快照、掃描ner 8080 /health、待更新套件 1994、networking.service與服務硬化 0/4的正式站可見證據。",
- "acceptance": "已有 Gitea CD run 3623、正式站 desktop / mobile 驗證與維護闖關路徑;runtime_execution_authorized=false。",
+ "acceptance": "已有 Gitea CD run 3623、正式站 desktop / mobile 驗證與維護闖關路徑;runtime 授權仍維持關閉。",
"guard": "只讀證據不是 主動掃描、/execute、SSH 變更、更新、重啟或服務硬化授權。"
},
"nextHeadlineReviewRecord": {
@@ -14946,7 +14946,7 @@
"title": "鏡像路由群組已知",
"body": "`security_鏡像_route_v1` 已定義操作控制台、執行期 state、channel event、audit 證據、批准 佇列的只讀目的地。",
"requirement": "AwoooP只能依 route group 顯示與分類,不新增掃描、執行、修復、專案庫、參照或部署動作。",
- "guard": "action_buttons_allowed=false;runtime_execution_authorized=false"
+ "guard": "不提供操作按鈕;runtime 授權仍維持關閉。"
},
"forbiddenOutputsLocked": {
"title": "禁止輸出已鎖住",
@@ -16794,7 +16794,7 @@
"detail": "目前 IwoooS 是低摩擦框架與只讀證據網;掃描、修復、部署、主機更新與版本來源變更都要獨立人工閘門。",
"evidence": "守門、快照、LOGBOOK 與邊界鍵都已鎖住。",
"next": "等 負責人證據或人工決策後,再另開 follow-up 執行期閘門。",
- "locked": "runtime_execution_authorized=false;active_runtime_gate_count=0。"
+ "locked": "runtime 授權仍維持關閉;執行期閘門維持 0。"
}
}
},
@@ -17598,7 +17598,7 @@
"title": "執行期 禁止動作",
"body": "Kali /execute、SSH、主機更新、主動掃描、憑證掃描、阻擋控制、專案庫 / 參照 / 工作流程 動作仍未授權。",
"handoff": "平行工作線只能新增只讀證據、介面投影、文件、快照與守門結果。",
- "guard": "runtime_execution_authorized=false;action_buttons_allowed=false"
+ "guard": "runtime 授權仍維持關閉;不提供操作按鈕。"
},
"awooopReadOnlyInputs": {
"title": "AwoooP只讀輸入",
diff --git a/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx b/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx
index ba3827c0..750354eb 100644
--- a/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx
@@ -28,6 +28,7 @@ import {
type AwoooPStatusChain,
} from "@/components/awooop/status-chain";
import { cn } from "@/lib/utils";
+import { publicBoundaryText, publicContractText } from "@/lib/public-security-redaction";
interface RunDetail {
run_id: string;
@@ -315,7 +316,7 @@ function OwnerResponseValidationDecisionBoundaryPanel() {
{t(`decisionRefs.${item.key}.detail` as never)}
- {item.contract}
+ {publicContractText(item.contract)}
))}
@@ -332,7 +333,7 @@ function OwnerResponseValidationDecisionBoundaryPanel() {
{ownerResponseValidationDecisionBoundaries.map((item) => (
- {item}
+ {publicBoundaryText(item)}
))}
diff --git a/apps/web/src/app/[locale]/awooop/approvals/page.tsx b/apps/web/src/app/[locale]/awooop/approvals/page.tsx
index 881e5611..a453a354 100644
--- a/apps/web/src/app/[locale]/awooop/approvals/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/approvals/page.tsx
@@ -30,6 +30,7 @@ import {
type AwoooPStatusChain,
} from "@/components/awooop/status-chain";
import type { IncidentTimelineResponse } from "@/lib/api-client";
+import { publicBoundaryText, publicContractText } from "@/lib/public-security-redaction";
// =============================================================================
// Types
@@ -679,11 +680,11 @@ function SecurityOwnerResponseGatePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
approval_record_created=false
-
owner_response_accepted_count=0
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("approval_record_created=false")}
+ {publicBoundaryText("owner_response_accepted_count=0")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
approval_record_created=false
-
github_primary_approval_granted=false
-
owner_response_accepted_count=0
-
repo_creation_authorized=false
-
refs_mutation_authorized=false
-
secret_value_collection_allowed=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("approval_record_created=false")}
+ {publicBoundaryText("github_primary_approval_granted=false")}
+ {publicBoundaryText("owner_response_accepted_count=0")}
+ {publicBoundaryText("repo_creation_authorized=false")}
+ {publicBoundaryText("refs_mutation_authorized=false")}
+ {publicBoundaryText("secret_value_collection_allowed=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{t(`reviewRefs.${item.key}.detail`)}
-
- {item.contract}
+
+ {publicContractText(item.contract)}
@@ -918,18 +919,18 @@ function OwnerResponseValidationApprovalBoundaryPanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
owner_response_validation_received_count=0
-
owner_response_validation_accepted_count=0
-
owner_response_validation_rejected_count=0
-
approval_record_created=false
-
repo_creation_authorized=false
-
refs_sync_authorized=false
-
workflow_modification_authorized=false
-
secret_value_collection_allowed=false
-
github_primary_switch_authorized=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("owner_response_validation_received_count=0")}
+ {publicBoundaryText("owner_response_validation_accepted_count=0")}
+ {publicBoundaryText("owner_response_validation_rejected_count=0")}
+ {publicBoundaryText("approval_record_created=false")}
+ {publicBoundaryText("repo_creation_authorized=false")}
+ {publicBoundaryText("refs_sync_authorized=false")}
+ {publicBoundaryText("workflow_modification_authorized=false")}
+ {publicBoundaryText("secret_value_collection_allowed=false")}
+ {publicBoundaryText("github_primary_switch_authorized=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{contracts.map((item) => (
-
{item.name}
+
{publicContractText(item.name)}
{item.detail}
))}
@@ -229,11 +230,11 @@ function SecurityContractCandidatePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
contract_publish_authorized=false
-
contract_mutation_authorized=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("contract_publish_authorized=false")}
+ {publicBoundaryText("contract_mutation_authorized=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{contracts.map((item) => (
-
{item.name}
+
{publicContractText(item.name)}
{item.detail}
))}
@@ -344,14 +345,14 @@ function GitHubPrimaryReadinessContractCandidatePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
repo_creation_authorized=false
-
refs_mutation_authorized=false
-
secret_value_collection_allowed=false
-
github_primary_switch_authorized=false
-
gitea_disablement_authorized=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("repo_creation_authorized=false")}
+ {publicBoundaryText("refs_mutation_authorized=false")}
+ {publicBoundaryText("secret_value_collection_allowed=false")}
+ {publicBoundaryText("github_primary_switch_authorized=false")}
+ {publicBoundaryText("gitea_disablement_authorized=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{contracts.map((item) => (
-
{item.name}
+
{publicContractText(item.name)}
{item.detail}
))}
@@ -462,17 +463,17 @@ function OwnerResponseValidationContractCandidatePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
owner_response_validation_received_count=0
-
owner_response_validation_accepted_count=0
-
approval_record_created=false
-
repo_creation_authorized=false
-
refs_sync_authorized=false
-
workflow_modification_authorized=false
-
secret_value_collection_allowed=false
-
github_primary_switch_authorized=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("owner_response_validation_received_count=0")}
+ {publicBoundaryText("owner_response_validation_accepted_count=0")}
+ {publicBoundaryText("approval_record_created=false")}
+ {publicBoundaryText("repo_creation_authorized=false")}
+ {publicBoundaryText("refs_sync_authorized=false")}
+ {publicBoundaryText("workflow_modification_authorized=false")}
+ {publicBoundaryText("secret_value_collection_allowed=false")}
+ {publicBoundaryText("github_primary_switch_authorized=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
read_only_production_landing_evidence_count=1
-
execution_router_linked=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("read_only_production_landing_evidence_count=1")}
+ {publicBoundaryText("execution_router_linked=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
@@ -990,8 +991,8 @@ function GitHubPrimaryReadinessHomePanel() {
{githubPrimaryReadinessRefs.map((ref) => (
-
- {ref.contract}
+
+ {publicContractText(ref.contract)}
{t(`readinessRefs.${ref.key}` as never)}
@@ -1018,9 +1019,9 @@ function GitHubPrimaryReadinessHomePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
+
{githubPrimaryReadinessBoundaries.map((boundary) => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
@@ -1160,9 +1161,9 @@ function OwnerResponseValidationRollupPanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
+
{ownerResponseValidationBoundaries.map((boundary) => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
@@ -1244,8 +1245,8 @@ function HighValueConfigOwnerPacketHomePanel() {
{highValueConfigOwnerPacketRefs.map((ref) => (
-
- {ref.contract}
+
+ {publicContractText(ref.contract)}
{t(`refs.${ref.key}` as never)}
@@ -1275,9 +1276,9 @@ function HighValueConfigOwnerPacketHomePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
+
{highValueConfigOwnerPacketBoundaries.map((boundary) => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
diff --git a/apps/web/src/app/[locale]/awooop/runs/[run_id]/page.tsx b/apps/web/src/app/[locale]/awooop/runs/[run_id]/page.tsx
index b3e48276..2146c019 100644
--- a/apps/web/src/app/[locale]/awooop/runs/[run_id]/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/runs/[run_id]/page.tsx
@@ -36,6 +36,7 @@ import {
type AwoooPStatusChain,
} from "@/components/awooop/status-chain";
import { cn } from "@/lib/utils";
+import { publicBoundaryText, publicContractText } from "@/lib/public-security-redaction";
interface RunDetail {
run_id: string;
@@ -583,7 +584,7 @@ function OwnerResponseValidationDetailBoundaryPanel() {
{t(`detailRefs.${item.key}.detail` as never)}
-
{item.contract}
+
{publicContractText(item.contract)}
))}
@@ -600,7 +601,7 @@ function OwnerResponseValidationDetailBoundaryPanel() {
{ownerResponseValidationDetailBoundaries.map((item) => (
- {item}
+ {publicBoundaryText(item)}
))}
diff --git a/apps/web/src/app/[locale]/awooop/runs/page.tsx b/apps/web/src/app/[locale]/awooop/runs/page.tsx
index 3405d299..ef6c0789 100644
--- a/apps/web/src/app/[locale]/awooop/runs/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/runs/page.tsx
@@ -35,6 +35,7 @@ import {
TriangleAlert,
} from "lucide-react";
import { cn } from "@/lib/utils";
+import { publicBoundaryText, publicContractText } from "@/lib/public-security-redaction";
// =============================================================================
// Types
@@ -1177,7 +1178,7 @@ function SecurityRunStateCandidatePanel() {
{runRefs.map((item) => (
-
{item.name}
+
{publicContractText(item.name)}
{item.detail}
))}
@@ -1188,11 +1189,11 @@ function SecurityRunStateCandidatePanel() {
{t("boundaryLabel")}
{t("boundaryTitle")}
{t("boundaryDetail")}
-
-
security_run_created=false
-
execution_router_linked=false
-
runtime_execution_authorized=false
-
action_buttons_allowed=false
+
+ {publicBoundaryText("security_run_created=false")}
+ {publicBoundaryText("execution_router_linked=false")}
+ {publicBoundaryText("runtime_execution_authorized=false")}
+ {publicBoundaryText("action_buttons_allowed=false")}
- {ref.name}
+ {publicContractText(ref.name)}
{t(`runRefs.${ref.key}` as never)}
@@ -1302,9 +1303,9 @@ function GitHubRunReadinessBoundaryPanel() {
{t("boundaryDetail")}
-
+
{githubRunReadinessBoundaries.map((boundary) => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
@@ -1398,8 +1399,8 @@ function OwnerResponseValidationRunBoundaryPanel() {
{t(`runRefs.${item.key}.detail` as never)}
-
- {item.contract}
+
+ {publicContractText(item.contract)}
@@ -1416,9 +1417,9 @@ function OwnerResponseValidationRunBoundaryPanel() {
{t("boundaryDetail")}
-
+
{ownerResponseValidationRunBoundaries.map((boundary) => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
diff --git a/apps/web/src/app/[locale]/code-review/page.tsx b/apps/web/src/app/[locale]/code-review/page.tsx
index 369efbb0..f939932b 100644
--- a/apps/web/src/app/[locale]/code-review/page.tsx
+++ b/apps/web/src/app/[locale]/code-review/page.tsx
@@ -2,6 +2,7 @@
import { AppLayout } from '@/components/layout'
import { IwoooSReadOnlyBridge } from '@/components/security/iwooos-read-only-bridge'
+import { publicBoundaryText } from '@/lib/public-security-redaction'
import {
Activity,
ArrowRight,
@@ -133,7 +134,7 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
{handoffFlags.map((flag) => (
- {flag}
+ {publicBoundaryText(flag)}
))}
@@ -176,7 +177,7 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
{t('candidateQueue.subtitle')}
- action_buttons_allowed=false
+ {publicBoundaryText('action_buttons_allowed=false')}
diff --git a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
index ca55a354..86afc8f3 100644
--- a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
+++ b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
@@ -37,6 +37,7 @@ import { useTranslations } from 'next-intl'
import { GlassCard } from '@/components/ui/glass-card'
import { StatusOrb } from '@/components/ui/status-orb'
import { AgentActivityConstellation } from '@/components/governance/agent-activity-constellation'
+import { redactPublicIdentifier } from '@/lib/public-security-redaction'
import {
apiClient,
type AiAgent12AgentWarRoomSnapshot,
@@ -13725,16 +13726,16 @@ export function AutomationInventoryTab() {
- {runner.display_name}
+ {redactPublicIdentifier(runner.display_name)}
- {runner.health_contract}
+ {redactPublicIdentifier(runner.health_contract)}
-
-
+
+
))}
diff --git a/apps/web/src/app/[locale]/security-compliance/page.tsx b/apps/web/src/app/[locale]/security-compliance/page.tsx
index 86f30ffe..308429ab 100644
--- a/apps/web/src/app/[locale]/security-compliance/page.tsx
+++ b/apps/web/src/app/[locale]/security-compliance/page.tsx
@@ -23,6 +23,7 @@ import { AppLayout } from "@/components/layout";
import { PageTabs, type TabConfig } from "@/components/layout/page-tabs";
import { SecurityPanel } from "@/components/panels/SecurityPanel";
import { CompliancePanel } from "@/components/panels/CompliancePanel";
+import { publicBoundaryText } from "@/lib/public-security-redaction";
const integrationItems = [
{ key: "routePreserved", value: "保留", icon: ShieldCheck, color: "#1f7a4d" },
@@ -627,7 +628,7 @@ function SecurityComplianceFrontStage({ locale: _locale }: { locale: string }) {
}}
>
{rolloutBoundaries.map((boundary) => (
-
- {boundary}
-
+ {publicBoundaryText(boundary)}
+
))}
@@ -709,7 +710,7 @@ function SecurityComplianceFrontStage({ locale: _locale }: { locale: string }) {
{integrationBoundaries.map((boundary) => (
-
- {boundary}
-
+ {publicBoundaryText(boundary)}
+
))}
diff --git a/apps/web/src/components/security/iwooos-read-only-bridge.tsx b/apps/web/src/components/security/iwooos-read-only-bridge.tsx
index 43e27181..e9b51368 100644
--- a/apps/web/src/components/security/iwooos-read-only-bridge.tsx
+++ b/apps/web/src/components/security/iwooos-read-only-bridge.tsx
@@ -8,6 +8,7 @@
import Link from 'next/link'
import { ArrowRight, ShieldCheck } from 'lucide-react'
import { useTranslations } from 'next-intl'
+import { publicBoundaryText } from '@/lib/public-security-redaction'
const metrics = [
{ key: 'overall', value: '64%' },
@@ -197,7 +198,7 @@ export function IwoooSReadOnlyBridge({ variant = 'light' }: IwoooSReadOnlyBridge
{boundaries.map(boundary => (
- {boundary}
+ {publicBoundaryText(boundary)}
))}
diff --git a/apps/web/src/lib/public-security-redaction.ts b/apps/web/src/lib/public-security-redaction.ts
new file mode 100644
index 00000000..f990d0c2
--- /dev/null
+++ b/apps/web/src/lib/public-security-redaction.ts
@@ -0,0 +1,81 @@
+export function publicBoundaryText(value: string): string {
+ const labels: Record = {
+ "security_compliance_route_preserved=true": "安全合規路由已保留,並整合到 IwoooS 權威入口。",
+ "security_compliance_removed=false": "安全合規頁沒有被移除,但不再作為孤立入口。",
+ "security_compliance_integration_mode=iwooos_frontstage_bridge": "前台整合模式為 IwoooS 安全合規橋接。",
+ "security_compliance_authoritative_entry=iwooos": "IwoooS 是目前安全治理的權威入口。",
+ "security_compliance_frontstage_summary_mode=compact_first": "前台採摘要優先,細節預設收合。",
+ "security_compliance_frontstage_default_detail_collapsed=true": "詳細證據預設收合,避免首屏過載。",
+ "security_compliance_frontstage_route_role_count=5": "前台路由角色已收斂為 5 類。",
+ "security_compliance_frontstage_primary_source=iwooos": "前台主要來源固定為 IwoooS。",
+ "security_compliance_frontstage_execution_entry_count=0": "前台沒有任何執行入口。",
+ "security_compliance_frontstage_links_read_only=true": "前台連結僅供只讀導覽。",
+ "iwooos_authoritative_security_entry=true": "IwoooS 已作為安全治理權威入口。",
+ "security_compliance_rollout_phase_count=5": "Rollout 維持 5 階段治理節奏。",
+ "security_compliance_rollout_current_phase=observe_first": "目前階段為先觀測、後收斂。",
+ "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")) {
+ return "未核准同步、刪除或強制推送分支 / 標籤。";
+ }
+ if (value.includes("workflow_modification_authorized=false") || value.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")) {
+ return "目前沒有建立資安執行 run。";
+ }
+ if (value.includes("approval_record_created=false") || value.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;
+}
+
+export function publicContractText(value: string): string {
+ const labels: Record = {
+ source_control_primary_readiness_gate_v1: "主要來源就緒度 Gate",
+ source_control_owner_response_validation_rollup_v1: "負責人回覆驗收彙整",
+ source_control_primary_rollback_adr_v1: "主要來源 rollback 決策紀錄",
+ source_control_workflow_secret_name_inventory_v1: "工作流程與機密名稱清冊",
+ gitea_inventory_owner_attestation_response_v1: "Gitea 清冊負責人證明",
+ github_target_owner_decision_response_v1: "GitHub 目標負責人決策",
+ source_control_ref_truth_owner_response_v1: "分支 / 標籤真相負責人回覆",
+ source_control_workflow_secret_name_owner_response_v1: "工作流程 / 機密名稱負責人回覆",
+ security_mirror_status_rollup_v1: "資安鏡像狀態彙整",
+ iwooos_posture_projection_v1: "IwoooS 態勢投影",
+ security_rollout_policy_v1: "資安 rollout 政策",
+ high_value_config_owner_packet_v1: "高價值配置負責人封包",
+ high_value_config_change_gate_v1: "高價值配置變更 Gate",
+ };
+ return labels[value] ?? "已脫敏只讀證據參照";
+}
+
+export function redactPublicIdentifier(value: string): string {
+ if (value.includes("actions.runner.")) return "已脫敏 runner systemd 服務";
+ return value.replace(/\b[a-z0-9][a-z0-9-]{2,}\/[A-Za-z0-9._-]+\b/g, "已脫敏專案來源");
+}