0.3.4 • Published yesterday
@cyte-editor/license
Licence
SEE LICENSE IN ./LICENSE
Version
0.3.4
Deps
0
Size
60 kB
Vulns
0
Weekly
0
@cyte-editor/license
CyteEditor 商业授权客户端 SDK — JWT 验签、域名/AppId 绑定、撤销同步、降级 fallback。
内部包:本 README 仅供 monorepo 内部开发参考,不发布到 npm 站点(npm 仅消费
dist/与公开元数据)。
定位
License Client SDK 是「Worker 颁发的 JWT」与「编辑器运行时」之间的唯一桥梁 —— 把一串字符串翻译成「客户能用哪些功能、能用多久、坏了怎么降级」的运行时决策。
设计原则详见 doc/launch/CyteEditor-Codebase-Refactor-Spec-v0.1.md §5。
当前实施进度
| 任务 | 状态 | 说明 |
|---|---|---|
| 2-12 | 包骨架(package.json / tsconfig / vite / vitest) | |
| 2-13 | verifyLicense / requireTier / getLicenseStatus 公共 API(payload 解码 + 字段校验 + 过期/domain/appId 判定 + 5 态状态机 + 事件订阅 + LicenseError) |
|
| 2-15 | 当前 | scripts/embed-public-key.mjs 构建期注入公钥(多 kid → PEM map 架构 + 指纹交叉校验 + placeholder 降级 + 幂等写入),生成 src/public-key.ts(gitignored) |
| 2-16 | 待办 | JWT ES256 验签(WebCrypto ECDSA P-256,替换 2-13 的"信任解码") |
| 2-17 | 待办 | IndexedDB 24h TTL 缓存 + 单调时间戳防回拨 |
| 2-18 | 待办 | 完整 7 态状态机(含 tamper_suspected 与防回退) |
| 2-19 | 待办 | 4 档校验模式(A 纯离线 默认 / B lazy / C strict+grace / D 硬件指纹) |
| 2-20 | 待办 | 反篡改 4 层(冗余校验 / 字符串拆分 / banner 法律证据 / 时间篡改防御) |
| 2-22 | 待办 | applyWatermark / applyReadonly 实际实现(集成层) |
2-13 当前阶段 verifyLicense 不做密码学验签(仅 base64url 解码 + 字段校验 + 过期判定),属 Spec §5.5 标准方案。禁止用于生产,待 2-16 完成 ES256 验签后方可上线。
公共 API
import {
verifyLicense,
requireTier,
getLicenseStatus,
getLicensePayload,
onLicenseEvent,
LicenseError,
} from '@cyte-editor/license'
// 1. 异步主入口(EditorManager 启动时调用)
const result = await verifyLicense({
key: 'eyJ...', // JWT token
appId: 'mycompany.app', // 可选:app_id 绑定校验
online: false, // 默认 A 档纯离线
})
// result: { valid, status, reason?, payload?, source, expiringSoonDays? }
// 2. 子包用:tier 同步守卫(不通过抛 LicenseError)
try {
requireTier('pro_business')
// ... Pro 功能代码
} catch (e) {
if (e instanceof LicenseError && e.reason === 'tier_insufficient') {
// 降级 / 引导升级
}
}
// 3. 状态查询(同步)
const status = getLicenseStatus() // 'valid' | 'expiring_soon' | 'expired' | ...
const payload = getLicensePayload() // LicensePayload | null(深拷贝)
// 4. 事件订阅
const unsubscribe = onLicenseEvent('license:expiring_soon', (e) => {
console.warn(`License expires in ${e.payload?.exp} days`)
})
unsubscribe()
体积预算
启动期目标:≤ 20 KB(gzip 前 minified 产物)。
| 阶段 | ESM | CJS | 占用 |
|---|---|---|---|
| 2-12 骨架 | 0.91 KB | 0.97 KB | 4.6% |
| 2-13 公共 API | 5.23 KB | 4.41 KB | 26.2% |
| 2-15 公钥嵌入 | 5.23 KB | 4.41 KB | 26.2%(public-key.ts 暂未被 SDK 主流程 import,2-16 验签上线后才纳入 bundle) |
| 预算上限 | 20 KB | 20 KB | 100% |
零运行时依赖;JWT 验签将使用 WebCrypto SubtleCrypto(2-16),无需 jose/jsonwebtoken。
构建 & 测试
pnpm --filter @cyte-editor/license build # 产出 dist/(前置自动跑 embed-public-key)
pnpm --filter @cyte-editor/license typecheck # TS 类型检查(前置自动跑 embed-public-key)
pnpm --filter @cyte-editor/license test # vitest run(含 24 用例:15 API + 9 公钥嵌入)
pnpm --filter @cyte-editor/license run embed-public-key # 单独跑公钥注入
公钥注入说明(2-15):本包构建/类型检查/测试入口均自动前置调用
scripts/embed-public-key.mjs,从仓库根keys/public.pem+keys/public.kid注入src/public-key.ts(该文件已 gitignored)。当keys/public.pem缺失(CI / 全新克隆)时脚本回退到 placeholder 模式,仅生成空骨架不阻塞 typecheck/test。