# iKuai 4.0 扩展体系统一方案

## 1. 背景

熊哥在设计4.0时就想所有高级功能模块化安装。裴总也不希望OSPF这些功能固化在系统里——太大了，不适合。4.0里PMD已经没有前端了，前端全是AppMarket。需要统一后端，复用前端。

## 2. 现状分析（基于源码）

### 2.1 三个仓库的关系

| 仓库 | 角色 | 语言 | 说明 |
|------|------|------|------|
| cst/docker-app | AppMarket服务端+包仓库 | Shell+Go | ipkg包仓库+签名工具+签名私钥 |
| service-group/ik_update_client_src | PMD设备端daemon | C | 包管理+进程监控+在线更新+自更新 |
| service-group/ik_remote_control2 | PMD服务端(ik_rc) | C | REST API+RPC+router_list+mgnt |

### 2.2 AppMarket体系

**设备端**（rootfs/usr/ikuai/）：
- `function/appmarket`（Shell 3166行）：前端+后端一体
- `script/appmarket.sh`：启动脚本
- `script/sec/applist_control.lua`：与ICC云端通信，API: `/api/v1/device/plugins`
- `etc/defaults/appmarket.conf`：SQLite表结构（applist + app_task_queue）

**服务端**（cst/docker-app）：
- `apps/`：Docker应用包仓库
- `native-apps/`：原生应用包仓库（ddns-go, adguardhome, clash, cloudflared...）
- `signing/`：签名工具+RSA3072密钥对
- `tools/devspace-keygen/`：Go写的密钥工具

**包格式**（.ipkg）：
```
app_name/
├── manifest.json          # 包信息+完整性校验
├── manifest.json.sig      # RSA3072签名
├── app/bin/{arch}/        # 二进制
├── scripts/
│   ├── PRE_INST.sh
│   ├── start.sh
│   ├── stop.sh
│   ├── POST_INST.sh
│   ├── PRE_UNINST.sh
│   └── POST_UNINST.sh
└── ui/                    # 前端页面
```

**manifest.json结构**：
```json
{
  "name": "qemu-guest-agent-amd64",
  "version": "1.0.1",
  "type": "0",              // 0=原生 1=Docker
  "maintainer": "...",
  "requirements": {
    "memory": "16MB",
    "storage": "16MB",
    "os_min_version": "4.0.306"
  },
  "integrity": {
    "algorithm": "sha256",
    "signature_algorithm": "rsa-3072-sha256",
    "signature_file": "manifest.json.sig",
    "files": [{"path": "...", "sha256": "..."}]
  },
  "arch": "amd64"
}
```

**签名验证流程**（设备端 appmarket function line 344-450）：
1. openssl dgst -sha256 -verify pubkey -signature manifest.json.sig manifest.json
2. 逐文件sha256sum校验
3. 通过后才执行PRE_INST → start → POST_INST

**降级拦截**（line 1334）：
```bash
if [ "$(Version $current_version)" -ge "$(Version $new_version)" ]; then
    continue  # 跳过，不安装
fi
```

### 2.3 PMD体系

**设备端**（ik_update_client_src，编译产物=pmd）：
- 版本：1.1.8（ik_update_client_src）vs 1.2.0（ik_pmd/src）— 同一项目不同版本
- C daemon，约15个源文件
- 核心能力：
  - `routine.c`：login() → query() 30秒轮询 → report()上报状态
  - `package.c`：包下载、AES-128/256-CBC解密、安装、卸载
  - `monitor.c`：进程监控，60秒探测，异常重启
  - `db.c`：JSON+AES加密本地DB（/etc/log/.__DB），写/tmp再sync到/etc/log
  - `update_msg.c`：ikstd_prot加密通信协议
  - 自更新：SIGUSR1 → do_reload_binary，先卸载旧版再安装新版
- 服务器地址（routine.c line 341-360）：
  - 命令行 -s 参数
  - /etc/pmd.d/pmd_host 文件（OEM定制用）
  - fallback: `pkgmgr-v4.ikuai8.com:1864`（硬编码 DEF_SERVER_HOST1/2）
  - OEM flag=true时: `127.0.0.1:1863`
- 包格式：JSON描述（name/version/md5/encryption/secret_key/secret_iv/urls/download）
- 签名：AES对称加密 + MD5校验（弱于AppMarket的RSA3072）

