feat: 实现 Bell 联系人与值班排班 (#183)

This commit is contained in:
QiuSW
2026-09-01 12:16:52 +08:00
parent 5adee5c3b4
commit e81f00e9aa
26 changed files with 1960 additions and 9 deletions
+19 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Architecture-and-Code-Map
wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Architecture-and-Code-Map.-
wiki_revision: 77af1bb5a71d7b89e74b1905ca11b6040dc0d1eb
synchronized_at: 2026-08-31T08:25:26Z
wiki_revision: 0b760f2398ea4c1fd1d776b0cf869532b167c495
synchronized_at: 2026-09-01T04:08:05Z
<!-- gitea-wiki-mirror:end -->
# 架构与代码地图
@@ -382,3 +382,20 @@ coordination-common.ps1
协调层不拥有业务数据或契约,不共享用户表、JWT、Cookie、数据库内部模型、摄像头凭据或产品实现。它不替代 `contracts/**`,也不让任一产品成为另一产品的启动前置;connector 可关闭,三端核心能力继续独立运行。根级运行状态位于清单指定的 `runtime_root\state`,产品日志仍归各自日志目录和产品入口管理。
<!-- coordination-deployment-v1:end -->
<!-- bell-contact-schedule:start -->
## Bell 联系人与值班排班代码路径
后端调用链:
- `Bell/server/router/contact.go` → `app/bell/contact.Handler` → `app/bell/contact.Service` → 联系人、通道、验证事实与审计表。
- `Bell/server/router/duty_schedule.go` → `app/bell/duty_schedule.Handler` → `app/bell/duty_schedule.Service` → 值班组、成员、排班版本、时段、发布与临时替班表。
- `Bell/server/cmd/migrate/migration/version/2026090110000_contact_schedule.go` 创建业务表、约束、不可变事实触发器,以及 GoAdmin 菜单、API 和 Casbin 权限种子。
- `Bell/ui/src/api/bell/contact.js`、`duty-schedule.js` 与对应 `views/bell/` 页面复用 GoAdmin 的请求封装、布局、表格、表单、弹窗和权限指令。
安全边界:
- `BELL_CONTACT_CHANNEL_KEY` 是 Base64 编码的 32 字节 AES-256 密钥,只允许从进程环境读取,不得写入仓库或日志。
- 通道地址采用 AES-GCM 加密,API 模型不暴露密文字段;服务端只在受控发送路径按需解密。
- `Bell/server/cmd/api/server.go` 在 GoAdmin `LoggerToFile` 之前注册联系人通道请求体脱敏中间件,使操作日志只能接触固定脱敏内容。
<!-- bell-contact-schedule:end -->
+21 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Business-Rules-and-Glossary
wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Business-Rules-and-Glossary.-
wiki_revision: c0903448152d7fa88715e902efa99615a6b97083
synchronized_at: 2026-08-31T07:23:13Z
wiki_revision: 9be486cd2d3fe424cf389f65c2c868eacab6a020
synchronized_at: 2026-09-01T04:08:16Z
<!-- gitea-wiki-mirror:end -->
# 业务规则与术语
@@ -287,3 +287,22 @@ synchronized_at: 2026-08-31T07:23:13Z
- **停用规则**:关闭 connector 只停止新接入或投递;不得清空未投递 Outbox、持久 replay、Receipt、Event、证据元数据或审计。
- **独立运行**:Sense、Brain、Bell 不因对端未安装、离线或 connector 关闭而停止各自核心能力;不得以共享数据库/JWT/Cookie 规避故障隔离。
<!-- integration-connectors-v1:end -->
<!-- bell-contact-schedule:start -->
## Bell 联系人与排班术语
- **联系人(Contact)**:可参与 Bell 告警接收和值班安排的人员记录。
- **通知通道(Channel)**:联系人使用的消息到达方式;通道地址密文保存,对外只提供脱敏摘要。
- **通道验证事实(Channel Validation)**:一次独立、只追加的验证结果;“已验证”不等于“已启用”。
- **值班组(Duty Group)**:参与同一排班规则的一组联系人。
- **排班版本(Schedule Version)**:值班组在指定 IANA 时区下的一套完整周排班;发布后冻结,不原位修改。
- **轮值时段(Rotation Slot)**:排班版本内的连续时间段,包含不同的主值班与备值班联系人。
- **临时替班(Override)**:在已发布排班上的只追加例外事实,不改写原排班历史。
规则:
1. 发布前必须验证整周无空档、无重叠,并验证主备不同、成员有效及通知通道已启用且已验证。
2. 已发布排班、通道验证事实、审计事实和临时替班记录保持不可变;更正通过新版本或新事实完成。
3. 同一排班版本中的临时替班不能重叠。
4. 普通操作员只读;创建、修改、启停、验证、发布和替班由管理员执行。
<!-- bell-contact-schedule:end -->
+32 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Local-Development-and-Verification
wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Local-Development-and-Verification.-
wiki_revision: 889ffccc30a998a5cc8c4a5d91af3c72771c093a
synchronized_at: 2026-08-31T13:00:20Z
wiki_revision: e90d408200d7189771eeec35ae76a00837e2eedf
synchronized_at: 2026-09-01T04:08:26Z
<!-- gitea-wiki-mirror:end -->
# 本地开发与验证
@@ -816,3 +816,33 @@ git diff --check
已验证范围不包含真实 GPU/生产模型、真实摄像头、通知供应商、生产迁移、16 路长稳和客户现场效果;这些项目必须在对应环境和独立工单中验收。
<!-- coordination-e2e-v1:end -->
<!-- bell-contact-schedule:start -->
## 验证 Bell 联系人与值班排班
后端与 PostgreSQL 集成验证:
```powershell
Set-Location Bell/server
$env:GOTOOLCHAIN = 'go1.26.5'
go test ./... -count=1
pwsh ./tests/bell_contact_schedule/run-postgres.ps1
```
前端验证:
```powershell
Set-Location Bell/ui
corepack pnpm lint
corepack pnpm build:prod
```
联系人通道加密需要在运行进程中配置 `BELL_CONTACT_CHANNEL_KEY`。它必须是 Base64 编码的 32 字节随机值,不得提交到 Git、Wiki、工单或日志。仅为当前 PowerShell 进程生成测试密钥:
```powershell
$keyBytes = [Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
$env:BELL_CONTACT_CHANNEL_KEY = [Convert]::ToBase64String($keyBytes)
```
PostgreSQL 脚本会验证密文保存、写接口不回显地址、验证与启用状态分离、过期版本冲突、完整周覆盖、已发布历史不可修改、临时替班不重叠、不可变事实约束、操作员只读权限,以及操作日志不含通道明文。当前范围不连接真实外部消息提供商。
<!-- bell-contact-schedule:end -->
+16 -2
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Product-Requirements
wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Product-Requirements.-
wiki_revision: 2b110cd34439aca8aef4bc509ba8b50655b18c0a
synchronized_at: 2026-08-31T07:24:22Z
wiki_revision: a2aada9db75909dc5fc85cc5d91c8c8bcab82c45
synchronized_at: 2026-09-01T04:09:23Z
<!-- gitea-wiki-mirror:end -->
# 产品需求
@@ -294,3 +294,17 @@ Brain 将内部匿名候选映射为标准事件;默认拓扑由 Sense 以机
Sense 的 `local_event.CreateWithOutbox` 是本地候选与标准事件 Outbox 的正式原子写入口;当前仓库尚无生产本地候选创建调用链,不把不存在的上游路径声明为已接通。真实客户 PKI、生产 PostgreSQL、现场网络与最终故障隔离由 #154/#155 验证。
<!-- standard-event-evidence-v1:end -->
<!-- bell-contact-schedule:start -->
## Bell 联系人和值班排班
Bell 的告警接收对象和值班安排由工单 #183 建立,目标是让管理员维护可审计、可验证且不泄露通道地址的通知基础数据。
- 联系人与通知通道分离管理;通道地址只以密文保存,API、操作日志和页面均不得返回或记录明文,只展示脱敏摘要。
- 通道“已启用”和“已验证”是两个独立状态;验证结果以只追加事实记录保存,不能用启用状态替代验证。
- 值班组成员必须是已启用联系人,发布前主值班与备值班必须是不同联系人,且均具有已启用、已验证的通知通道。
- 周排班使用 IANA 时区,必须覆盖完整一周且不允许时间空档或重叠;排班以版本发布,已发布版本不可修改。
- 临时替班作为只追加事实记录保存,不能覆盖或改写已发布历史,且同一排班版本内不得时间重叠。
- 普通操作员只读,管理员可维护与发布。
- 本范围只提供联系人、通道验证事实和值班排班基础能力,不执行真实外部通知;实际发送属于后续工单 #185。
<!-- bell-contact-schedule:end -->