Skip to content

功能授权 ​

License 控制整个部署可使用的功能,租户套餐控制租户可分配的菜单范围,账号权限控制具体操作。 功能授权矩阵由 shared/src/licensing/constants.ts 的功能项和中文标签派生,不扫描页面或数据库自动增加模块。

功能登记与模式 ​

当前有 16 个授权项。growth(运营中心)覆盖短链管理、渠道分析、营销活动及会员参与营销; iot(IoT 设备)覆盖设备管理后台。二者的菜单根分别是 17000、18000。 专业版签发预设包含 growth,企业版预设包含全部功能;IoT 不在社区版和专业版预设中。 签发时可用显式 --features 覆盖预设,运行时只看已签名载荷的 features[],版本名称不自动授予功能。

LICENSE_MODE行为
off全部功能可用,不检查 License
warn全部功能可用,未授权调用限流记录事件
required未授权调用返回 403;授权失效时关闭增值功能,核心能力保持可用

在宽限期内原授权功能保持可用。受限模式的状态响应返回空的有效功能列表, 原 License 的功能列表仍保留用于查看签发内容。

页面生成授权文件 ​

平台超级管理员可在「License 授权 → 生成授权文件」填写目标安装 ID、客户、版本预设、功能、有效天数、 宽限天数与配额,使用自行保管的 Ed25519 签发私钥下载 .zenlic 或复制文件内容。 版本只提供初始功能预设,实际授权仍以最终勾选的 features[] 为准。

签名在浏览器通过 Web Crypto 完成,需要 HTTPS 或 localhost 与支持 Ed25519 的浏览器。 私钥支持未加密的 PKCS8 Base64 和 PRIVATE KEY PEM;仅保存在本页签的组件状态中, 不进入表单提交、请求、持久化存储或会话回放。签发尝试结束、重置或切换页签后清空私钥。 生成的文件不会直接改变当前部署授权,仍需在目标部署的「激活」页签验证并安装。

签发方可继续使用 packages/server/scripts/license-issue.ts --gen-keys 生成自有密钥对, 将公钥配置到目标部署的 LICENSE_ISSUER_PUBLIC_KEY,保管私钥用于签发。目标安装 ID 默认带入当前部署的 ID, 向其他部署发证时应替换为该部署的 ID。签发密钥 ID 用于标识私钥;使用内置测试公钥的部署要求 test-2026。 页面和 CLI 复用同一套签发参数校验及载荷工厂,CLI 的原有离线签发方式继续可用。

新增模块 ​

  1. 在 licensing/constants.ts 登记功能键和中文标签,在 feature-catalog.ts 登记说明与 menuRoots。 新顶层菜单必须属于某个授权根,或在 CORE_MENU_ROOTS 明确登记为核心并说明原因; 新子菜单继承其根的分类。系统设置等核心容器中的授权子树可单独登记,授权根之间不能嵌套。

  2. 在路由域声明默认分类,例如:

    ts
    export default defineRouteDomain({
      name: 'marketing',
      licensing: { feature: 'growth' },
      mounts: () => [
        [marketingCampaignContract.basePath, marketingCampaignsRoutes],
        [memberMarketingContract.basePath, memberMarketingRoutes],
      ],
    });

    新挂载会自动获得域的 License 门控。核心域使用 licensing: { core: '基础能力的原因' }; 核心域中的授权子功能可在挂载上单独声明 { feature }。

  3. 在契约组默认值或操作上同步声明 feature,使独立挂载、操作元数据和契约路由保持一致。 后台令牌操作在认证后经 guard 校验;会员 / 设备等非后台凭证操作显式声明 feature 时, 在路由提供的凭证校验中间件之后执行门控。

  4. 当前迁移基线面向空库,不保留旧菜单分类兼容或历史回填迁移。重建数据库后执行迁移与 seed, 运营、IoT 及其子菜单和按钮直接按当前功能目录初始化正确的 featureKey。 具体重建流程见数据库与迁移。

  5. 检查签发预设、租户套餐和测试。已有许可证、已有租户套餐不会自动获得新增功能,需按实际购买结果重新签发或分配。

明确豁免的入口 ​

已有短链跳转、站点渲染、支付 / 微信回调、外部审批回调等持续服务入口保留原有可用性, 对应挂载使用 { licenseExempt: '原因' }。IoT 的设备 HTTP / WebSocket 接入也保留现有设备鉴权与持续接入行为; IoT 授权控制管理后台,不因后台 License 缺失中断在网设备接入。管理和会员营销 API 不属于这些豁免。 公开身份本身不等于豁免,例如网盘外链仍随网盘授权控制。

防漏检查 ​

  • 菜单装配拒绝未分类的新顶层入口、不存在 / 重复 / 重叠的授权根、断开的父节点和未覆盖菜单。
  • 路由域分类是必填字段,同时有运行时校验;新 API 自动继承授权,豁免原因不能为空。
  • app.contract.test.ts 检查每个授权项都有实际挂载门控,防止只增加矩阵标签。
  • License 模式、会员营销独立挂载和全局搜索过滤测试覆盖未授权拒绝、已授权放行和核心功能可用。

以上测试随 npm test 在 CI 执行;类型检查随 npm run lint 执行。新增模块后也应检查 授权状态接口、后台矩阵以及 required 模式的实际拒绝响应。

Built with VitePress for local documentation preview.