**服务端**（ik_remote_control2，编译产物=ik_rc）：
- C daemon，基于libevent
- REST API（rest.c）：handle_sget/handle_spatch（服务状态查询/更新）
- RPC服务（rpcs.c）：管理router_list，处理设备连接
- mgnt.c：主备切换、权重管理、curl健康检查
- router_list.c：设备注册/注销、上下行计数
- proc.c：CPU/内存采样
- task.c：任务队列
- Docker部署（Ubuntu 16.04容器）
- 作者：xpfeng@ikuai8.com

### 2.4 功能固化现状

| 功能 | 源码位置 | 固化方式 | 组件化难度 |
|------|----------|----------|------------|
| OSPF | frr-reload-c(C) + ospf.sh + frr二进制 | rc脚本 boot_load_sync | 中——需打ipkg包 |
| GRE | gre_tunnel.sh | rc脚本 | 低——纯脚本 |
| IPsec | shell+二进制 | rc脚本 | 中 |
| Docker | plugins/docker/ | install.sh（已有组件化雏形） | 低——已有install.sh |

### 2.5 问题总结

1. **两套后端并行**：AppMarket(Shell)管Docker+原生应用，PMD(C daemon)管二进制包
2. **签名机制不一致**：AppMarket用RSA3072+SHA256，PMD用AES+MD5
3. **PMD没有前端**：4.0里PMD前端已移除，设备上只剩C daemon
4. **PMD服务端(ik_rc)**：有完整的设备管理REST API+RPC+主备，但和AppMarket服务端(docker-app仓库)是独立的两套
5. **OSPF/GRE/IPsec固化**：裴总不希望，熊哥也想模块化

## 3. 目标

**统一后端，复用前端**

- AppMarket前端不动（已有完整UI+交互）
- 后端统一：AppMarket(Shell)负责安装/签名/完整性，PMD(C daemon)负责进程监控/在线更新/自更新
- OSPF等OS组件打成ipkg包，通过AppMarket安装，PMD监控
- 签名统一用RSA3072+SHA256

## 4. 技术路径

### 4.1 分工：AppMarket后端 + PMD后端各管什么

```
AppMarket前端（不动）
  │
  ├── 安装/卸载/升级 → AppMarket后端(Shell)
  │   ├── 包格式：ipkg + manifest.json
  │   ├── 签名验证：RSA3072 + SHA256
  │   ├── 降级拦截：Version比较
  │   └── 脚本流程：PRE_INST → start → POST_INST
  │
  ├── 进程监控/自更新/在线检查 → PMD后端(C daemon)
  │   ├── 30秒query服务器轮询
  │   ├── 60秒进程探测+异常重启
  │   ├── SIGUSR1自更新
  │   └── 4.0消息队列通知
  │
  └── 离线安装 → AppMarket本地上传 + RSA验证
```

### 4.2 接口层：PMD暴露API给AppMarket调用

PMD C daemon暴露本地Unix socket或HTTP接口，AppMarket Shell调用：

| 接口 | 方向 | 功能 |
|------|------|------|
| `/list` | AppMarket→PMD | 获取PMD管理的包列表 |
| `/status?name=xxx` | AppMarket→PMD | 查询包运行状态 |
| `/install?name=xxx` | AppMarket→PMD | 触发安装 |
| `/uninstall?name=xxx` | AppMarket→PMD | 触发卸载 |
| `/monitor?name=xxx&action=start/stop` | AppMarket→PMD | 启停进程监控 |
| `/update_check` | AppMarket→PMD | 触发在线更新检查 |
| 通知事件 | PMD→AppMarket | 包更新/异常通知（通过4.0消息队列） |

PMD已有`/tmp/pmd_progress.sock`（Unix socket, main.c line 457），扩展它就行。

### 4.3 OSPF作为第一个组件化试点

当前OSPF组成：
- `frr-reload-c`（C，packages/ik_apps/frr-reload-c/）
- `ospf.sh` + `ospf` function（rootfs/usr/ikuai/）
- frr二进制（zebra/ospfd/staticd）

打成ipkg包：
```
ospf/
├── manifest.json
├── manifest.json.sig
├── app/bin/{arch}/
│   ├── zebra
│   ├── ospfd
│   ├── staticd
│   └── frr-reload
├── scripts/
│   ├── PRE_INST.sh      # 创建/etc/frr目录
│   ├── start.sh          # 启动zebra/ospfd
│   ├── stop.sh           # 停止zebra/ospfd
│   └── POST_INST.sh     # 注册rc启动项
└── app/bin/{arch}/lib/   # frr依赖库
```

