Files
awoooi/apps/web/src/lib/public-security-redaction.ts
Your Name 1650408392
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 18s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
fix(awooop): clarify controlled automation boundaries
2026-06-29 18:46:29 +08:00

180 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export function publicBoundaryText(value: string): string {
const redacted = value
.replace(/live Wazuh/gi, "只讀管理端")
.replace(/runtime action/gi, "執行期變更")
.replace(/runtime gate 已開/g, "執行期閘門開啟")
.replace(/執行期已授權/g, "已取得執行期授權")
.replace(/host write/gi, "主機變更")
.replace(/active response/gi, "主動回應流程")
.replace(/raw output/gi, "脫敏輸出摘要")
.replace(/secret value/gi, "機密明文")
.replace(/raw secret/gi, "原始機密");
const labels: Record<string, string> = {
"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[redacted]) return labels[redacted];
if (redacted.includes("runtime_execution_authorized=false")) {
return "低 / 中 / 高風險已走 AI controlled apply此 false 僅標示 critical / break-glass 或外部來源切換未開放。";
}
if (redacted.includes("action_buttons_allowed=false")) {
return "此頁不放直接危險按鈕AI controlled work item 仍由 check-mode、rollback 與 verifier 推進。";
}
if (redacted.includes("active_runtime_gate_count=0")) return "執行期閘門維持關閉。";
if (redacted.includes("owner_response_validation_received_count=0")) {
return "負責人回覆尚未收到;僅作 evidence不阻擋低 / 中 / 高風險 AI controlled apply。";
}
if (redacted.includes("owner_response_validation_accepted_count=0")) {
return "負責人回覆尚未接受;僅作 evidence不作為 controlled automation 終局。";
}
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 (redacted.includes("workflow_modification_authorized=false") || redacted.includes("workflow_secret_modification_authorized=false")) {
return "未核准修改工作流程、runner 或機密設定。";
}
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 "此只讀面板不直連執行路由;可回滾變更由 AI controlled queue 與 verifier 接手。";
}
if (redacted.includes("security_run_created=false") || redacted.includes("github_primary_run_created=false")) {
return "目前沒有建立資安執行 run。";
}
if (redacted.includes("approval_record_created=false") || redacted.includes("security_approval_record_created=false")) {
return "目前沒有建立審批紀錄。";
}
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這是歷史/evidence 欄位,不阻擋 controlled apply。";
}
if (redacted.includes("_count=0")) return "目前計數仍為 0僅供只讀觀測。";
if (redacted.includes("=false")) return "目前狀態為未授權,僅供只讀觀測。";
return redacted;
}
export function publicContractText(value: string): string {
const labels: Record<string, string> = {
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] ?? "已脫敏只讀證據參照";
}
const PUBLIC_PROJECT_NAMES: Record<string, string> = {
"agent-bounty-protocol": "代理獎勵協議",
"awoooi": "核心營運平台",
"awooooi": "核心營運平台",
"bitan": "藥局服務前台",
"bitan-pharmacy": "藥局服務平台",
"clawbot-v5": "自動化助理平台",
"ewoooc": "行動商務平台",
"mo": "行動商務前台",
"open-design": "設計系統",
"source-control": "版本控管範圍",
"tsenyang-website": "品牌網站",
"vibework": "工作協作產品",
"wooo-aiops": "AI 維運平台",
"wooo-infra-config": "基礎設施設定",
};
const PUBLIC_AGENT_NAMES: Record<string, string> = {
"codex": "程式修正代理",
"openclaw": "決策分析代理",
"nemotron": "推理評估代理",
"hermes": "通訊協作代理",
"elephantalph": "資料評估代理",
"elephantalpha": "資料評估代理",
};
const RAW_REPOSITORY_IDENTIFIER_RE = /\b[a-z0-9][a-z0-9-]{1,}\/[A-Za-z0-9._-]+\b/;
const INTERNAL_CODE_RE = /^[a-z][a-z0-9]*(?:[_:.-][a-z0-9]+){1,}$/i;
const CJK_TEXT_RE = /[\u3400-\u9fff]/;
function normalizedIdentifier(value: string | null | undefined): string {
return String(value ?? "").trim().toLowerCase();
}
function hasUnsafePublicIdentifier(value: string): boolean {
const normalized = value.toLowerCase();
return (
RAW_REPOSITORY_IDENTIFIER_RE.test(value) ||
normalized.includes("github.com")
);
}
export function publicProjectText(value: string | null | undefined, fallback = "已脫敏專案"): string {
const raw = String(value ?? "").trim();
if (!raw) return fallback;
const normalized = normalizedIdentifier(raw);
const key = normalized.split("/").pop() ?? normalized;
if (PUBLIC_PROJECT_NAMES[normalized]) return PUBLIC_PROJECT_NAMES[normalized];
if (PUBLIC_PROJECT_NAMES[key]) return PUBLIC_PROJECT_NAMES[key];
if (!hasUnsafePublicIdentifier(raw) && CJK_TEXT_RE.test(raw)) return raw;
return fallback;
}
export function publicAgentText(value: string | null | undefined, fallback = "已脫敏執行代理"): string {
const raw = String(value ?? "").trim();
if (!raw) return fallback;
const normalized = normalizedIdentifier(raw);
const knownKey = Object.keys(PUBLIC_AGENT_NAMES).find((key) => normalized.includes(key));
if (knownKey) return PUBLIC_AGENT_NAMES[knownKey];
if (!hasUnsafePublicIdentifier(raw) && CJK_TEXT_RE.test(raw)) return raw;
return fallback;
}
export function publicInternalCodeSummary(
values: Array<string | null | undefined> | string | null | undefined,
emptyLabel = "無公開阻塞項"
): string {
const items = Array.isArray(values) ? values.filter(Boolean) : [values].filter(Boolean);
if (items.length === 0) return emptyLabel;
const readable = items
.map((item) => String(item ?? "").trim())
.filter((item) => item && !hasUnsafePublicIdentifier(item) && CJK_TEXT_RE.test(item) && !INTERNAL_CODE_RE.test(item));
if (readable.length > 0) return readable.slice(0, 3).join("、");
return `已脫敏狀態 ${items.length}`;
}
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, "已脫敏專案來源");
}