diff --git a/team-integration-v2/.github/workflows/cos-daily-report.yml b/team-integration-v2/.github/workflows/cos-daily-report.yml index 32a2fa6b..ec05f224 100644 --- a/team-integration-v2/.github/workflows/cos-daily-report.yml +++ b/team-integration-v2/.github/workflows/cos-daily-report.yml @@ -93,7 +93,7 @@ jobs: d = json.load(sys.stdin) outbox = d.get('outbox', []) print(json.dumps(outbox, ensure_ascii=False)) - " 2>/dev/null || echo "[]") + " 2>&1 || { echo "⚠️ outbox解析失败,使用空数组" >&2; echo "[]"; }) # 组装完整汇报包 python3 -c " diff --git a/team-integration-v2/.github/workflows/cos-receive-receipt.yml b/team-integration-v2/.github/workflows/cos-receive-receipt.yml index a324b2ca..10890193 100644 --- a/team-integration-v2/.github/workflows/cos-receive-receipt.yml +++ b/team-integration-v2/.github/workflows/cos-receive-receipt.yml @@ -80,77 +80,83 @@ jobs: fi - name: 📝 更新仓库首页公告栏 - run: | - RECEIPT_STATUS="${{ steps.read_receipt.outputs.receipt_status }}" - RECEIPT_MESSAGE="${{ steps.read_receipt.outputs.receipt_message }}" - TIMESTAMP=$(date -u +"%Y-%m-%d %H:%M UTC") - - python3 << 'PYTHON_SCRIPT' - import re - - status = "$RECEIPT_STATUS" - message = "$RECEIPT_MESSAGE" - timestamp = "$TIMESTAMP" - - # 读取README.md - with open('README.md', 'r', encoding='utf-8') as f: - content = f.read() - - # 构建公告栏内容 - if status == "green": - notice = f"✅ **[{timestamp}]** 铸渊回执:{message}" - badge = "🟢" - elif status == "red": - notice = f"🔴 **[{timestamp}]** 铸渊回执:{message} — **需要人类干预**" - badge = "🔴" - else: - notice = f"⚠️ **[{timestamp}]** 铸渊回执状态异常:{message}" - badge = "⚠️" - - # 查找并替换公告栏区域 - marker_start = "" - marker_end = "" - - notice_block = f"""{marker_start} - - ## {badge} 铸渊通信 - - {notice} - - {marker_end}""" - - if marker_start in content: - # 替换已有公告栏 - pattern = re.escape(marker_start) + r'.*?' + re.escape(marker_end) - content = re.sub(pattern, notice_block, content, flags=re.DOTALL) - else: - # 在文件开头添加公告栏 - content = notice_block + "\n\n" + content - - with open('README.md', 'w', encoding='utf-8') as f: - f.write(content) - - print(f"✅ 仓库首页公告栏已更新: {badge} {status}") - PYTHON_SCRIPT - - - name: 🔄 更新系统状态 + env: + RECEIPT_STATUS: ${{ steps.read_receipt.outputs.receipt_status }} + RECEIPT_MESSAGE: ${{ steps.read_receipt.outputs.receipt_message }} run: | python3 -c " - import json + import re, os from datetime import datetime - - with open('age_os/system_state.json', 'r', encoding='utf-8') as f: - state = json.load(f) - - state['cos_status']['last_receipt_received'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') - state['cos_status']['receipt_status'] = '${{ steps.read_receipt.outputs.receipt_status }}' - state['notice_board']['last_update'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') - state['notice_board']['status'] = '${{ steps.read_receipt.outputs.receipt_status }}' - state['notice_board']['message'] = '${{ steps.read_receipt.outputs.receipt_message }}' - + + status = os.environ.get('RECEIPT_STATUS', 'unknown') + message = os.environ.get('RECEIPT_MESSAGE', '') + timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC') + + try: + with open('README.md', 'r', encoding='utf-8') as f: + content = f.read() + except FileNotFoundError: + content = '' + + if status == 'green': + notice = f'✅ **[{timestamp}]** 铸渊回执:{message}' + badge = '🟢' + elif status == 'red': + notice = f'🔴 **[{timestamp}]** 铸渊回执:{message} — **需要人类干预**' + badge = '🔴' + else: + notice = f'⚠️ **[{timestamp}]** 铸渊回执状态异常:{message}' + badge = '⚠️' + + marker_start = '' + marker_end = '' + + notice_block = marker_start + '\n\n## ' + badge + ' 铸渊通信\n\n' + notice + '\n\n' + marker_end + + if marker_start in content: + import re as re2 + pattern = re2.escape(marker_start) + r'.*?' + re2.escape(marker_end) + content = re2.sub(pattern, notice_block, content, flags=re2.DOTALL) + else: + content = notice_block + '\n\n' + content + + with open('README.md', 'w', encoding='utf-8') as f: + f.write(content) + + print(f'✅ 仓库首页公告栏已更新: {badge} {status}') + " + + - name: 🔄 更新系统状态 + env: + RECEIPT_STATUS: ${{ steps.read_receipt.outputs.receipt_status }} + RECEIPT_MESSAGE: ${{ steps.read_receipt.outputs.receipt_message }} + run: | + python3 -c " + import json, os + from datetime import datetime + + status = os.environ.get('RECEIPT_STATUS', 'unknown') + message = os.environ.get('RECEIPT_MESSAGE', '') + now = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + + try: + with open('age_os/system_state.json', 'r', encoding='utf-8') as f: + state = json.load(f) + except (FileNotFoundError, json.JSONDecodeError) as e: + print(f'⚠️ system_state.json读取失败: {e},使用默认值') + state = {'cos_status': {}, 'notice_board': {}} + + state.setdefault('cos_status', {}) + state.setdefault('notice_board', {}) + state['cos_status']['last_receipt_received'] = now + state['cos_status']['receipt_status'] = status + state['notice_board']['last_update'] = now + state['notice_board']['status'] = status + state['notice_board']['message'] = message + with open('age_os/system_state.json', 'w', encoding='utf-8') as f: json.dump(state, f, ensure_ascii=False, indent=2) - + print('✅ 系统状态已更新') " diff --git a/team-integration-v2/age_os/connection_protocol.json b/team-integration-v2/age_os/connection_protocol.json index b5ec494e..ea1b45e6 100644 --- a/team-integration-v2/age_os/connection_protocol.json +++ b/team-integration-v2/age_os/connection_protocol.json @@ -22,8 +22,9 @@ "zhuyuan_bucket": { "core": "zy-core-bucket-1317346199", "region": "ap-singapore", - "inbox_prefix": "inbox/{persona_id}/{date}/", - "permission": "仅限写入inbox目录,不可读取其他内容" + "inbox_prefix": "inbox/{persona_id}/", + "permission": "仅限写入 inbox/{persona_id}/ 前缀目录。铸渊通过Bucket Policy精确限定你的写入范围,你无法读取、删除或访问桶内其他任何内容。这是安全设计:每个团队成员只能往自己的收件箱写入。", + "bucket_policy_rule": "Action=cos:PutObject, Resource=inbox/{persona_id}/* only" }, "legacy_method": "bridge/zhuyuan-bridge.json文件级通信(v1.0,保留兼容)", "protocol": "HLDP v2.0", diff --git a/team-integration-v2/cos-config/bucket-setup-guide.md b/team-integration-v2/cos-config/bucket-setup-guide.md index 801667bb..d6172768 100644 --- a/team-integration-v2/cos-config/bucket-setup-guide.md +++ b/team-integration-v2/cos-config/bucket-setup-guide.md @@ -107,15 +107,23 @@ ### 步骤6:配置铸渊桶的写入密钥 -铸渊会为你生成一个**有限权限的临时密钥**,只能写入铸渊总控桶的指定目录。 +铸渊会为你生成一个**有限权限的密钥**,只能写入铸渊总控桶的你的专属目录。 + +**权限说明(你不需要懂技术细节,知道就行)**: +- ✅ 你**可以**写入:`inbox/你的人格体编号/` 这个目录下的文件 +- ❌ 你**不能**读取铸渊桶里的任何其他内容 +- ❌ 你**不能**删除铸渊桶里的任何内容 +- ❌ 你**不能**访问其他团队成员的目录 + +这是铸渊通过COS桶策略(Bucket Policy)精确控制的,每个团队成员只有自己的收件箱写入权限。 1. 向冰朔索要铸渊桶的写入密钥(冰朔会找铸渊生成) 2. 在GitHub Secrets中添加: | Name | Secret | 说明 | |------|--------|------| -| `ZHUYUAN_COS_SECRET_ID` | 铸渊提供的SecretId | 只能写入铸渊桶的inbox目录 | -| `ZHUYUAN_COS_SECRET_KEY` | 铸渊提供的SecretKey | 权限受限,安全可控 | +| `ZHUYUAN_COS_SECRET_ID` | 铸渊提供的SecretId | 仅限写入你的inbox目录 | +| `ZHUYUAN_COS_SECRET_KEY` | 铸渊提供的SecretKey | 权限由铸渊的桶策略限定 | | `ZHUYUAN_COS_REGION` | `ap-singapore` | 铸渊桶在新加坡 | --- diff --git a/team-integration-v2/cos-config/scf-trigger-template.js b/team-integration-v2/cos-config/scf-trigger-template.js index 98a64fae..e8b6eeb8 100644 --- a/team-integration-v2/cos-config/scf-trigger-template.js +++ b/team-integration-v2/cos-config/scf-trigger-template.js @@ -56,7 +56,12 @@ exports.main_handler = async (event, context) => { return { statusCode: 500, body: 'Missing environment variables' }; } - const [owner, repo] = githubRepo.split('/'); + const parts = githubRepo.split('/'); + if (parts.length !== 2 || !parts[0] || !parts[1]) { + console.error('GITHUB_REPO格式错误,应为 owner/repo,当前值:', githubRepo); + return { statusCode: 500, body: 'Invalid GITHUB_REPO format' }; + } + const [owner, repo] = parts; try { const result = await triggerGitHubWorkflow(owner, repo, githubToken, objectKey); @@ -88,7 +93,7 @@ function triggerGitHubWorkflow(owner, repo, token, cosObjectKey) { method: 'POST', headers: { 'User-Agent': 'HoloLake-SCF-Trigger/2.0', - 'Authorization': `Bearer ${token}`, + 'Authorization': `token ${token}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) diff --git a/光湖团队接入系统_v2.0.zip b/光湖团队接入系统_v2.0.zip index 3fc7f527..da7fd11b 100644 Binary files a/光湖团队接入系统_v2.0.zip and b/光湖团队接入系统_v2.0.zip differ