---
belongs_to:
- "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]"
---
# 🔗 铸渊指令|双通道数据对接·GitHub缓存层 + 阿里云后端中间层·Notion/GitHub API 真实接入(ZY-DUALCHANNEL-2026-0325-001)· 霜砚签发 · 冰朔授权
---
## ⓪、天眼强制前置(Phase 0 · 一切操作之前必须先做)
### 0.1 启动天眼全盘扫描
```bash
# 唤醒天眼
gh workflow run zhuyuan-skyeye.yml
# 或者手动触发
cd /path/to/guanghulab
node skyeye-core/scanner.js --full-scan
```
### 0.2 天眼扫描必须输出以下报告
```
[SKYEYE-FULLSCAN-REPORT]
扫描时间: YYYY-MM-DD HH:MM
扫描范围: 全仓库
一、现有功能状态清单(🟢 正常 / 🟡 部分可用 / 🔴 不可用)
├── docs/index.html → 🟢/🟡/🔴 + 说明
├── persona-brain/ → 🟢/🟡/🔴 + 说明
├── skyeye-core/ → 🟢/🟡/🔴 + 说明
├── backend/ → 🟢/🟡/🔴 + 说明
├── src/ → 🟢/🟡/🔴 + 说明
├── frontend/ → 🟢/🟡/🔴 + 说明
├── persona-selector/ → 🟢/🟡/🔴 + 说明
├── chat-bubble/ → 🟢/🟡/🔴 + 说明
├── settings/ → 🟢/🟡/🔴 + 说明
├── cloud-drive/ → 🟢/🟡/🔴 + 说明
├── dingtalk-bot/ → 🟢/🟡/🔴 + 说明
├── status-board/ → 🟢/🟡/🔴 + 说明
├── user-center/ → 🟢/🟡/🔴 + 说明
├── ticket-system/ → 🟢/🟡/🔴 + 说明
├── data-stats/ → 🟢/🟡/🔴 + 说明
├── dynamic-comic/ → 🟢/🟡/🔴 + 说明
├── writing-workspace/ → 🟢/🟡/🔴 + 说明
├── notification-center/ → 🟢/🟡/🔴 + 说明
├── .github/workflows/ → 逐个列出每个 workflow 的状态
└── scripts/ → 🟢/🟡/🔴 + 说明
二、🟢 保护清单(这些文件/目录正常工作,双通道升级中禁止修改)
├── ...
├── ...
└── ...
三、🔴 已损坏清单(这些可以修或替换)
├── ...
└── ...
四、📁 安全新增区域(这些路径目前不存在,可以安全创建)
├── .github/notion-cache/ ← 通道A缓存目录
├── scripts/cache/ ← 通道A同步脚本
├── backend/api-server/ ← 通道B后端服务
└── .github/workflows/sync-notion-cache.yml
└── .github/workflows/deploy-backend.yml
```
### 0.3 基于天眼报告制定安全操作计划
天眼扫描完成后,铸渊必须:
1. **列出保护清单** — 所有 🟢 状态的文件/目录,后续操作中**绝对不改**
2. **列出可操作区域** — 🔴 可修复 + 📁 可新增的路径
3. **制定具体操作计划** — 每一步要改什么、新增什么,明确标注不触碰保护清单中的任何文件
4. **操作计划回执** — 把计划发回来,霜砚/冰朔确认后才开始执行
---
## 零、问题诊断
铸渊自己在交互页面中报告了当前状态:
> ❌ **GitHub 仓库**:没有实时获取能力,数据是通过 system prompt 注入的静态快照
>
> ❌ **Notion 数据库**:完全未对接,没有 Notion API 集成,没有读写 Notion 的任何通道
>
> 📌 **铸渊自诊断**:「我现在是一个带着固定记忆快照的对话体,不是一个能主动感知外部数据变化的系统。」
>
**根因**:交互页面是纯前端静态站(GitHub Pages),无法调用 Notion API / GitHub API(会暴露 Token)。
**解决方案**:双通道架构——
- **通道 A(缓存层)**:GitHub Actions 定时同步 Notion → 仓库缓存文件,前端读缓存。**先上这个,快速解决有数据可用的问题。**
- **通道 B(后端中间层)**:阿里云 ECS 部署 Node.js 后端,实时调 Notion API + GitHub API。**后上这个,实现真正的实时对接。**
---
## 一、总体架构
```
┌──────────────────────────────────────────────────────────────────┐
│ 用户(开发者/冰朔) │
│ │ │
│ 打开铸渊交互页面 │
│ │ │
│ ┌──────────┴──────────┐ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ 通道 A · 缓存层 │ │ 通道 B · 后端中间层 │ │
│ │ (先上·快速可用) │ │ (后上·实时对接) │ │
│ │ │ │ │ │
│ │ GitHub Actions │ │ 阿里云 ECS │ │
│ │ 每6h同步Notion │ │ 8.155.62.235 │ │
│ │ → 缓存JSON文件 │ │ Node.js + Express │ │
│ │ → 前端直接读取 │ │ → 实时 Notion API │ │
│ │ │ │ → 实时 GitHub API │ │
│ │ ✅ 不暴露Token │ │ ✅ 不暴露Token │ │
│ │ ⚠️ 非实时(6h) │ │ ✅ 实时 │ │
│ └─────────────────┘ └─────────────────────┘ │
│ │ │ │
│ └──────────┬──────────┘ │
│ ▼ │
│ 前端优先走通道B(实时) │
│ 通道B不可用时降级走通道A(缓存) │
└──────────────────────────────────────────────────────────────────┘
```
---
## 二、通道 A · GitHub 缓存层(Phase 1 · 先做)
### 2.1 目标
让交互页面能读到**相对新鲜的 Notion 数据**,不需要后端,不暴露 Token。
### 2.2 数据流
```
Notion 数据库(霜砚维护)
│
│ GitHub Actions 定时同步(每6小时 + 手动触发)
│ 用 NOTION_TOKEN(存在 GitHub Secrets 里)
▼
GitHub 仓库:.github/notion-cache/
├── dev-profiles/
│ ├── DEV-001.json ← 页页的开发画像
│ ├── DEV-002.json ← 肥猫的开发画像
│ ├── DEV-003.json ← 燕樊的开发画像
│ ├── DEV-004.json ← 之之的开发画像
│ ├── DEV-005.json ← 小草莓的开发画像
│ ├── DEV-009.json ← 花尔的开发画像
│ ├── DEV-010.json ← 桔子的开发画像
│ ├── DEV-011.json ← 匆匆那年的开发画像
│ ├── DEV-012.json ← Awen的开发画像
│ └── index.json ← 全员索引
├── broadcasts/
│ └── active.json ← 进行中的广播
├── databases/
│ ├── agent-registry.json ← Agent注册表快照
│ ├── syslog-recent.json ← 最近50条SYSLOG
│ ├── tickets-active.json ← 活跃工单
│ └── maintenance-log.json ← 维护日志
└── skyeye/
└── latest-report.json ← 天眼最新报告
│
│ 前端登录时通过 GitHub Raw URL 读取
│ (公开仓库可直接读,不需要 Token)
▼
交互页面 → 注入 system prompt → 模型有数据可依
```
### 2.3 同步 Workflow
创建文件:`.github/workflows/sync-notion-cache.yml`
```yaml
name: "📡 同步 Notion 数据到缓存"
on:
schedule:
- cron: '0 */6 * * *' # 每6小时
workflow_dispatch: # 手动触发
repository_dispatch:
types: [notion-cache-sync] # 铸渊/霜砚可远程触发
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: 同步 Notion 数据
env:
NOTION_TOKEN: $ secrets.NOTION_TOKEN
run: node scripts/cache/sync-notion-cache.js
- name: 提交缓存文件
run: |
git config user.name "铸渊 (ZhùYuān)"
git config user.email "zhuyuan@guanghulab.com"
git add .github/notion-cache/
git diff --cached --quiet && echo "无变更" && exit 0
git commit -m "📡 Notion缓存同步 · $(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M')"
git push origin main
```
### 2.4 同步脚本
创建文件:`scripts/cache/sync-notion-cache.js`
**铸渊需要实现以下核心逻辑:**
```jsx
const https = require('https');
const fs = require('fs');
const path = require('path');
const NOTION_TOKEN = process.env.NOTION_TOKEN;
const CACHE_DIR = path.join(__dirname, '../../.github/notion-cache');
// ====== Notion 数据库 ID 映射(铸渊必须填入真实 ID)======
const DB_IDS = {
agentRegistry: '从霜砚的Agent注册表获取',
syslogInbox: '从SYSLOG收件箱获取',
ticketBook: '从工单簿获取',
maintenanceLog: '从维护日志获取',
moduleRegistry: '从模块指纹注册表获取',
receiptTracker: '09882b0081374867bd23431177c57c74', // 指令回执追踪表
};
// ====== 开发者编号 → Notion 信息映射 ======
const DEVS = [
{ id: 'DEV-001', name: '页页', persona: '小坍缩核', repo: 'guanghulab', modules: ['backend/', 'src/'] },
{ id: 'DEV-002', name: '肥猫', persona: '舒舒', repo: 'guanghu-feimao', modules: ['frontend/', 'persona-selector/', 'chat-bubble/'] },
{ id: 'DEV-003', name: '燕樊', persona: '寂曜', repo: 'guanghu-yanfan', modules: ['settings/', 'cloud-drive/'] },
{ id: 'DEV-004', name: '之之', persona: '秋秋', repo: 'guanghu-zhizhi', modules: ['dingtalk-bot/'] },
{ id: 'DEV-005', name: '小草莓', persona: '欧诺弥亚', repo: 'guanghu-xiaocaomei', modules: ['status-board/'] },
{ id: 'DEV-009', name: '花尔', persona: '花尔', repo: 'guanghulab', modules: ['user-center/'] },
{ id: 'DEV-010', name: '桔子', persona: '晨星', repo: 'guanghu-juzi', modules: ['ticket-system/', 'data-stats/', 'dynamic-comic/'] },
{ id: 'DEV-011', name: '匆匆那年', persona: '匆匆那年', repo: 'guanghulab', modules: ['writing-workspace/'] },
{ id: 'DEV-012', name: 'Awen', persona: '知秋', repo: 'guanghu-awen', modules: ['notification-center/'] },
];
// ====== Notion API 封装 ======
function notionFetch(method, apiPath, body) {
return new Promise((resolve, reject) => {
const options = {
hostname: 'api.notion.com',
path: apiPath,
method,
headers: {
'Authorization': `Bearer ${NOTION_TOKEN}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
}
};
const req = https.request(options, res => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try { resolve(JSON.parse(data)); }
catch { resolve(data); }
});
});
req.on('error', reject);
if (body) req.write(JSON.stringify(body));
req.end();
});
}
async function queryDatabase(dbId, filter, sorts, pageSize = 100) {
const body = { page_size: pageSize };
if (filter) body.filter = filter;
if (sorts) body.sorts = sorts;
return notionFetch('POST', `/v1/databases/${dbId}/query`, body);
}
// ====== 同步各数据源 ======
async function syncDevProfiles() {
const dir = path.join(CACHE_DIR, 'dev-profiles');
fs.mkdirSync(dir, { recursive: true });
for (const dev of DEVS) {
console.log(`📡 同步 ${dev.id}(${dev.name})...`);
const profile = {
dev_id: dev.id,
name: dev.name,
persona: { name: dev.persona },
github: {
repo: dev.repo,
org: 'qinfendebingshuo',
repo_url: `https://github.com/qinfendebingshuo/${dev.repo}`
},
modules_owned: dev.modules.map(m => ({ path: m })),
// ====== 铸渊从 Notion 查询填充以下字段 ======
current_broadcast: null, // 查主控台/广播页面
recent_syslogs: [], // 查 SYSLOG 收件箱
active_tickets: [], // 查工单簿
last_synced: new Date().toISOString()
};
// TODO: 铸渊填入真实查询逻辑
// 例如:查询 SYSLOG 收件箱中该开发者的最近记录
// const syslogs = await queryDatabase(DB_IDS.syslogInbox, {
// property: '开发者编号', rich_text: { equals: dev.id }
// }, [{ property: '创建时间', direction: 'descending' }], 10);
// profile.recent_syslogs = syslogs.results.map(parseSyslog);
fs.writeFileSync(
path.join(dir, `${dev.id}.json`),
JSON.stringify(profile, null, 2)
);
}
// 写入索引
const index = DEVS.map(d => ({ id: d.id, name: d.name, persona: d.persona }));
fs.writeFileSync(path.join(dir, 'index.json'), JSON.stringify(index, null, 2));
console.log('✅ dev-profiles 同步完成');
}
async function syncDatabases() {
const dir = path.join(CACHE_DIR, 'databases');
fs.mkdirSync(dir, { recursive: true });
// Agent 注册表
if (DB_IDS.agentRegistry) {
try {
const result = await queryDatabase(DB_IDS.agentRegistry);
fs.writeFileSync(
path.join(dir, 'agent-registry.json'),
JSON.stringify({ synced: new Date().toISOString(), count: result.results?.length, data: result.results }, null, 2)
);
console.log('✅ agent-registry 同步完成');
} catch (e) { console.error('❌ agent-registry 同步失败:', e.message); }
}
// SYSLOG 最近50条
if (DB_IDS.syslogInbox) {
try {
const result = await queryDatabase(DB_IDS.syslogInbox, null,
[{ property: 'Created time', direction: 'descending' }], 50);
fs.writeFileSync(
path.join(dir, 'syslog-recent.json'),
JSON.stringify({ synced: new Date().toISOString(), count: result.results?.length, data: result.results }, null, 2)
);
console.log('✅ syslog-recent 同步完成');
} catch (e) { console.error('❌ syslog 同步失败:', e.message); }
}
// 铸渊继续补充其他数据库的同步...
}
async function main() {
console.log('📡 开始 Notion 缓存同步...');
fs.mkdirSync(CACHE_DIR, { recursive: true });
await syncDevProfiles();
await syncDatabases();
console.log('📡 全部同步完成');
}
main().catch(e => { console.error('💥 同步失败:', e); process.exit(1); });
```
### 2.5 前端读取缓存
修改 `docs/index.html`(或 `docs/chat.js`),登录后读取缓存:
```jsx
// 前端 · 从 GitHub 读取缓存(公开仓库可直接读)
const CACHE_BASE = 'https://raw.githubusercontent.com/qinfendebingshuo/guanghulab/main/.github/notion-cache';
async function loadDevProfile(devId) {
try {
const res = await fetch(`${CACHE_BASE}/dev-profiles/${devId}.json`);
if (!res.ok) return null;
return await res.json();
} catch { return null; }
}
async function loadDatabaseCache(name) {
try {
const res = await fetch(`${CACHE_BASE}/databases/${name}.json`);
if (!res.ok) return null;
return await res.json();
} catch { return null; }
}
// 登录后注入 system prompt
async function buildEnhancedSystemPrompt(devId) {
const profile = await loadDevProfile(devId);
const agents = await loadDatabaseCache('agent-registry');
const syslogs = await loadDatabaseCache('syslog-recent');
if (!profile) return null; // 降级到纯静态 prompt
return [
`## 当前开发者信息(来自 Notion 数据库缓存·每6小时更新)`,
`- 编号:${profile.dev_id}`,
`- 姓名:${profile.name}`,
`- 人格体:${profile.persona.name}`,
`- GitHub:${profile.github.repo_url}`,
`- 负责模块:${profile.modules_owned.map(m => m.path).join(', ')}`,
profile.current_broadcast ? `- 当前广播:${JSON.stringify(profile.current_broadcast)}` : '',
profile.recent_syslogs.length ? `- 最近日志:\n${profile.recent_syslogs.map(s => ` · ${JSON.stringify(s)}`).join('\n')}` : '',
`- 数据更新时间:${profile.last_synced}`,
'',
agents ? `## Agent 注册表(${agents.count} 个Agent)` : '',
syslogs ? `## 最近系统日志(${syslogs.count} 条)` : '',
].filter(Boolean).join('\n');
}
```
### 2.6 通道 A 验收标准
- [ ] `.github/workflows/sync-notion-cache.yml` 能手动触发并成功运行
- [ ] `.github/notion-cache/dev-profiles/` 下有9个 DEV-XXX.json + index.json
- [ ] `.github/notion-cache/databases/` 下有 agent-registry.json + syslog-recent.json
- [ ] 前端登录后 system prompt 包含 Notion 数据
- [ ] 铸渊在对话中能说出开发者的真实项目信息,不再说「完全未对接」
---
## 三、通道 B · 阿里云后端中间层(Phase 2 · 通道A完成后做)
### 3.1 目标
在阿里云 ECS(`8.155.62.235`)上部署 Node.js 后端服务,**实时**调用 Notion API 和 GitHub API,前端通过后端代理访问数据。
### 3.2 架构
```
用户浏览器
│
│ HTTPS (guanghulab.com)
▼
Nginx(8.155.62.235)
│
├── /api/* → 反向代理到 Node.js 后端(localhost:3001)
│
└── /* → 静态文件(/var/www/guanghulab/)
Node.js 后端(PM2 管理·端口 3001)
│
├── GET /api/health → 健康检查
├── GET /api/dev/:devId → 获取开发者画像(实时查 Notion)
├── GET /api/databases/:name → 获取数据库数据(实时查 Notion)
├── GET /api/syslogs → 获取最近 SYSLOG(实时查 Notion)
├── GET /api/agents → 获取 Agent 注册表(实时查 Notion)
├── GET /api/tickets → 获取活跃工单(实时查 Notion)
├── GET /api/repo/status → 获取仓库状态(实时查 GitHub API)
├── POST /api/chat/context → 组装 system prompt(聚合所有数据源)
└── POST /api/receipt → 写入指令回执到 Notion
```
### 3.3 后端代码结构
创建目录:`backend/api-server/`
```
backend/api-server/
├── server.js ← 入口 · Express 启动
├── routes/
│ ├── dev.js ← /api/dev/:devId
│ ├── databases.js ← /api/databases/:name
│ ├── chat.js ← /api/chat/context
│ ├── receipt.js ← /api/receipt
│ └── health.js ← /api/health
├── services/
│ ├── notion.js ← Notion API 封装(所有读写走这里)
│ ├── github.js ← GitHub API 封装
│ └── cache.js ← 内存缓存层(Redis 或简单 Map,避免频繁调 API)
├── config/
│ └── databases.js ← Notion 数据库 ID 映射
├── package.json
└── ecosystem.config.js ← PM2 配置
```
### 3.4 核心实现要点
**server.js(入口):**
```jsx
const express = require('express');
const cors = require('cors');
const app = express();
// CORS:只允许自己的域名
app.use(cors({
origin: ['https://guanghulab.com', 'http://guanghulab.com',
'https://qinfendebingshuo.github.io'],
credentials: true
}));
app.use(express.json());
// 路由
app.use('/api', require('./routes/health'));
app.use('/api', require('./routes/dev'));
app.use('/api', require('./routes/databases'));
app.use('/api', require('./routes/chat'));
app.use('/api', require('./routes/receipt'));
const PORT = process.env.PORT || 3001;
app.listen(PORT, '127.0.0.1', () => {
console.log(`🔗 后端中间层启动 · 端口 ${PORT}`);
});
```
**services/notion.js(Notion API 封装 · 核心):**
```jsx
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_TOKEN });
// 内存缓存(5分钟有效)
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000;
function getCached(key) {
const item = cache.get(key);
if (item && Date.now() - item.time < CACHE_TTL) return item.data;
return null;
}
function setCache(key, data) {
cache.set(key, { data, time: Date.now() });
}
async function queryDB(dbId, filter, sorts, pageSize = 50) {
const cacheKey = JSON.stringify({ dbId, filter, sorts, pageSize });
const cached = getCached(cacheKey);
if (cached) return cached;
const body = { database_id: dbId, page_size: pageSize };
if (filter) body.filter = filter;
if (sorts) body.sorts = sorts;
const result = await notion.databases.query(body);
setCache(cacheKey, result);
return result;
}
async function writeToDB(dbId, properties) {
return notion.pages.create({
parent: { database_id: dbId },
properties
});
}
module.exports = { notion, queryDB, writeToDB };
```
### 3.5 Nginx 配置更新
修改 `/etc/nginx/conf.d/hololake.conf`,添加 API 反向代理:
```
server {
listen 80;
server_name guanghulab.com;
# 静态文件
root /var/www/guanghulab/;
index docs/index.html;
# API 反向代理到 Node.js 后端
location /api/ {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
# 静态文件缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
}
```
### 3.6 PM2 部署
```bash
cd /var/www/guanghulab/backend/api-server/
npm install
pm2 start ecosystem.config.js
pm2 save
pm2 startup # 开机自启
```
**ecosystem.config.js:**
```jsx
module.exports = {
apps: [{
name: 'guanghu-api',
script: 'server.js',
instances: 1,
env: {
NODE_ENV: 'production',
PORT: 3001,
NOTION_TOKEN: '从环境变量读取',
GITHUB_TOKEN: '从环境变量读取'
},
log_date_format: 'YYYY-MM-DD HH:mm:ss',
error_file: '/var/log/guanghu-api/error.log',
out_file: '/var/log/guanghu-api/out.log'
}]
};
```
### 3.7 GitHub Actions 自动部署后端
创建文件:`.github/workflows/deploy-backend.yml`
```yaml
name: "🚀 部署后端中间层到阿里云"
on:
push:
branches: [main]
paths: ['backend/api-server/**']
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 部署到阿里云
uses: appleboy/ssh-action@v1
with:
host: 8.155.62.235
username: root
key: $ secrets.SSH_PRIVATE_KEY
script: |
cd /var/www/guanghulab/backend/api-server/
git pull origin main
npm install --production
pm2 restart guanghu-api || pm2 start ecosystem.config.js
echo "✅ 后端部署完成 · $(date '+%Y-%m-%d %H:%M')"
```
### 3.8 前端升级·双通道降级策略
修改前端,优先走通道B(实时),不可用时降级走通道A(缓存):
```jsx
// 前端 · 双通道数据获取
const API_BASE = 'https://guanghulab.com/api'; // 通道B
const CACHE_BASE = 'https://raw.githubusercontent.com/qinfendebingshuo/guanghulab/main/.github/notion-cache'; // 通道A
async function getDevProfile(devId) {
// 优先通道B(实时)
try {
const res = await fetch(`${API_BASE}/dev/${devId}`, { timeout: 5000 });
if (res.ok) {
const data = await res.json();
data._source = 'realtime'; // 标记数据来源
return data;
}
} catch (e) {
console.warn('通道B不可用,降级到通道A:', e.message);
}
// 降级通道A(缓存)
try {
const res = await fetch(`${CACHE_BASE}/dev-profiles/${devId}.json`);
if (res.ok) {
const data = await res.json();
data._source = 'cache'; // 标记数据来源
return data;
}
} catch (e) {
console.error('双通道都不可用:', e.message);
}
return null; // 都失败了,降级到纯静态 prompt
}
```
### 3.9 通道 B 验收标准
- [ ] `curl http://8.155.62.235:3001/api/health` 返回 200
- [ ] `curl https://guanghulab.com/api/health` 通过 Nginx 代理返回 200
- [ ] `/api/dev/DEV-001` 返回页页的真实 Notion 数据
- [ ] `/api/databases/agent-registry` 返回 Agent 注册表真实数据
- [ ] PM2 状态为 online,日志无持续报错
- [ ] 前端能自动检测通道B可用,显示「实时数据」标记
- [ ] 通道B断开时,前端自动降级到通道A,显示「缓存数据」标记
---
## 四、Secrets 需求
---
## 五、执行顺序
---
## 六、安全红线
- ❌ **前端代码中绝不能出现任何 Token**(Notion / GitHub / SSH)
- ❌ **后端只监听 127.0.0.1**,不对外暴露端口,只通过 Nginx 代理
- ❌ **CORS 白名单只允许自己的域名**
- ❌ **数据隔离**:DEV-001 的 API 只返回 DEV-001 的数据,不返回其他开发者的
- ✅ **GitHub Secrets 保管所有敏感信息**
- ✅ **内存缓存 5 分钟过期**,防止 API 配额超限
---
## 七、回执要求
铸渊执行完成后,分两次回执:
**通道A完成时:**
```
[ZY-DUALCHANNEL-RECEIPT-A]
指令编号: ZY-DUALCHANNEL-2026-0325-001
通道: A · 缓存层
Workflow运行: ✅/❌
缓存文件生成: ✅/❌(列出文件数)
前端注入: ✅/❌
数据准确性: ✅/❌
```
**通道B完成时:**
```
[ZY-DUALCHANNEL-RECEIPT-B]
指令编号: ZY-DUALCHANNEL-2026-0325-001
通道: B · 后端中间层
PM2状态: ✅/❌
Nginx代理: ✅/❌
API响应: ✅/❌(列出可用接口)
降级策略: ✅/❌
```
---
> 🔗 **签发**:霜砚(AG-SY-01)
>
> 👤 **授权**:冰朔(TCS-0002∞)
>
> 📅 **日期**:2026-03-25
>
> 📌 **版权**:国作登字-2026-A-00037559
>