Skip to content
bitzorcas
中EN

Guide

Menu 安全、测试、运维与商业 GA

Menu 的认证授权边界、全局影响、测试证据、运行诊断、发布清单和源码事实驱动的商业 GA 缺口。

Last updated

Menu 已具备清晰的 owner、生成端点、权限目录、双 ORM store 和跨实例失效骨架;但树完整性、变更原子性、审计和运维恢复仍未达到商业 GA。

1. 安全模型

JWT authentication

Menu management endpoints

menus.menu.* resource authorization

navigation endpoint

role-to-module visibility

global SysModule mutation

display decision only

target endpoint authorization

管理端点必须同时认证并通过 create/update/delete/view 权限;navigation 只要求认证,然后按角色模块关系过滤。

2. 全局影响面

SysModule 不是租户表。任何管理写入都会改变全平台目录并清理全局菜单缓存 tag。角色授权关系虽然按租户解析,但结构、显示名、链接和启停是共享的。

因此 Menu 管理权限应被视为平台级高风险权限,不能等同普通租户后台配置权。

3. 显示过滤的安全边界

目标端点必须独立授权
// ① 导航接口只决定是否把入口展示给当前用户。
var navigation = await menus.GetNavigationAsync(currentUser, cancellationToken);
// ② 目标命令仍声明自己的资源与动作。
public sealed record ApproveInvoice(string InvoiceId)
: ICommand<Result>, IAuthorizedRequest
{
public ResourceDescriptor Resource { get; } = new("billing", "invoice");
public AuthorizationAction Action { get; } = AuthorizationAction.Approve;
}
// ③ 即使客户端手工调用 URL,授权管线也会再次决策。

不要把 LinkUrl 当成可信策略输入,也不要根据节点是否存在决定后端授权。

4. admin 短路风险

角色名 admin 直接获得全部启用目录可见性。这是应用层约定,不是显式 permission grant。角色命名、外部 IdP 映射或租户自定义角色可能意外触发它。

GA 方案应选择:使用平台级不可伪造声明、显式超级管理员 capability,或仍经 Authorization policy 决策;同时固定大小写、租户与审计语义。

5. 输入与链接安全

当前没有校验 LinkUrl 的 scheme、host、相对路径、开放重定向或 javascript: 等危险值,也没有校验 Icon。若前端直接渲染这些字段,必须由 UI 做严格编码和允许列表;更稳妥的是服务端在写入时强制相对内部路由。

Name/Description 也应按文本渲染,不能当 HTML 注入。

6. 已有自动化证据

测试当前证明
MenuQueryHandlerTestsdetail 命中与 not-found
MenuInfrastructureArchitectureTestsORM 中立、查询走 store、fail-closed adapter
AuthorizationMenuPersistenceOwnershipArchitectureTestsowner 行、窄端口、生成 model/seed manifest、迁移所有权
IdentitySeedDataTests菜单/权限种子引用与资产规则
FeatureDefinitionSeedStepTestsFeature 资产关联可解析
PortRepositoryParityTestsSqlSugar/EF Core store 行为一致
ApiShellHostBuildSmokeTests无数据库时 unavailable store

这些证据不覆盖树算法和写用例业务规则。

7. 必补测试金字塔

大量单元: visibility/tree/validators

集成: transaction/index/cache/outbox

契约: generated HTTP/auth/problem details

少量 E2E: multi-tenant/multi-instance/admin

优先补可重复、快速的算法测试,再用真实数据库和两实例环境固定基础设施语义。

8. 运行诊断

遇到“用户看不到菜单”时按顺序检查:

  1. 请求是否通过认证;
  2. ICurrentUser.User.Roles 是否为预期角色名;
  3. Authorization reader 是否返回匹配的模块 Code;
  4. SysModule Code 是否完全对应;
  5. 目标行与所有祖先是否 Enabled/未软删;
  6. 所有祖先是否在根可达路径;
  7. navigation 路径上的节点是否都 IsMenu=true;
  8. 当前实例是否持有旧缓存。

9. 缓存诊断示例

Terminal window
# 查同步消费者是否收到事件及资源 ID。
rg -n "Menu cache invalidated|Failed to invalidate menu cache" ./logs
# 源码核对 tag、TTL 和事件资源。
rg -n "MenuCacheTags|CachePolicy.Medium|LocalResourceTypes.Cache" src/Platform/Menu -g '*.cs'
# 数据库侧需同时检查 Code、ParentId、Enabled、IsMenu、IsDeleted。

当前消费者错误会被抑制;仅看到消息已消费不等于缓存失效成功。

10. 数据完整性巡检

生产巡检至少报告:空/重复 Code、空 Name、孤儿 ParentId、自引用、环、过深树、不可达启用节点、非菜单父节点下的菜单子节点、重复同级 OrderSort、危险 LinkUrl、授权关系引用缺失 Code。

巡检应只报告并提供修复计划,不应未经审批自动改写全局目录。

11. 发布前清单

  • 备份 SysModule 与角色模块权限关系;
  • 对比 seed 资产和数据库差异;
  • 验证九个端点的 401/403/成功矩阵;
  • 在每个支持 ORM 上运行 parity;
  • 用两个 API 实例验证广播失效;
  • 模拟 notifier 不可用与缓存异常;
  • 验证深树、环、孤儿的失败方式;
  • 验证链接只进入允许的内部路由;
  • 准备 Code 迁移与回滚脚本;
  • 发布后抽样普通用户、无角色用户和超级管理员。

12. 商业 GA 缺口

按优先级应补:

  1. 树写入 validator 与读侧环/深度保护;
  2. 事务化重父级、级联删除与确定性排序;
  3. Code 不可变或显式迁移工作流;
  4. URL/Name/Icon/Scope 完整校验;
  5. 数据库写与缓存事件的 outbox/重试;
  6. 事件 ResourceId 过滤和失败投递;
  7. 乐观并发与影响行数检查;
  8. 平台级管理审计、审批和回滚;
  9. 租户覆盖/本地化产品决策;
  10. consumer contract、双实例与故障注入门禁。

具体任务已写入 Architecture-Hub 的 Menu GA backlog,本文只陈述当前实现和验收方向。

13. 当前上线判断

在可信平台管理员、受控 seed、浅且无环目录、允许最多 15 分钟缓存兜底的内部场景,可有限使用。若对外提供租户自助配置、强审计、零陈旧或复杂树编辑,当前实现不应宣称 GA。

14. 全局扫描

Terminal window
# 当前测试证据。
rg -n "Menu" tests -g '*.cs'
# 环、事务、outbox、审计实现缺口;预期 Menu 源码无关键命中。
rg -n "visited|MaxDepth|UnitOfWork|Outbox|Audit" src/Platform/Menu -g '*.cs'
# 所有生成端点和授权请求。
rg -n "GenerateEndpoint|IAuthorizedRequest" src/Platform/Menu -g '*.cs'

模块总览 · 管理与缓存

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%