158 lines
9.2 KiB
TypeScript
158 lines
9.2 KiB
TypeScript
export function publicBoundaryText(value: string): string {
|
||
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[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<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, "已脫敏專案來源");
|
||
}
|