manifest.json:
```json
{
  "name": "ospf",
  "version": "1.0.0",
  "type": "0",
  "maintainer": "iKuai",
  "requirements": {"memory": "32MB", "storage": "16MB", "os_min_version": "4.0.306"},
  "integrity": {
    "algorithm": "sha256",
    "signature_algorithm": "rsa-3072-sha256",
    "signature_file": "manifest.json.sig",
    "files": [...]
  }
}
```

### 4.4 在线更新流程（PMD主导）

```
设备启动
├── AppMarket.sh boot → 初始化SQLite + sync_apps
├── pmd启动 → login(pkgmgr-v4.ikuai8.com:1864)
│   ├── 上报：设备信息 + 已安装包列表（含OSPF）
│   ├── 服务器返回：各包最新版本 + 下载URL
│   ├── query() 30秒轮询
│   ├── 发现新版本 → 下载 → RSA3072验证 → 缓存
│   ├── 通知AppMarket：通过消息队列 "OSPF有更新"
│   └── 用户确认/自动应用 → stop旧版 → install新版 → start新版
│
└── 降级拦截
    ├── PMD缓存服务器下发的latest版本列表
    ├── 安装请求 → Version比较
    ├── 请求版本 < 缓存版本 → 拦截
    └── 例外：恢复出厂+全程离线
```

### 4.5 服务端整合

当前PMD服务端(ik_rc)和AppMarket服务端(docker-app仓库+ICC)是分开的：
- ik_rc：C daemon，管设备连接、RPC、主备
- docker-app：包仓库+签名工具
- ICC云端：applist_control.lua调`/api/v1/device/plugins`

整合方向：
- ik_rc保持设备连接+RPC不动
- docker-app仓库增加OS组件分类（OSPF/GRE/IPsec的ipkg包）
- ICC云端API统一：`/api/v1/device/plugins`返回所有包（含OS组件）

## 5. 风险评估

| 风险 | 等级 | 缓解 |
|------|------|------|
| OSPF组件化后3.0升级配置丢失 | 中 | 升级脚本检测已有OSPF配置，自动安装OSPF组件 |
| PMD自更新失败 | 低 | 已有do_reload回滚机制，保留旧版本备份 |
| RSA3072私钥泄露 | 中 | 私钥只在docker-app/signing/，不在设备上 |
| 降级绕过 | 低 | 恢复出厂+全程离线可绕过（离线确实管不到） |
| PMD+AppMarket接口稳定性 | 中 | Unix socket接口，版本兼容，灰度发布 |

## 6. 实施计划

### 第一批：OSPF组件化试点
- [ ] 把OSPF打成ipkg包（manifest.json+scripts+binaries）
- [ ] 签名：用docker-app/signing/sign_app_manifest.sh
- [ ] 验证：AppMarket安装/卸载/启停
- [ ] 降级拦截验证

### 第二批：PMD暴露接口给AppMarket
- [ ] 扩展/tmp/pmd_progress.sock接口
- [ ] AppMarket Shell调用PMD接口
- [ ] PMD采用AppMarket签名验证（RSA3072替代AES+MD5）
- [ ] 两套后端共存测试

### 第三批：OS组件逐步组件化
- [ ] GRE打ipkg包
- [ ] IPsec打ipkg包
- [ ] rc脚本改为PMD注册启动项（不硬编码）
- [ ] Docker引擎本身打ipkg包（已有install.sh雏形）

## 7. 前端复用策略

AppMarket前端已有：
- 应用列表页
- 安装/卸载交互
- 版本更新提示
- 上传安装

OS组件（OSPF/GRE/IPsec）复用前端：
- 新增"OS组件"分类（category字段已在manifest.json里）
- 前端按category过滤展示
- 不需要新页面，只是多一个分类tab
- 前端工作量：增加分类筛选 + 组件状态展示（调PMD接口）

前端团队需要的：
1. PMD接口文档（/list, /status, /install, /uninstall, /monitor）
2. manifest.json增加category字段定义
3. OS组件的状态展示UI（running/stopped/error + PID + uptime）

## 8. 待讨论

1. PMD包格式是否统一为ipkg？还是PMD保留自己的JSON格式，只是签名改RSA3072？
2. OSPF组件化后rc启动脚本怎么处理？建议PMD注册启动项
3. ik_rc服务端是否需要改动？还是只改docker-app仓库+ICC？
4. GRE/IPsec是否同步组件化？建议OSPF跑通后再推
5. Docker引擎是否也组件化？已有install.sh，可打ipkg包
