@gloablehive/license
v0.1.2
Published
Local license generation, validation and feature gating for OpenClaw — no SaaS dependency
Readme
@gloablehive/license
本地授权模块 — 零 SaaS 依赖的 License 发放、验证、功能开关
原理
运维/发放端 客户/Gateway
┌──────────────┐ license.json ┌──────────────────┐
│ CLI: issue │ ───────────────→ │ LicenseGuard │
│ HMAC 签名 │ │ boot() 校验签名 │
│ 功能+配额 │ │ isFeatureEnabled │
└──────────────┘ │ canSendMessage │
└──────────────────┘- 签名: HMAC-SHA256,篡改 license.json 任何字段都会校验失败
- 机器绑定: 可选,防止 License 拷贝到其他机器
- 宽限期: 过期后 7 天内降级为 free,超 7 天停服
- 无网络: 不需要 SaaS 后端,纯本地 JSON 文件
快速开始
安装
npm install @gloablehive/license发放 License (运维端)
# 设置签名密钥 (发放和验证必须用同一个)
export OPENCLAW_LICENSE_SECRET="your-secret-key"
# 查看可用套餐
npx openclaw-license plans
# 发放 basic 套餐, 365天有效
npx openclaw-license issue \
--merchant M001 \
--name "日本水果店" \
--plan basic \
--days 365 \
--output ~/.openclaw/license.json
# 绑定机器 (防拷贝)
npx openclaw-license issue \
--merchant M001 \
--name "水果店" \
--plan pro \
--bind-machine \
--output ~/.openclaw/license.json验证 License
npx openclaw-license verify --file ~/.openclaw/license.json
npx openclaw-license info --file ~/.openclaw/license.json
npx openclaw-license machine-id在代码中使用
import { LicenseGuard } from '@gloablehive/license';
const guard = new LicenseGuard(
'~/.openclaw/license.json',
process.env.OPENCLAW_LICENSE_SECRET!,
);
// Boot Gate — 启动时校验
const result = await guard.boot();
if (!result.valid) {
console.error('License invalid:', result.error);
process.exit(1);
}
// Feature Gate — 功能开关
if (guard.isFeatureEnabled('fts_search')) {
// 执行 FTS5 搜索
}
if (guard.isFeatureEnabled('multi_project')) {
// 允许多项目
}
// Quota Gate — 配额检查
const msgCheck = guard.canSendMessage();
if (!msgCheck.allowed) {
console.warn(msgCheck.reason); // "Daily message limit reached"
return;
}
// 记录用量
guard.recordMessage();
guard.recordTokens(1500);
// 查看用量
const usage = guard.getUsageSummary();
console.log(`今日消息: ${usage.dailyMessages}/${usage.quotas.dailyMessages}`);套餐对比
| Plan | 价格 | 项目 | Agent/项目 | 月Token | 日消息 | FTS5 | 向量 | 多项目 | |------|------|------|-----------|---------|--------|------|------|--------| | free | 0 | 1 | 4 | 10万 | 100 | ✅ | ❌ | ❌ | | basic | ¥99 | 3 | 6 | 100万 | 500 | ✅ | ❌ | ✅ | | pro | ¥299 | 10 | 无限 | 500万 | 无限 | ✅ | ✅ | ✅ | | enterprise | 定制 | 无限 | 无限 | 无限 | 无限 | ✅ | ✅ | ✅ |
安全
- 签名密钥: 通过
OPENCLAW_LICENSE_SECRET环境变量传入,发放端和客户端必须一致 - 防篡改: 修改 license.json 任何字段 → 签名校验失败
- 防拷贝:
--bind-machine绑定机器指纹 - 防过期: 7 天宽限期 → 降级 free → 完全停服
- 计时安全: 签名比较使用
crypto.timingSafeEqual防计时攻击
文件结构
license.json # License 授权文件
├── version: 1 # 格式版本
├── payload # 授权信息
│ ├── id # License UUID
│ ├── merchantId # 商户 ID
│ ├── merchantName # 商户名
│ ├── plan # 套餐等级
│ ├── features # 功能开关
│ ├── quotas # 配额限制
│ ├── issuedAt # 发放时间
│ ├── expiresAt # 过期时间
│ └── machineId # 机器指纹 (可选)
└── signature # HMAC-SHA256 签名
usage.json # 运行时用量 (自动生成)
├── dailyMessages # 今日消息数
├── monthlyTokens # 本月 Token 数
└── updatedAt # 最后更新后续: SaaS 联动
当 SaaS 后端就绪后:
license.json改为 SaaS 下发 (API:POST /api/license/issue)- 添加 24h 心跳刷新 (
POST /api/license/heartbeat) - 用量上报改为 5min 批量推送到 SaaS
- 本地逻辑完全不变,只是 License 来源从手动变成自动
