插件接口
RenMori 采用开放核心架构。开源的 renmori 命令行工具是集成点:它负责解析配置、准备输出目录与备份、驱动面向用户的流程,并始终内置基线容器格式。强保护部分,即逐构建多态引擎、运行时密钥派生以及原生核心与启动器,位于一个闭源插件之中,以预构建组件的形式分发,从不以源码形式分发。
本页定义二者之间稳定的进程契约。该契约是公开的,使开源工具与闭源插件能够各自独立地进行版本管理与发布;只有插件的实现是闭源的。
插件发现
开源工具按以下顺序定位插件:
renmori protect的--plugin <path>参数RENMORI_PLUGIN环境变量- 未找到插件:工具使用基线格式运行,并拒绝任何非基线的
strength
<path> 是一个可执行文件,或一个由开源工具以当前 Python 解释器运行的 .py 脚本。插件只有在 capabilities 握手(见下文)成功之后才会被使用;握手失败的插件视为不存在,转而使用基线路径。
当前版本的 CLI 在上述显式路径之外,还会查找本地缓存,并在需要时从公开 Release 下载插件、按 SHA256SUMS 校验后写入缓存。未设置 strength 时默认使用完整保护,若没有可用的插件则运行失败;--strength auto 在无插件时回退到基线;--strength baseline 从不下载插件。详见 闭源插件。
传输方式
每次调用都是一个短生命周期的子进程,第一个参数用于选择操作。需要请求体时,请求是 stdin 上的单个 JSON 对象;响应是 stdout 上的单个 JSON 对象。所有供人阅读的日志均写入 stderr,以保证 stdout 可被机器解析。成功时退出码为 0,失败时为非零值。所有字段名与枚举值均为 ASCII,且与区域设置无关。
请求与响应对象都携带一个整数字段 interface。开源工具发送其支持的最高版本,并拒绝 capabilities 中不包含该版本的插件。
操作
capabilities
无请求体。插件输出一个描述自身的 JSON 对象,并以 0 退出:
protect
stdin 上的请求对象:
插件将 source_dir 复制到 output_dir,把所有资源与 Ren'Py 脚本封入多态容器,为每个目标平台分发其原生核心(以及按请求分发启动器),写入运行时扩展,移除已封装的明文原件,然后在 stdout 上输出响应对象:
失败时,插件输出 {"interface": N, "status": "error", "message": "<reason>"} 并以非零值退出。开源工具会报告该消息,以其运行时失败退出码退出,并尽可能不留下不完整的 output_dir。
职责划分
- 开源工具负责:参数与
renmori.toml的解析、输出与备份的决策及其所涉及的复制或移动、执行前的摘要与确认、根据响应写出的构建清单,以及全部本地化输出 - 插件负责:容器格式及其逐构建随机化、密钥派生、原生核心与启动器,以及
output_dir下的最终磁盘内容
对插件而言,原地保护同样表达为一对普通的 source_dir → output_dir:开源工具先将原目录移开(移至备份目录,或移至事后丢弃的临时目录),再将原路径作为 output_dir 传入,因此插件无需支持原地模式。
版本与完整性
只有当请求或响应的结构发生破坏性变更时,interface 才会递增。一个插件可以同时支持多个版本,开源工具会选择双方共同支持的最高版本。新增的可选字段不会使版本号递增。
由插件产出的构建,应当能够与第三方使用开放框架加手写弱引擎拼装出的构建相区分:构建清单中可以携带一个由运行时校验的构建指纹。该绑定机制随闭源组件一同定义,不在本公开契约的范围之内。