# 在线租约与续租

> 了解 Infra 管理的租约申请、配额计算、授权期限，以及 chrovia.license API。

Source: https://console.getchrovia.com/zh/docs/sdk-leases

**租约（lease）**用于维持当前浏览器实例的在线授权，由 Chrovia Infra 自动续租。仅需要在线授权的 License 使用租约。

## 标准接入：保留 Chrovia Infra

安装浏览器时保留 `Extensions/chrovia-infra` 目录。普通 SDK 集成已由 Infra 负责申请和续租，你的插件不应再运行第二套续租循环。参见[插件安装](https://console.getchrovia.com/zh/docs/sdk-plugins)。

1. 为实例安装有效的 [License](https://console.getchrovia.com/zh/docs/sdk-license)。
2. 保持机器能够连接 Console，并确保 License 配额可用。
3. 保留 Chrovia Infra 并启动浏览器。它负责首次授权和续租，包括 Service Worker 唤醒后的续租。
4. 续租失败时按下方步骤排查，不要再启动一套续租循环。

只有官方签发的 `payload.noLease: true` License 才跳过该流程。删除 Infra 或断网不会将在线 License 变成离线 License。

## 当前时序与配额

| 项目 | 当前行为 |
| --- | --- |
| 启动宽限期 | 对需要租约的有效 License 提供 10 分钟 |
| 租约有效期 | 最长 60 分钟，Console 不会签发超过 License 到期时间的租约 |
| 定期续租 | Infra 每 50 分钟检查一次 |
| 临时故障重试 | Infra 在 1 分钟后重试 |
| 软宽限期 | 已接受的租约到期后再延续 5 分钟 |
| 终止性拒绝 | Infra 立即使进程授权失效，不保留剩余租约时间 |

这些间隔不保证机器休眠期间精确续租。授权失效时，浏览器显示 License 锁定提示：选择**是**暂时关闭提示，选择**否**退出浏览器。如果授权仍不可用，提示会再次出现。关闭提示不等于完成续租。

服务端每次成功签发消耗一小时配额，即使响应丢失或浏览器提前退出也一样。多个独立实例共享 License 配额。完全重启会生成新的实例身份，不能复用旧进程的租约。不要为了检查状态手动申请租约。月度计算方式见[计费与配额](https://console.getchrovia.com/zh/docs/commercial-license-billing)。

## 正确理解快照

```js
const state = await chrovia.license.get();
console.log({
  valid: state.valid,
  requiresLease: state.requiresLease,
  leaseExpiresAt: state.leaseExpiresAt,
});
```

| 字段 | 含义 |
| --- | --- |
| `valid` | License 加载成功，不是实时租约授权标志 |
| `requiresLease` | 是否需要在线租约 |
| `licenseId`、`instanceId` | 绑定申请及响应所用的标识 |
| `claimTimestamp`、`claimMac` | 申请租约时原样传递；每次申请获取新值，不要记录日志或复用 |
| `leaseExpiresAt` | 未来的续租截止时间或 `null`；首次申请前也可能是启动宽限期截止时间 |

状态响应不包含完整 License 或能力列表。API 对象存在也不能证明当前在线授权正常。应在 Console 的 License 详情中核对能力，并按下方续租排查步骤处理锁定提示。

## 手动租约 API

仅在集成需要替代 Infra 续租时使用，不要同时运行两套续租。向 `POST https://console.getchrovia.com/api/license/lease` 发送 `licenseId`、`instanceId`、`timestamp`、`mac`，使用刚获取的 `license.get()` 返回值（`claimTimestamp` → `timestamp`，`claimMac` → `mac`）。保持机器时间同步，并在申请租约的实例中将完整响应原样传给 `applyLease()`。

| API | 返回值 |
| --- | --- |
| `license.get()` | 快照 Promise，不续租 |
| `license.applyLease(lease)` | 快照 Promise；租约被拒绝时拒绝该 Promise |
| `license.invalidate(reason)` | 快照 Promise；将需要租约的进程标记为终止性未授权 |

`applyLease` 对非对象参数以 `DataCloneError` 拒绝 Promise，对无效、已到期或不兼容的租约以 `DataError` 拒绝。不要把租约保存为 `Chrovia License` 或 `Extended Preferences`。

`invalidate` 不是退出登录工具，也不是状态探测接口。终止性失效的进程不能靠再次 `applyLease` 恢复；需要解决服务端原因后完全重启。内核 API 没有 `renew()` 方法。

## 排查续租失败

检查 **Chrovia Infra 的 Service Worker**，不是自己的弹出窗口或网页控制台。错误日志前缀为 `Chrovia Infra: lease refresh failed`。核对实际安装的扩展、Console 主机权限、网络、系统时间及 Console 中的 License 卡片。

Infra 将 `expired`、`revoked`、`quota_exceeded`、`not_found` 视为终止性失败。网络错误和其他拒绝会安排重试，但宽限期有限。恢复网络可能修复临时到期；重启不能恢复已撤销或已到期的 License。配额重置后，需要重启因配额拒绝而终止性失效的进程。
