From 3edd723faf4562dd64dad3c85249be73d58705d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 16:27:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=90=20=E4=BF=AE=E5=A4=8DSFP=20nonce?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=81=8F=E5=B7=AE=20+=20=E6=8F=90=E5=8F=96ma?= =?UTF-8?q?gic=20numbers=E4=B8=BA=E5=91=BD=E5=90=8D=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/workflows/zhuyuan-commander.yml | 4 +- data/security/sfp-nonce-registry.json | 144 ++++++++++++++++++++++++ scripts/sfp-core.js | 19 ++-- scripts/skyeye/scan-soldier-health.js | 11 +- tests/contract/sfp-core.test.js | 4 +- 5 files changed, 163 insertions(+), 19 deletions(-) diff --git a/.github/workflows/zhuyuan-commander.yml b/.github/workflows/zhuyuan-commander.yml index 39fd50b0..1bf8a74e 100644 --- a/.github/workflows/zhuyuan-commander.yml +++ b/.github/workflows/zhuyuan-commander.yml @@ -2,8 +2,8 @@ name: "🎖️ 铸渊·将军唤醒 · Commander Wake-up" on: schedule: - - cron: '0 0 * * *' # UTC 00:00 = 北京 08:00 - - cron: '0 12 * * *' # UTC 12:00 = 北京 20:00 + - cron: '0 0 * * *' # UTC 00:00 = 北京 08:00(将军早班唤醒) + - cron: '0 12 * * *' # UTC 12:00 = 北京 20:00(将军晚班唤醒) workflow_dispatch: permissions: diff --git a/data/security/sfp-nonce-registry.json b/data/security/sfp-nonce-registry.json index 255deaf3..28f033f9 100644 --- a/data/security/sfp-nonce-registry.json +++ b/data/security/sfp-nonce-registry.json @@ -157,6 +157,150 @@ "agent_id": "AG-TY", "timestamp": "2026-03-19T00:22:24+08:00", "content_hash": "7f4b1a99e8fc" + }, + { + "nonce": "olnmim", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "05a17114410b" + }, + { + "nonce": "r42f7r", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "d6cd1c87b887" + }, + { + "nonce": "2pi1t3", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "0a5df5415ade" + }, + { + "nonce": "sswkv7", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "c3b54c6c243e" + }, + { + "nonce": "pu7e0o", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "c3b54c6c243e" + }, + { + "nonce": "cbz6t0", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "b95bfcf4a347" + }, + { + "nonce": "g5dfi3", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "10c4ec3aeafb" + }, + { + "nonce": "cxu97j", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "902e455fe109" + }, + { + "nonce": "w2dw4b", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "929460febd09" + }, + { + "nonce": "aqyuid", + "agent_id": "AG-SY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "f85462954167" + }, + { + "nonce": "oycw4f", + "agent_id": "AG-QQ", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "c10beff06c0b" + }, + { + "nonce": "69xg61", + "agent_id": "AG-TY", + "timestamp": "2026-03-19T00:23:59+08:00", + "content_hash": "7f4b1a99e8fc" + }, + { + "nonce": "3783f4", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "05a17114410b" + }, + { + "nonce": "153ac0", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "d6cd1c87b887" + }, + { + "nonce": "b1b39e", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "0a5df5415ade" + }, + { + "nonce": "32af7a", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "c3b54c6c243e" + }, + { + "nonce": "bda41d", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "c3b54c6c243e" + }, + { + "nonce": "2c6a56", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "b95bfcf4a347" + }, + { + "nonce": "250ec9", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "10c4ec3aeafb" + }, + { + "nonce": "eb8195", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "902e455fe109" + }, + { + "nonce": "d20686", + "agent_id": "AG-ZY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "929460febd09" + }, + { + "nonce": "18fa39", + "agent_id": "AG-SY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "f85462954167" + }, + { + "nonce": "8d0d13", + "agent_id": "AG-QQ", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "c10beff06c0b" + }, + { + "nonce": "7de110", + "agent_id": "AG-TY", + "timestamp": "2026-03-19T00:25:55+08:00", + "content_hash": "7f4b1a99e8fc" } ] } \ No newline at end of file diff --git a/scripts/sfp-core.js b/scripts/sfp-core.js index f5f7d629..07b72e74 100644 --- a/scripts/sfp-core.js +++ b/scripts/sfp-core.js @@ -20,6 +20,8 @@ const SFP_NONCE_PATH = path.join(ROOT, 'data/security/sfp-nonce-registry.json') const SFP_ALERT_PATH = path.join(ROOT, 'data/security/sfp-alert-log.json'); const BEIJING_OFFSET_MS = 8 * 3600 * 1000; +const MAX_NONCE_REGISTRY_SIZE = 1000; +const MAX_ALERT_LOG_SIZE = 500; // ━━━ SFP 指纹正则 ━━━ const SFP_REGEX = /⌜SFP::([^:]+)::([^:]+)::([0-9T+:.-]+)::([a-f0-9]{12})::([a-zA-Z0-9]{6})⌝/; @@ -62,13 +64,8 @@ function computeContentHash(content) { // ━━━ 生成6位随机nonce ━━━ function generateNonce() { - const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; - let nonce = ''; - const bytes = crypto.randomBytes(6); - for (let i = 0; i < 6; i++) { - nonce += chars[bytes[i] % chars.length]; - } - return nonce; + // Use hex encoding of random bytes for unbiased distribution + return crypto.randomBytes(3).toString('hex'); } // ━━━ 获取北京时间ISO字符串 ━━━ @@ -107,8 +104,8 @@ function generateSFP(agentId, content) { content_hash: contentHash }); // 保留最近 1000 条 nonce 记录 - if (nonceRegistry.used_nonces.length > 1000) { - nonceRegistry.used_nonces = nonceRegistry.used_nonces.slice(-1000); + if (nonceRegistry.used_nonces.length > MAX_NONCE_REGISTRY_SIZE) { + nonceRegistry.used_nonces = nonceRegistry.used_nonces.slice(-MAX_NONCE_REGISTRY_SIZE); } writeJSON(SFP_NONCE_PATH, nonceRegistry); } catch (e) { @@ -236,8 +233,8 @@ function logAlert(alertEntry) { logged_at: getBeijingTimestamp() }); // 保留最近 500 条 - if (alertLog.alerts.length > 500) { - alertLog.alerts = alertLog.alerts.slice(-500); + if (alertLog.alerts.length > MAX_ALERT_LOG_SIZE) { + alertLog.alerts = alertLog.alerts.slice(-MAX_ALERT_LOG_SIZE); } writeJSON(SFP_ALERT_PATH, alertLog); } catch (e) { diff --git a/scripts/skyeye/scan-soldier-health.js b/scripts/skyeye/scan-soldier-health.js index 6a83c3e8..9a065796 100644 --- a/scripts/skyeye/scan-soldier-health.js +++ b/scripts/skyeye/scan-soldier-health.js @@ -18,6 +18,9 @@ const ROOT = path.resolve(__dirname, '../..'); const DASHBOARD_PATH = path.join(ROOT, 'data/bulletin-board/dashboard.json'); const SKYEYE_REPORTS_DIR = path.join(ROOT, 'data/skyeye-reports'); +const FAILURE_RATE_THRESHOLD = 20; +const CONSECUTIVE_FAILURE_THRESHOLD_DAYS = 7; + // ━━━ 安全读取 JSON ━━━ function readJSON(filePath) { try { @@ -96,18 +99,18 @@ function scanSoldierHealth() { } // 故障率 > 20% → P0 - if (result.failure_rate > 20) { + if (result.failure_rate > FAILURE_RATE_THRESHOLD) { result.status = '❌'; result.issues.push({ type: 'high_failure_rate', - message: `小兵故障率 ${result.failure_rate}% > 20%`, + message: `小兵故障率 ${result.failure_rate}% > ${FAILURE_RATE_THRESHOLD}%`, action: 'P0工单 · 全局小兵修复' }); } } // 检查连续7天同一错误 - const recentReports = getRecentReports(7); + const recentReports = getRecentReports(CONSECUTIVE_FAILURE_THRESHOLD_DAYS); if (recentReports.length >= 2) { // 收集各报告中的失败 workflow const errorMap = {}; @@ -124,7 +127,7 @@ function scanSoldierHealth() { // 连续7天同一错误 for (const [name, count] of Object.entries(errorMap)) { - if (count >= 7) { + if (count >= CONSECUTIVE_FAILURE_THRESHOLD_DAYS) { result.recurring_errors.push({ soldier: name, consecutive_failures: count, diff --git a/tests/contract/sfp-core.test.js b/tests/contract/sfp-core.test.js index 296a980b..73030dbc 100644 --- a/tests/contract/sfp-core.test.js +++ b/tests/contract/sfp-core.test.js @@ -137,10 +137,10 @@ describe('SFP v1.0 · 系统指纹安全协议', () => { expect(hash).toMatch(/^[a-f0-9]{12}$/); }); - test('generateNonce 返回6位字母数字', () => { + test('generateNonce 返回6位hex字符', () => { const nonce = sfpCore.generateNonce(); expect(nonce).toHaveLength(6); - expect(nonce).toMatch(/^[a-z0-9]{6}$/); + expect(nonce).toMatch(/^[a-f0-9]{6}$/); }); test('SFP_REGEX 能正确匹配指纹格式', () => {