feat: 实现容量与配额安全闸 (#75)
This commit is contained in:
@@ -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: 3c95336ab96aa1e245f67c598299f2904f0e4437
|
||||
synchronized_at: 2026-08-27T11:07:58Z
|
||||
wiki_revision: 502d61f5c765c6c9b71432cdbbf0159c9b9c1071
|
||||
synchronized_at: 2026-08-28T03:50:51Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 架构与代码地图
|
||||
@@ -174,3 +174,44 @@ Bell 使用独立 PostgreSQL、JWT realm、token key 和首次迁移管理员环
|
||||
- `dev_scripts/harness.py sync` 只从 Gitea Wiki 导出 `wiki-docs.json` 映射的核心镜像;`sync --check` 只检查一致性。
|
||||
- `archive`、`export` 和 `export --all` 只在人工明确要求时处理可选任务快照,任务快照不进入核心映射。
|
||||
- `dev_scripts/wiki_docs.py` 负责 Gitea Wiki 读取、revision、镜像头、脏文件保护和安全路径校验。
|
||||
|
||||
<!-- sense-provisioning:start -->
|
||||
## Sense 批量开通代码入口
|
||||
|
||||
工单 #72 的领域代码位于 `Sense/server/app/sense/provisioning/`,GoAdmin JWT/Casbin/PermissionAction 路由注册在 `Sense/server/app/admin/router/sense_provisioning.go`,迁移位于 `Sense/server/cmd/migrate/migration/version/2026082809000_provisioning.go`。前端页面为 `Sense/ui/src/views/sense/provisioning/index.vue`,API 封装为 `Sense/ui/src/api/sense/provisioning.js`;页面复用 BasicLayout、动态菜单、Axios、Element Plus Steps/Upload/Form/Table/Pagination/Dialog/Tag/Alert/Button 和权限指令。
|
||||
|
||||
PostgreSQL 表 `sense_provisioning_batches` 保存幂等键、配额快照和汇总状态,`sense_provisioning_items` 保存行号、设备信息、逐项状态、失败原因、尝试次数和已建立的设备引用;两表都没有凭据字段。执行链按条目条件领取 ready/failed 状态,调用既有 Device、Credential Vault 与 Admission 服务,成功项不整体回滚。API 根路径为 `/api/v1/provisioning/batches`,覆盖创建/预校验、列表、详情、执行、失败项重试、单项重试和无秘密 CSV 导出。
|
||||
<!-- sense-provisioning:end -->
|
||||
|
||||
<!-- sense-local-events:start -->
|
||||
## Sense 本地事件只读链路
|
||||
|
||||
- 内部模型、DTO、服务、API 与合成夹具:`Sense/server/app/sense/local_event/`。
|
||||
- GoAdmin 路由:`Sense/server/app/admin/router/sense_local_event.go`,仅开放 `GET /api/v1/local-events` 和 `GET /api/v1/local-events/:id`。
|
||||
- PostgreSQL 表:`sense_local_event_candidates`;迁移同时建立“本地事件”菜单、详情功能权限和 implementation_operator/site_admin/viewer 的只读 Casbin 策略。
|
||||
- go-admin-ui 页面:`Sense/ui/src/views/sense/local-event/index.vue`;复用 BasicLayout、Element Plus 表单、表格、分页、Dialog、Tag、权限指令与 Axios 封装。
|
||||
- API 响应只包含 Sense 内部候选、匿名源引用、规则引用、证据状态和保留信息,不包含 Bell/Brain schema 或送达字段。页面上的 Bell 送达状态固定解释为“不适用”,避免把本地候选冒充外部预警。
|
||||
- 列表和详情成功/失败读取会同步写入脱敏的 `sys_opera_log`,不依赖可关闭的全局数据库日志开关;记录只含动作、路由、操作者、结果和候选 ID,不保存筛选值、响应或证据内容。拒绝访问继续由认证/RBAC 身份审计记录。
|
||||
<!-- sense-local-events:end -->
|
||||
|
||||
<!-- sense-operations:start -->
|
||||
## Sense 运维中心代码路径
|
||||
|
||||
- 后端入口:`Sense/server/app/admin/router/sense_operations.go`。
|
||||
- 领域投影:`Sense/server/app/sense/operations/`,只读聚合 `sense_devices`、`sense_admission_results` 和 `sense_media_routes`,不建立第二套运维状态表。
|
||||
- API:`GET /api/v1/operations`、`GET /api/v1/operations/:id`、`POST /api/v1/operations/:id/retry`;均复用 GoAdmin JWT、Casbin、PermissionAction 和响应封装。
|
||||
- 设备重试先用版本 CAS 取得在途所有权,再调用既有 admission Probe;失败时释放在途闸。媒体重试以 CAS 写入 `retry_pending` 和到期时间,由既有 MediaMTX 对账循环执行。
|
||||
- 前端:`Sense/ui/src/views/sense/operations/` 与 `Sense/ui/src/api/sense/operations.js`,复用 BasicLayout、Element Plus 表单、表格、分页、Dialog、Tag 和权限按钮。
|
||||
- 本模块不导入 Brain/Bell 模型,不访问其数据库,不定义共享契约。
|
||||
<!-- sense-operations:end -->
|
||||
|
||||
<!-- sense-quota:start -->
|
||||
## Sense 容量与配额代码路径
|
||||
|
||||
- 领域模型、DTO、服务、API 与测试:`Sense/server/app/sense/quota/`。
|
||||
- GoAdmin 路由:`Sense/server/app/admin/router/sense_quota.go`;API 为 `GET /api/v1/quota` 和 `PUT /api/v1/quota`,复用 JWT、Casbin、PermissionAction 和 GoAdmin 响应封装。
|
||||
- PostgreSQL 表:`sense_quota_settings` 保存单行配置与版本,`sense_quota_changes` 保存不可变变更记录。迁移 `2026082812000_quota.go` 初始化默认 16、动态菜单、最小权限及设备启用权限。
|
||||
- 设备新增和重新启用由 `quota.WithAvailableSlot` 在事务内锁定配置行、计算非停用设备占用并执行写入;设备服务与批量开通服务共用该事实源。
|
||||
- 前端:`Sense/ui/src/views/sense/quota/` 与 `Sense/ui/src/api/sense/quota.js`;复用 BasicLayout、Axios、Element Plus Alert/Row/Progress/Form/Table/Pagination/Dialog/Tag/Button 和权限指令。
|
||||
- 本模块不导入 Brain/Bell 模型,不访问其数据库,也不定义跨项目配额契约。
|
||||
<!-- sense-quota:end -->
|
||||
|
||||
@@ -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: 96fca4d2aa411725282bd3911c133efc75f7146a
|
||||
synchronized_at: 2026-08-27T09:04:59Z
|
||||
wiki_revision: f7a08ae4eaa7557f2b8a470d895b06567f77d0e1
|
||||
synchronized_at: 2026-08-28T03:51:05Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 业务规则与术语
|
||||
@@ -154,3 +154,37 @@ synchronized_at: 2026-08-27T09:04:59Z
|
||||
- Gitea Wiki 只保存长期有效的项目事实;核心页面由 `wiki-docs.json` 显式映射。
|
||||
- `docs/task/` 是按人工明确要求形成的专项或历史兼容快照,可能不完整或不是最新状态,不得替代工单。
|
||||
- 默认不创建、导出或更新任务快照;导出过程不自动删除本地历史文件。
|
||||
|
||||
<!-- sense-local-events:start -->
|
||||
## Sense 本地事件候选规则
|
||||
|
||||
- “本地事件候选”是 Sense 内部匿名记录,不是 Bell Event 或 Alert;任何跨项目输出必须等待版本化协调契约。
|
||||
- 候选状态与证据状态是两组独立状态,不能用证据成功推断事件已确认,也不能用事件已确认推断证据成功。
|
||||
- 列表和详情只读;新增、确认、删除、重试或送达不属于本页面。
|
||||
- 每条记录保存明确的 `retain_until`,页面展示实际到期时间;保留时长由服务端生产者/策略决定,页面不虚构全局固定天数。
|
||||
- 合成夹具只由测试显式装载,生产启动和迁移都不会自动写入假事件。
|
||||
- GET 列表和详情继续经过 Sense JWT、Casbin RBAC、数据权限中间件及系统操作审计。
|
||||
<!-- sense-local-events:end -->
|
||||
|
||||
<!-- sense-operations:start -->
|
||||
## Sense 运维状态规则
|
||||
|
||||
- 运维问题是设备、媒体或本地推理适配器的本地状态,不是 Event 或 Bell Alert;不得进入 Bell 业务预警队列。
|
||||
- 问题必须同时保留期望态、实际态、差异、建议动作、对象版本和安全闸;退避问题还要展示下次重试时间。
|
||||
- 设备认证失败和时间漂移复用既有视频接入探测;媒体失败复用既有 MediaMTX 对账循环。
|
||||
- 受控重试必须校验对象版本并防止同一对象并发执行;实施/运维和站点管理员可执行,viewer 只读。
|
||||
- 孤儿媒体路由只能显示“隔离待确认”,不得从运维中心自动删除。
|
||||
- Brain 未配置或未安装时显示本地推理 unavailable,不读取 Brain 数据库,也不阻断设备/媒体运维。
|
||||
<!-- sense-operations:end -->
|
||||
|
||||
<!-- sense-quota:start -->
|
||||
## Sense 容量与配额规则
|
||||
|
||||
- 配额是 Sense 单产品的交付配置,不是单机性能承诺;默认初始化为 16 路,数据库、循环、分页和列表容量不得以 16 为硬上限。
|
||||
- 配额占用按非停用设备计算:已接入和待接入各占用一路,停用设备不占用;重新启用必须重新经过配额安全闸并回到待接入状态。
|
||||
- 设备新增、重新启用及批量开通写入必须使用同一 PostgreSQL 配额事实源。写事务锁定单行配额配置、读取当前占用、检查剩余量后再写设备,防止并发超配。
|
||||
- 配额缺失、非法或读取失败时,新增、启用和批量相关写入必须拒绝;已有设备、视频流和只读查询继续可用。
|
||||
- 降低配额到当前占用以下不会自动停用设备或中断视频;剩余量按 0 显示,后续新增/启用持续拒绝,直到占用回到配额内。
|
||||
- 32/64/128 只展示当前配置和目标硬件性能测试状态。未验证不得解释为支持或稳定承载承诺。
|
||||
- 配额调整必须记录旧值、新值、操作人、时间和原因;viewer 与实施/运维角色只读,只有站点管理员可调整配额和重新启用设备。
|
||||
<!-- sense-quota:end -->
|
||||
|
||||
@@ -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: e912a1ca1410e01680a0f11f6199ccb42cd8fe8f
|
||||
synchronized_at: 2026-08-27T09:06:08Z
|
||||
wiki_revision: e298b5a31fcc39e3e2d9b4df543a4bc50d94bcaa
|
||||
synchronized_at: 2026-08-28T03:53:13Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 产品需求
|
||||
@@ -190,3 +190,37 @@ YoVision 首个可交付目标是在民办寄宿学校以默认 16 路高风险
|
||||
- Sense 账号不能登录 Bell,Bell 账号不能登录 Sense。
|
||||
- 三个项目独立构建、测试和版本化;Sense/Bell 独立迁移、备份、恢复和打包。
|
||||
- 集成断开不阻断各自核心能力,恢复后按 Outbox 和幂等收据继续。
|
||||
|
||||
<!-- sense-provisioning:start -->
|
||||
## Sense 批量开通长期规则
|
||||
|
||||
SEN-004 已在工单 #72 实现、合入 `dev` 并通过用户验收。Sense 可独立导入 CSV/XLSX 摄像头清单,服务端预校验地址、重复项和剩余配额,再按条目执行接入。批次保留创建时的配额与占用快照,但新的批次与设备写入必须读取 SEN-011 的统一配额事实源;16 不是数据库、循环、分页或单机容量硬上限。
|
||||
|
||||
导入清单禁止账号和密码字段。ONVIF/RTSP 凭据只在受控表单与单次执行请求中短暂存在,随后进入既有加密 Vault;批次、条目、响应、日志和结果导出都不得包含凭据。批次允许部分成功,成功设备不因其他条目失败而回滚;批量重试与单项重试只领取失败条目,并通过批次幂等键、持久化设备引用和条件状态更新避免重复创建设备。
|
||||
<!-- sense-provisioning:end -->
|
||||
|
||||
<!-- sense-local-events:start -->
|
||||
## Sense 本地事件候选
|
||||
|
||||
SEN-008 在 Sense 内提供只读的本地事件候选查询。网管或非技术人员可按发生时间、候选状态、证据状态、规则引用和关键词筛选,查看候选详情、证据处理结果与逐条保留到期时间。
|
||||
|
||||
候选状态只表示 Sense 内部的 `candidate`(候选)或 `confirmed`(已确认事件);证据状态独立表示 `pending`(处理中)、`success`(成功)或 `failed`(失败)。本能力在 Brain、Bell 均未启动时仍可使用。本地候选不是跨项目事件契约,不等同于 Bell Alert,也不表示已经向 Bell 送达。
|
||||
<!-- sense-local-events:end -->
|
||||
|
||||
<!-- sense-operations:start -->
|
||||
## Sense 运维中心
|
||||
|
||||
SEN-009 由 Sense 独立提供设备、媒体和可选本地推理的运维概览。页面以“期望态—实际态—未收敛差异—下一步动作”展示认证失败、退避等待、时间漂移、孤儿安全闸和能力未安装,面向网管或非技术运维人员,不暴露凭据或内部数据库结构。
|
||||
|
||||
运维中心在 Brain、Bell 均未启动时可用。本地推理适配器尚未建立协调契约时显示 unavailable;该状态不导致页面失败。所有问题均为 Sense 运维事实,不等同于 Bell 业务 Alert,也不会从本页面发送给 Bell。
|
||||
|
||||
读取默认只读。受控重试仅对明确可重试的设备/媒体问题开放,必须通过 RBAC、对象版本和在途状态校验并写入脱敏审计。孤儿媒体资源只隔离和提示,不提供自动删除。
|
||||
<!-- sense-operations:end -->
|
||||
|
||||
<!-- sense-quota:start -->
|
||||
## Sense 容量与配额长期规则
|
||||
|
||||
SEN-011 将默认 16 路实现为可配置的 Sense 本地交付配额。统一配置保存在 PostgreSQL;新增设备、重新启用和批量开通在写事务内原子校验。配额不可读时拒绝这些写入,但已有设备、视频流和读取保持可用。降低配额不会自动停用现有设备。
|
||||
|
||||
容量页面只展示 16/32/64/128 的当前配置和性能测试状态。除已经验证的 16 路学校试点基线外,其余档位在完成目标硬件压测前都不得解释为单机承载承诺。
|
||||
<!-- sense-quota:end -->
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Deployment-and-Operations
|
||||
wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Deployment-and-Operations.-
|
||||
wiki_revision: 367c6aed6eaeece793622431c7d1b11b1b9dbec5
|
||||
synchronized_at: 2026-08-27T09:07:20Z
|
||||
wiki_revision: 95965345e43d7fc403486c8afaecf36d79b757d0
|
||||
synchronized_at: 2026-08-28T03:53:21Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# YoVision 部署与运维
|
||||
@@ -80,3 +80,15 @@ Sense\start_sense.bat
|
||||
- MediaMTX 启用时进程、路径和播放链路状态可定位。
|
||||
- Supervisor 不会与手工进程重复占用端口。
|
||||
- 日志和文档没有秘密;未验证的 Brain、Bell、真机或生产行为明确标注。
|
||||
|
||||
<!-- sense-provisioning:start -->
|
||||
## Sense 批量开通与容量配额配置排错
|
||||
|
||||
数据库迁移 `2026082812000_quota.go` 首次创建统一配额配置:读取当次迁移进程的可选 `SENSE_PROVISIONING_QUOTA` 正整数作为初值,未设置或无效时使用 16。迁移完成后,运行期配额以 PostgreSQL `sense_quota_settings` 为事实源,并由“容量与配额”页面受控调整;后续修改环境变量不会覆盖数据库值。每个批量开通批次仍记录创建时的配额与占用快照。
|
||||
|
||||
升级后看不到“容量与配额”时,确认迁移成功并重新登录刷新动态菜单。implementation_operator、site_admin、viewer 可读取容量;只有 site_admin 可调整配额和重新启用设备。调整必须填写原因。降低配额不会停止已有流;当占用达到或超过配额时,新增和启用返回冲突。
|
||||
|
||||
页面显示“配额配置不可读取”时,先确认 `sense_quota_settings` 的 ID 1 记录存在、limit 为 1–100000 的整数且数据库可读;不要通过手工插入设备绕过安全闸。配置不可读时已有流和查询应继续,新设备、重新启用和批量开通写入会返回服务不可用。32/64/128 的“未验证”状态不能作为容量承诺。
|
||||
|
||||
批量导入被拒绝时还应检查模板只含 line_number/name/location/address,地址必须为不带账号、查询参数或片段的 HTTP(S) ONVIF 地址。条目失败时按页面原因检查网络、获准网段、凭据和接入状态;仅重试失败项,不删除已成功设备。日志、导出和问题记录不得粘贴摄像头凭据。
|
||||
<!-- sense-provisioning:end -->
|
||||
|
||||
Reference in New Issue
Block a user