> For AI agents: the complete documentation index is available at https://renmori.mewbaka.cn/llms.txt, the full documentation bundle is available at https://renmori.mewbaka.cn/llms-full.txt.

# 保护强度与闭源插件

RenMori 采用开放核心架构。开源的 `renmori` CLI 负责封包、校验与 CI 集成，并内置一套固定的开源基线格式；完整强度的保护由闭源原生插件提供。插件本身是免费的预编译二进制，闭源的只是其源码。

## 两种保护强度

| 项目       | 基线保护                         | 完整保护                        |
| -------- | ---------------------------- | --------------------------- |
| 启用方式     | `--strength baseline`        | 默认，或 `--strength` 指定插件声明的强度 |
| 是否需要插件   | 否，不下载、不调用                    | 是，首次使用时自动下载                 |
| 容器格式     | 固定、公开的容器格式 v1                | 每次构建随机化的多态格式                |
| 密钥       | 每次构建生成或从环境变量读取，以明文写入加载器扩展    | 由插件在运行时派生，磁盘上不保存明文密钥        |
| 脚本层      | 已编译脚本使用独立脚本密钥再加密             | 由插件执行，包括逐构建的 AST 编码变换       |
| 原生核心与启动器 | 无                            | 原生核心；可选原生启动器（`--launcher`）  |
| 离线运行     | 始终可以                         | 插件缓存后可以                     |
| 可防御      | `unrpa`、`unrpyc` 等现成解包与反编译工具 | 现成工具，以及针对单一格式编写的通用解包器       |
| 适用场景     | 开发调试、完全离线环境、无法使用插件的情况        | 正式发行                        |

:::warning
基线格式的容器结构公开，密钥与读取器以明文随游戏分发。它能使现成工具失效，但面对有针对性的攻击者并不构成真正的保护。正式发行请使用完整保护。两者的威胁模型参阅 [威胁模型](https://renmori.mewbaka.cn/technical/threat-model.md)。
:::

## 强度的确定方式

| `--strength` 或 `strength` | 插件可用            | 插件不可用             |
| ------------------------- | --------------- | ----------------- |
| 未设置                       | 使用插件声明的最强强度     | 以退出码 2 失败，不会退化为基线 |
| `baseline`                | 不使用插件，使用基线      | 使用基线              |
| `auto`                    | 使用插件声明的最强强度     | 使用基线              |
| 其他取值                      | 插件支持该取值时使用，否则失败 | 以退出码 2 失败         |

默认行为宁可失败也不自动退化，是为了避免在未察觉的情况下发布只有基线强度的构建。需要“有插件时使用完整保护、否则使用基线”的行为时，请显式指定 `auto`。

## 插件的获取顺序

需要插件时，`renmori` 按以下顺序查找，使用第一个可用的结果：

1. `--plugin PATH` 指定的文件
2. 环境变量 `RENMORI_PLUGIN` 指定的文件
3. 本地缓存中的插件
4. 从公开 Release 自动下载

指定的路径不存在时，会在 stderr 中提示并继续后续步骤。设置 `RENMORI_NO_DOWNLOAD` 时跳过第 4 步。

## 自动下载

### 平台与文件

| 运行 `renmori` 的平台 | 下载的文件                        |
| ---------------- | ---------------------------- |
| Windows x64      | `renmori-plugin-win-x64.exe` |
| Linux x64        | `renmori-plugin-linux-x64`   |
| macOS Apple 芯片   | `renmori-plugin-mac-arm64`   |
| macOS Intel      | `renmori-plugin-mac-x86_64`  |

插件按运行 `renmori` 的平台选择，与游戏的目标平台无关；目标平台由 `--platforms` 或自动检测决定。上表之外的平台没有可下载的插件，只能使用 `--plugin` 指定，或使用基线保护。

### 下载流程

1. 确定下载地址：默认为 `https://github.com/MewBaka/RenMori/releases/download/<tag>/`，`<tag>` 默认为当前版本内置的插件标签，可由 `RENMORI_PLUGIN_TAG` 覆盖；设置 `RENMORI_PLUGIN_BASE_URL` 时改为从该地址下载
2. 确认：交互式终端下提示 `完整保护需要闭源插件。从下面下载 <文件>？[Y/n]`，回答 `n` 或 `no` 时放弃下载；CI、非交互环境、`--quiet` 或 `-y` 时直接下载
3. 获取同一地址下的 `SHA256SUMS`，查找对应文件的校验值；找不到对应条目时放弃
4. 下载插件文件，计算 SHA-256 并与 `SHA256SUMS` 比对；不一致时丢弃文件并提示“下载的插件校验不通过”
5. 先写入临时文件，再原子地替换到缓存路径；在 macOS 与 Linux 上设置可执行权限

任一步骤失败时插件视为不可用：未设置强度时命令失败，`auto` 时回退到基线。

### 缓存位置

| 平台          | 缓存目录                                                                           |
| ----------- | ------------------------------------------------------------------------------ |
| Windows     | `%LOCALAPPDATA%\renmori\plugin\<tag>\`                                         |
| macOS、Linux | `$XDG_CACHE_HOME/renmori/plugin/<tag>/`，未设置时为 `~/.cache/renmori/plugin/<tag>/` |

缓存按 Release 标签分目录保存，升级 `renmori` 或修改 `RENMORI_PLUGIN_TAG` 后会使用对应标签的新目录。删除缓存目录即可强制重新下载。

## 环境变量

| 环境变量                      | 作用                               |
| ------------------------- | -------------------------------- |
| `RENMORI_PLUGIN`          | 使用指定路径的插件，跳过缓存与下载，等同于 `--plugin` |
| `RENMORI_NO_DOWNLOAD`     | 设置为任意非空值时从不下载；仍会使用已有的缓存          |
| `RENMORI_PLUGIN_BASE_URL` | 从该地址获取插件与 `SHA256SUMS`，适用于内网镜像   |
| `RENMORI_PLUGIN_TAG`      | 指定 Release 标签，同时决定缓存子目录          |

## 离线与内网环境

- **预先缓存**：在可联网的机器上执行一次完整保护，将缓存目录复制到离线机器的相同位置
- **固定路径**：将插件文件放在构建机上，通过 `RENMORI_PLUGIN` 或 `--plugin` 指定
- **内网镜像**：在内网服务器上同时提供插件文件与 `SHA256SUMS`，通过 `RENMORI_PLUGIN_BASE_URL` 指向该地址
- **禁止联网**：设置 `RENMORI_NO_DOWNLOAD=1`，确保构建过程不发起任何网络请求

在 CI 中缓存插件的方法参阅 [CI 集成](https://renmori.mewbaka.cn/integration/ci.md)。

## 能力握手

使用插件之前，`renmori` 以 `capabilities` 子命令调用插件，读取其返回的 JSON，其中包括插件支持的接口版本与可用强度列表。以下情况下插件视为不可用：

- 插件无法执行、返回非零退出码，或 30 秒内没有响应
- 返回内容不是有效的 JSON
- 接口版本低于 `renmori` 所需的版本，此时 stderr 中会提示 `plugin interface … unsupported`

握手成功后，`renmori` 以 `protect` 子命令调用插件，通过 stdin 传入包含源目录、输出目录、强度、平台、启动器、排除列表、分块大小与锁定设置的请求 JSON，并从插件 stdout 的最后一行读取结果；插件的进度信息直接输出到 stderr。插件以 `.py` 结尾时由当前 Python 解释器运行，否则直接执行。

开源工具与闭源插件之间的完整进程接口参阅 [开源与闭源组件的接口](https://renmori.mewbaka.cn/technical/plugin-interface.md)。
