diff --git a/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md b/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md deleted file mode 100644 index 2fdf058..0000000 --- a/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md +++ /dev/null @@ -1,48 +0,0 @@ -# JDK17 + Mockito + CI Stability Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Stabilize local/CI test execution by fixing Mockito agent startup behavior and pinning CI to JDK 17. - -**Architecture:** Configure Maven Surefire to preload Mockito as a javaagent and set required JVM flags to avoid runtime self-attach failures. Add a CI workflow that always uses JDK 17 and runs compile/test checks. Update README for explicit developer/CI runtime expectations. - -**Tech Stack:** Maven Surefire, Mockito, GitHub Actions, JDK 17, Spring Boot 3.5 - ---- - -### Task 1: Build/Test runtime hardening - -**Files:** -- Modify: `pom.xml` - -1. Add explicit `mockito.version` property. -2. Add `maven-surefire-plugin` with `argLine` including: - - `-Djdk.attach.allowAttachSelf=true` - - `-XX:+EnableDynamicAgentLoading` - - `-javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar` - -### Task 2: CI JDK pinning - -**Files:** -- Create: `.github/workflows/ci.yml` - -1. Add workflow on `push` + `pull_request`. -2. Use `actions/setup-java` with Temurin `17`. -3. Run `mvn -q -DskipTests compile` then `mvn -q test`. - -### Task 3: Documentation sync - -**Files:** -- Modify: `README.md` - -1. Add explicit local recommended JDK 17 note. -2. Add CI note: workflow runs JDK 17 and compile+test. -3. Add troubleshooting note for Mockito agent behavior on newer JDKs. - -### Task 4: Verification - -**Commands:** -1. `mvn -q -DskipTests compile` -2. `mvn -q test` (sandbox) -3. `mvn -q test` (escalated fallback if sandbox attach restrictions block) -4. Key checks with `rg` for workflow and surefire config. diff --git a/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md b/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md deleted file mode 100644 index 0bd22a0..0000000 --- a/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md +++ /dev/null @@ -1,168 +0,0 @@ -# PCIe密码卡强类型封装设计(第一期) - -- 日期:2026-02-28 -- 范围:基于 `0018接口.pdf`(国密标准SDF)与 `PCIE密码卡应用接口说明书.docx`(SDFE扩展) -- 目标:为上层提供强类型业务方法,屏蔽底层JNA细节 - -## 1. 设计目标与约束 - -### 1.1 目标 - -1. 提供强类型业务方法,不要求上层使用 `execute(command, params)`。 -2. 采用短连接会话模型:每个业务方法内部完成 `openDevice/openSession/call/closeSession/closeDevice`。 -3. 第一期开通核心子集接口,覆盖设备管理、会话、HMAC、LMK与常用密钥管理。 -4. 统一错误模型与错误码映射,便于上层处理与运维排障。 - -### 1.2 非目标 - -1. 不在第一期覆盖文档所有SDF/SDFE接口。 -2. 不在第一期做多设备负载均衡与高并发优化。 -3. 不在第一期实现JNI桥代码生成。 - -## 2. 方案选型 - -### 2.1 备选方案 - -1. 动态命令入口(`execute(command, params)`)+ 强类型外观。 -2. 纯强类型服务(推荐)。 -3. 从头文件自动生成绑定与服务代码。 - -### 2.2 选型结论 - -采用方案2:新增 `PcieCryptoService` 及其 `JnaPcieCryptoService` 实现, -强类型方法直接调用JNA映射,统一通过短连接模板管理句柄生命周期。 - -## 3. 总体架构 - -### 3.1 分层 - -1. `PcieCryptoService`:面向上层的强类型业务接口。 -2. `JnaPcieCryptoService`:服务实现,调用 `PcieNativeLibrary`。 -3. `PcieSessionTemplate`:统一短连接模板。 -4. `PcieNativeLibrary`:JNA native函数映射。 -5. `PcieErrorMapper`:错误码映射(`retCode -> 业务可读信息`)。 - -### 3.2 调用路径 - -上层业务 -> `PcieCryptoService` 强类型方法 -> `PcieSessionTemplate` -> `PcieNativeLibrary` -> 厂商 `.so` - -## 4. 第一期开通接口(核心子集) - -### 4.1 设备与会话 - -1. `getDeviceNumber()` -> `SDFE_GetDeviceNumber` -2. `getNormalDeviceNumber()` -> `SDFE_GetNormalDeviceNumber` -3. `deviceSelfTest()` -> `SDFE_DeviceSelfTest` -4. `deviceConfGet()` -> `SDFE_DeviceConfGet` -5. `initIdentify(oldPin, newPin)` -> `SDFE_InitIdentify` - -> 注:`open/close` 作为模板内部行为,不暴露给上层业务接口。 - -### 4.2 常用密钥管理(用户确认的8组) - -1. `generateKeyPairEcc` / `generateKeyPairRsa` -2. `generateKek` -3. `backupUserKey` / `recoverUserKey` -4. `backupKek` / `recoverKek` -5. `deleteUserKey` / `deleteKek` -6. `statusUserKeyEcc` / `statusUserKeyRsa` -7. `statusKek` -8. `changePrivateKeyAccessPassword` - -### 4.3 HMAC - -1. `hmac(algId, key, data)` -2. 内部流程:`SDFE_HmacInit` -> `SDFE_HmacUpdate` -> `SDFE_HmacFinal` - -### 4.4 LMK(核心) - -1. `generateLmk` / `loadLmk` / `backupLmk` / `recoverLmk` / `destroyLmk` -2. `checkLmk` / `exportLmkSeedMac` - -## 5. 强类型模型 - -### 5.1 请求对象 - -1. `GenerateKeyRequest`:`keyIndex`, `keyBits`, `keyType` -2. `RecoverUserKeyRequest`:`keyIndex`, `keyType`, `cipherKeyData`, `storeFlag` -3. `RecoverKekRequest`:`keyIndex`, `cipherKeyData` -4. `ChangePrivateKeyPasswordRequest`:`keyIndex`, `oldPassword`, `newPassword` -5. `HmacRequest`:`algId`, `key`, `data` - -### 5.2 响应对象 - -1. `OperationResult`:`success`, `retCode`, `message` -2. `DeviceCountResult`:`deviceNumber`, `normalDeviceNumber` -3. `DeviceConfResult`:映射 `SDFE_DeviceConf` -4. `BackupUserKeyResult` / `BackupKekResult`:`data`, `length` -5. `KeyStatusResult`:`keyState` -6. `HmacResult`:`hmac`, `hmacLength` - -## 6. 会话模板(短连接) - -定义统一模板方法: - -```text -executeWithSession(apiName, callback): - SDF_OpenDevice - SDF_OpenSession - callback(session) - SDF_CloseSession - SDF_CloseDevice -``` - -约束: - -1. 所有强类型方法必须通过模板执行。 -2. 关闭失败仅记录日志,不覆盖主调用错误。 -3. 模板保证异常场景也能回收句柄。 - -## 7. 错误处理 - -1. `retCode == 0`:成功。 -2. `retCode != 0`:抛 `PcieCryptoException(apiName, retCode, mappedMessage)`。 -3. 映射文档补充错误码: - - `SDR_UKEYERR` - - `SDR_GENKEYERR` - - `SDR_STATEERR` - - `SDR_RETRYERR` - - `SDR_DEVICE_BUSY` - - `SDR_RET_ERR_STATUS` - - `SDR_RET_INIT_STATUS` - - `SDR_RET_LOGINED` - - `SDR_RET_GD32_TIMEOUT` -4. 参数校验失败在服务层抛 `IllegalArgumentException`,不下发至设备。 - -## 8. 并发与安全 - -1. 第一期开启串行访问(单设备锁)避免状态错乱。 -2. PIN/口令参数不打印明文日志。 -3. 密钥备份字节在服务层保持二进制,不做文本日志输出。 - -## 9. 对上层的使用方式 - -示例: - -1. `pcieCryptoService.generateLmk()` -2. `pcieCryptoService.backupKek(keyIndex, outBufferSize)` -3. `pcieCryptoService.hmac(request)` - -上层仅依赖强类型接口与DTO,不直接依赖JNA类型和指针。 - -## 10. 验收标准 - -1. 强类型接口可完成第一期核心子集调用。 -2. 每个方法均使用短连接模板。 -3. 统一异常中包含 `apiName + retCode + mappedMessage`。 -4. `mvn -DskipTests compile` 通过。 -5. 关键路径联调用例可跑通: - - `getDeviceNumber` - - `deviceConfGet` - - `hmac` - - `generateKek + statusKek` - -## 11. 后续扩展 - -1. 第二期覆盖U盾与内部密钥管理。 -2. 第三期覆盖全量SDF/SDFE并补充结构体严格对齐校验。 -3. 加入真实设备集成测试与回放测试。 diff --git a/docs/plans/2026-02-28-pcie-realcard-smoke-checklist.md b/docs/plans/2026-02-28-pcie-realcard-smoke-checklist.md deleted file mode 100644 index a1a5e77..0000000 --- a/docs/plans/2026-02-28-pcie-realcard-smoke-checklist.md +++ /dev/null @@ -1,75 +0,0 @@ -# PCIe 真卡联调与冒烟检查清单 - -## 1. 前置条件 - -- 部署环境为目标架构(与生产一致的 CPU/OS/libc)。 -- 已安装厂商 `.so`,并可被进程访问。 -- 服务配置为 JNA 真卡模式: - - `tms.crypto-card.enabled=true` - - `tms.crypto-card.mode=JNA` - - `tms.crypto-card.vendor-lib-path` 或 `tms.crypto-card.vendor-lib-name` 正确 - - `tms.crypto-card.strict-alg-id-validation=true`(若厂商扩展算法可临时关闭) -- 已知内部接口鉴权令牌 `X-Internal-Token`。 - -## 2. 核心检查项(必须通过) - -1. 设备与会话 - - `GET /api/v1/device/crypto/device-count` - - `GET /api/v1/device/crypto/device-info` - - `POST /api/v1/device/crypto/self-test` -2. 基础密码能力 - - 随机数:`GET /api/v1/device/crypto/random?length=16` - - 摘要:`POST /api/v1/device/crypto/digest` - - HMAC:`POST /api/v1/device/crypto/hmac` -3. 对称能力 - - 明文密钥加解密:`/encrypt/plain` + `/decrypt/plain` - - KEK 生成与状态:`/kek/generate` + `/kek/status` -4. 主密钥状态 - - `GET /api/v1/device/crypto/lmk/seed-mac` - -验收标准: - -- `ApiResponse.success == true` -- `ApiResponse.code == 200` -- 返回长度字段与 Base64 解码长度一致 -- 错误日志中无 native 崩溃/段错误 - -## 3. 高风险专项 - -### 3.1 `SDFE_ImportEncKeyPair_ECC`(结构体直传) - -- 用最小可用样本执行导入流程。 -- 成功后立即查询相关密钥状态接口验证导入结果。 -- 若出现参数错误,优先检查结构体字段对齐与 `unsigned long` 位宽。 - -### 3.2 `ECCCipher` 变长字段边界 - -- 对不同明文长度执行 ECC 加密路径。 -- 记录返回 `ECCCipher.l` 的最大值。 -- 若接近当前上限(`C_MAX_LEN`),必须提升上限并复测。 - -### 3.3 算法标识白名单 - -- 对业务实际用到的所有 `algId` 跑一遍。 -- 若被严格校验拦截,补充到 `Gm0018AlgorithmIds` 后再回归。 - -## 4. 失败排查顺序 - -1. 配置错误:库路径、库名、鉴权 token。 -2. 运行时依赖:`ldd`/动态库缺失。 -3. 参数编码:Base64 入参、长度字段、结构体大小。 -4. 算法标识:`algId` 是否在白名单。 -5. 厂商错误码:结合 `PcieErrorMapper` 与厂商文档定位。 - -## 5. 回归策略 - -- 每次升级以下任一项,都执行本清单: - - JDK 版本 - - 厂商 `.so` 版本 - - JNA 结构体定义 - - `JnaPcieCryptoService` 参数转换逻辑 - -## 6. 自动化模板 - -- 使用脚本:`scripts/pcie_realcard_smoke.sh` -- 建议在联调机和预生产各执行一次,并保留日志归档。 diff --git a/docs/plans/2026-03-02-cisd-init-api-curl-examples.md b/docs/plans/2026-03-02-cisd-init-api-curl-examples.md deleted file mode 100644 index e1a0951..0000000 --- a/docs/plans/2026-03-02-cisd-init-api-curl-examples.md +++ /dev/null @@ -1,214 +0,0 @@ -# CISD 初始化 API Curl 样例集 - -- 日期:2026-03-02 -- 适用接口前缀:`/api/v1/device`、`/api/v1/init` -- 说明:以下样例用于联调,不包含生产鉴权与审计策略 - -## 1. 公共变量 - -```bash -BASE_URL="${BASE_URL:-http://127.0.0.1:8080}" -INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}" -``` - -## 2. 查询设备预置版本信息 - -```bash -curl -sS \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/device/status" | jq -``` - -预期关键字段: - -1. `data.presetProductType`:`ENTERPRISE|INDIRECT|DIRECT` -2. `data.presetVersion` - -## 3. 企业/间参请求体(RabbitMQ) - -```bash -cat > /tmp/cisd-init-standard-rabbit.json <<'JSON' -{ - "orgCodeType": "BIC", - "orgCode": "AAAABBBBXXX", - "orgNameCn": "测试机构", - "orgNameEn": "TEST BANK", - "deployMode": "SINGLE", - "nodes": { - "node01Ip": "10.0.0.11" - }, - "mq": { - "mqType": "RABBITMQ", - "channelUsername": "cisd_channel_user", - "channelPassword": "cisd_channel_pass" - }, - "licenses": { - "receiverLicenseFileId": "file-receiver-001" - } -} -JSON -``` - -## 4. 企业/间参请求体(TLQ) - -```bash -cat > /tmp/cisd-init-standard-tlq.json <<'JSON' -{ - "orgCodeType": "BIC", - "orgCode": "AAAABBBBXXX", - "orgNameCn": "测试机构", - "orgNameEn": "TEST BANK", - "deployMode": "DUAL", - "nodes": { - "node01Ip": "10.0.0.11", - "node02Ip": "10.0.0.12" - }, - "mq": { - "mqType": "TLQ", - "channelUsername": "cisd_channel_user", - "channelPassword": "cisd_channel_pass", - "tlqLicenseFileId": "file-tlq-license-001" - }, - "licenses": { - "receiverLicenseFileId": "file-receiver-001" - } -} -JSON -``` - -## 5. 轻量化直参请求体(RABBITMQ_TLQ) - -```bash -cat > /tmp/cisd-init-direct-tlq.json <<'JSON' -{ - "orgCodeType": "BIC", - "orgCode": "AAAABBBBXXX", - "orgNameCn": "测试机构", - "orgNameEn": "TEST BANK", - "deployMode": "DUAL", - "nodes": { - "node01Ip": "10.0.1.11", - "node02Ip": "10.0.1.12" - }, - "mq": { - "mqType": "RABBITMQ_TLQ", - "channelUsername": "cisd_channel_user", - "channelPassword": "cisd_channel_pass", - "tlqLicenseFileId": "file-tlq-license-001" - }, - "licenses": { - "receiverLicenseFileId": "file-receiver-001", - "cfgZipFileId": "/opt/cpconfig.cfg" - }, - "signServer": { - "signHost": "172.30.1.101", - "signPort": 50006, - "signType": "Infosec", - "signCertDn": "CN=051@AAAABBBBXXX@7321@1,OU=Org,OU=CIPS,O=CFCA OCA1,C=CN", - "signCertSn": "1154809590", - "signPassword": "secret" - }, - "directTlq": { - "localNodeSeq": "A", - "upstreamInstitutions": "CIPSCNSHXXX;CIPSCNWXXXX", - "upstreamCocCount": 2 - } -} -JSON -``` - -## 6. 轻量化直参请求体(RABBITMQ_CFMQ) - -```bash -cat > /tmp/cisd-init-direct-cfmq.json <<'JSON' -{ - "orgCodeType": "BIC", - "orgCode": "AAAABBBBXXX", - "orgNameCn": "测试机构", - "orgNameEn": "TEST BANK", - "deployMode": "SINGLE", - "nodes": { - "node01Ip": "10.0.1.11" - }, - "mq": { - "mqType": "RABBITMQ_CFMQ", - "channelUsername": "cisd_channel_user", - "channelPassword": "cisd_channel_pass", - "cfmqConfigFileId": "/pmts/cfg/cfmqapi_trans.properties" - }, - "licenses": { - "receiverLicenseFileId": "file-receiver-001", - "cfgZipFileId": "/opt/cpconfig.cfg" - }, - "signServer": { - "signHost": "172.30.1.101", - "signPort": 50006, - "signType": "Infosec", - "signCertDn": "CN=051@AAAABBBBXXX@7321@1,OU=Org,OU=CIPS,O=CFCA OCA1,C=CN", - "signCertSn": "1154809590", - "signPassword": "secret" - } -} -JSON -``` - -## 7. 初始化任务执行链路(通用) - -将 `` 替换为上面任一 json 文件路径。 - -```bash -REQUEST_JSON="/tmp/cisd-init-standard-rabbit.json" - -# 1) preview -curl -sS -X POST \ - -H "Content-Type: application/json" \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/init/preview" \ - -d @"${REQUEST_JSON}" | jq - -# 2) create task -TASK_ID="$(curl -sS -X POST \ - -H "Content-Type: application/json" \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/init/tasks" \ - -d @"${REQUEST_JSON}" | jq -r '.data.taskId')" - -echo "TASK_ID=${TASK_ID}" - -# 3) execute task -curl -sS -X POST \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/init/tasks/${TASK_ID}/execute" | jq - -# 4) query steps -curl -sS \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/init/tasks/${TASK_ID}/steps" | jq -``` - -## 8. 单步日志查询(失败定位) - -```bash -STEP_NO=3 -curl -sS \ - -H "X-Internal-Token: ${INTERNAL_TOKEN}" \ - "${BASE_URL}/api/v1/init/tasks/${TASK_ID}/steps/${STEP_NO}/log" | jq -r '.data.content' -``` - -## 9. 常见问题 - -1. 直参 TLQ 报 `directTlq is required`:请求体缺 `directTlq` 三字段。 -2. `APP_MQ_CREDENTIALS_APPLY` 失败:应用配置匹配路径无文件或无写权限。 -3. MQ 连接失败:确认 `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY` 与收发器解密密钥一致。 - -## 10. 一键执行脚本(推荐) - -```bash -chmod +x scripts/cisd_init_flow.sh -REQUEST_JSON=/tmp/cisd-init-standard-rabbit.json \ -BASE_URL=http://127.0.0.1:8080 \ -INTERNAL_TOKEN=change-me-internal-token \ -./scripts/cisd_init_flow.sh -``` - -输出目录默认:`/tmp/cisd-init-run/run-`,包含每一步请求响应与失败日志抓取结果。 diff --git a/docs/plans/2026-03-02-cisd-init-onhost-validation-and-rollback.md b/docs/plans/2026-03-02-cisd-init-onhost-validation-and-rollback.md deleted file mode 100644 index 1e3114e..0000000 --- a/docs/plans/2026-03-02-cisd-init-onhost-validation-and-rollback.md +++ /dev/null @@ -1,165 +0,0 @@ -# CISD 初始化真机联调与回滚手册 - -- 日期:2026-03-02 -- 适用版本:`ENTERPRISE` / `INDIRECT` / `DIRECT` -- 适用代码基线:已包含 `APP_MQ_CREDENTIALS_APPLY`、`direct_db_init`、`tlq_init_cfg` - -## 1. 目的 - -1. 在目标设备上完成初始化关键路径联调。 -2. 验证三类版本在“预部署完成后,仅做客户化初始化”的边界下可稳定运行。 -3. 提供失败后的快速回滚与重试指引。 - -## 2. 关键实现映射(联调前必须确认) - -1. 企业/间参步骤链: -`RENDER_CONFIG -> SET_(RABBITMQ|TLQ) -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY` -2. 轻量化直参(TLQ)步骤链: -`RENDER_CONFIG -> MQ_USER_APPLY -> DB_INIT(direct_db_init) -> TLQ_INIT_CFG(tlq_init_cfg) -> VERIFY` -3. 轻量化直参(CFMQ)步骤链: -`RENDER_CONFIG -> MQ_USER_APPLY -> DB_INIT(direct_db_init) -> CFMQ_APPLY -> VERIFY` -4. 通道账号密码写回应用配置时默认加密: -`DESede(3DES) + secretKey=ABCDEFGHIJKLMN1234567890 + HEX(upper)`。 - -## 3. 联调前置检查 - -## 3.1 环境变量基线 - -在 TMS 进程环境确认以下参数: - -```bash -echo "$TMS_CISD_PRESET_PRODUCT_TYPE" -echo "$TMS_INIT_EXECUTOR_MODE" -echo "$TMS_INIT_EXECUTOR_STANDARD_CPCONFIG_PATH" -echo "$TMS_INIT_EXECUTOR_DIRECT_DB_SCRIPT_DIR" -echo "$TMS_INIT_EXECUTOR_DIRECT_TLQ_INIT_CFG_DIR" -echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_1" -echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_2" -echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_ENCRYPT_ENABLED" -echo "$TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY" -``` - -建议值: - -1. `TMS_INIT_EXECUTOR_MODE=LOCAL` -2. `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_ENCRYPT_ENABLED=true` -3. `TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY` 与现场收发器解密密钥一致。 - -## 3.2 目录与脚本存在性 - -```bash -ls -l /home/cmep4i/cpconfig.cfg -ls -l /home/cmep4i/cpackage/toolsh/{setfraq.sh,setftq.sh,setsql.sh,setsptp.sh} -ls -l /opt/CAE_Install_Base_Resource/DB/setsql.sh -ls -l /opt/CAE_Install_App_Resource/CAE/init_cfg.sh -``` - -## 3.3 MQ 与配置文件可写性 - -```bash -ls -l /home/cmep4i/cmsp/application-prd*.properties -ls -l /home/cmep4i/cmtp/application-prd*.properties -which rabbitmqctl -which rabbitmqadmin -``` - -## 4. 联调执行清单(统一流程) - -## 4.1 接口执行顺序 - -1. `GET /api/v1/device/status` -2. `POST /api/v1/init/preview` -3. `POST /api/v1/init/task` -4. `POST /api/v1/init/task/{taskId}/execute` -5. `GET /api/v1/init/task/{taskId}/steps` -6. 失败时逐步查看日志:`GET /api/v1/init/task/{taskId}/steps/{stepNo}/log` - -## 4.2 用例矩阵(最小集合) - -1. 企业版 + RabbitMQ -2. 企业版 + TLQ -3. 间参版 + RabbitMQ -4. 轻量化直参 + RABBITMQ_TLQ(必须带 `directTlq` 三字段) -5. 轻量化直参 + RABBITMQ_CFMQ - -## 4.3 直参 TLQ 请求体附加字段 - -```json -{ - "directTlq": { - "localNodeSeq": "A", - "upstreamInstitutions": "CIPSCNSHXXX;CIPSCNWXXXX", - "upstreamCocCount": 2 - } -} -``` - -## 5. 关键验收点 - -1. `RENDER_CONFIG` 后,`cpconfig.cfg` 中机构号、节点、签名参数、`MQ_TYPE` 已替换。 -2. `MQ_USER_APPLY` 后,RabbitMQ 中存在通道用户,且具备目标 vhost 权限。 -3. `MQ_QUEUE_APPLY` 后,业务队列创建成功(企业/间参)。 -4. `APP_MQ_CREDENTIALS_APPLY` 后,`spring.rabbitmq.username/password` 已更新且为密文(非明文)。 -5. `DB_INIT` 生成或替换的 SQL 文件可执行,无路径/权限错误。 -6. `VERIFY` 成功,任务最终状态 `SUCCESS`。 - -## 6. 失败定位顺序 - -1. 配置错误:版本预置、环境变量、路径。 -2. 权限错误:TMS 进程用户对脚本和配置文件不可写。 -3. 脚本依赖缺失:`rabbitmqctl/rabbitmqadmin`、Java、数据库客户端。 -4. 参数不完整:直参 TLQ 缺 `directTlq` 字段。 -5. 密钥不一致:写回密文与收发器解密密钥不匹配导致 MQ 连接失败。 - -## 7. 回滚策略(按层次) - -## 7.1 执行前备份(强制) - -```bash -TS=$(date +%Y%m%d%H%M%S) -mkdir -p /tmp/cisd-init-backup-$TS -cp -a /home/cmep4i/cpconfig.cfg /tmp/cisd-init-backup-$TS/ -cp -a /home/cmep4i/cmsp/application-prd*.properties /tmp/cisd-init-backup-$TS/ 2>/dev/null || true -cp -a /home/cmep4i/cmtp/application-prd*.properties /tmp/cisd-init-backup-$TS/ 2>/dev/null || true -echo "/tmp/cisd-init-backup-$TS" -``` - -## 7.2 配置回滚 - -```bash -cp -a /tmp/cisd-init-backup-/cpconfig.cfg /home/cmep4i/cpconfig.cfg -cp -a /tmp/cisd-init-backup-/application-prd*.properties /home/cmep4i/cmsp/ 2>/dev/null || true -cp -a /tmp/cisd-init-backup-/application-prd*.properties /home/cmep4i/cmtp/ 2>/dev/null || true -``` - -## 7.3 MQ 回滚(按需) - -```bash -# 删除通道用户(示例) -rabbitmqctl delete_user - -# 删除业务队列(示例,按实际创建队列名执行) -rabbitmqadmin --username=admin --password=admin --vhost=/ delete queue name= -rabbitmqadmin --username=admin --password=admin --vhost=/RQ delete queue name= -``` - -## 7.4 数据库回滚(按实际 SQL 执行情况) - -1. 若仅生成 SQL 未执行:删除临时生成物即可。 -2. 若已执行入库:使用预先准备的回滚 SQL 或从数据库备份恢复。 -3. 严禁在无备份情况下直接清库重建。 - -## 8. 重试策略 - -1. 先回滚配置和 MQ 变更,再重建任务重试,不复用失败任务。 -2. 每次仅变更一个变量(如路径、密钥、账号),避免多变量同时变化。 -3. 连续两次同一步失败,先停止重试,导出该步骤日志并人工排查根因。 - -## 9. 交付物归档 - -每次联调需归档: - -1. `taskId`、版本类型、请求参数(脱敏后)。 -2. 步骤执行日志目录:`/tmp/tms-init-logs//`。 -3. 回滚操作记录(是否执行、执行人、时间)。 -4. 最终结论:通过/失败及根因。 diff --git a/docs/plans/2026-03-02-cisd-init-request-schema-spec.md b/docs/plans/2026-03-02-cisd-init-request-schema-spec.md deleted file mode 100644 index 17d356b..0000000 --- a/docs/plans/2026-03-02-cisd-init-request-schema-spec.md +++ /dev/null @@ -1,108 +0,0 @@ -# CISD Init Request Schema Spec (Preset-Version Driven) - -## 1. Scope -This document defines the frontend request schema for CISD initialization in TMS when product version is preset by device metadata. - -- Frontend must call `GET /api/v1/device/status` first. -- If `presetProductType` is empty or invalid, initialization is forbidden. -- Frontend must render version-specific form fields automatically; user does not manually choose version. - -## 2. Device status fields used by frontend -`/api/v1/device/status` response includes: - -- `presetProductType`: `ENTERPRISE | INDIRECT | DIRECT` -- `presetVersion`: preset package version -- `presetSource`: where preset was loaded from (e.g., `CONFIG`, future `DB`) - -## 3. Init preview request payload -Endpoint: `POST /api/v1/init/preview` - -```json -{ - "orgCodeType": "BIC", - "orgCode": "AAAABBBBXXX", - "orgNameCn": "示例机构", - "orgNameEn": "Example Bank", - "deployMode": "DUAL", - "nodes": { - "node01Ip": "10.0.0.1", - "node02Ip": "10.0.0.2", - "node03Ip": "127.0.0.1", - "node04Ip": "127.0.0.1" - }, - "mq": { - "mqType": "RABBITMQ", - "channelUsername": "channel_user", - "channelPassword": "channel_password", - "tlqLicenseFileId": "file-tlq-license", - "cfmqConfigFileId": "file-cfmq-config" - }, - "licenses": { - "receiverLicenseFileId": "file-receiver-license", - "cfgZipFileId": "file-cfg-zip" - }, - "signServer": { - "signHost": "172.30.1.101", - "signPort": 50006, - "signType": "Infosec", - "signCertDn": "CN=...", - "signCertSn": "1154809590", - "signPassword": "***" - } -} -``` - -## 4. Mandatory fields by product type - -### 4.1 Common mandatory fields (all versions) -- `orgCodeType`, `orgCode`, `orgNameCn` -- `deployMode` -- `nodes.node01Ip` -- `mq.mqType`, `mq.channelUsername`, `mq.channelPassword` -- `licenses.receiverLicenseFileId` - -### 4.2 ENTERPRISE / INDIRECT -Allowed values: -- `deployMode`: `SINGLE | DUAL` -- `mq.mqType`: `RABBITMQ | TLQ` - -Conditional required fields: -- `deployMode=DUAL` -> `nodes.node02Ip` -- `mqType=TLQ` -> `mq.tlqLicenseFileId` - -### 4.3 DIRECT -Allowed values: -- `deployMode`: `SINGLE | DUAL | QUAD` -- `mq.mqType`: `RABBITMQ_TLQ | RABBITMQ_CFMQ` - -Always required: -- `licenses.cfgZipFileId` -- `signServer.signHost` -- `signServer.signPort` -- `signServer.signType` -- `signServer.signCertDn` -- `signServer.signCertSn` -- `signServer.signPassword` - -Conditional required fields: -- `deployMode=DUAL|QUAD` -> `nodes.node02Ip` -- `deployMode=QUAD` -> `nodes.node03Ip`, `nodes.node04Ip` -- `mqType=RABBITMQ_TLQ` -> `mq.tlqLicenseFileId` -- `mqType=RABBITMQ_CFMQ` -> `mq.cfmqConfigFileId` - -## 5. Prefilled vs user-input fields - -### 5.1 Prefilled and hidden from frontend -- Product preset metadata: version type and package version -- Database deployment credentials and root/app user passwords -- RabbitMQ admin username/password - -### 5.2 User input fields -- Institution identity and node addresses -- MQ channel username/password -- Version-conditional file uploads (receiver license, TLQ license, CFMQ config, direct CFG zip) -- Direct sign server information - -## 6. Validation behavior -- Validation errors return code `4001` with field message. -- Missing/invalid preset product type returns business error and initialization is blocked. diff --git a/docs/plans/2026-03-02-cisd-init-schema-dto-plan.md b/docs/plans/2026-03-02-cisd-init-schema-dto-plan.md deleted file mode 100644 index 872bbd7..0000000 --- a/docs/plans/2026-03-02-cisd-init-schema-dto-plan.md +++ /dev/null @@ -1,121 +0,0 @@ -# CISD Init Request Schema DTO Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Replace placeholder init preview request with a production-ready CISD initialization request DTO and server-side rule validation based on preset product type. - -**Architecture:** Keep the current single-module Spring Boot structure. Introduce strong-typed nested DTOs for init request payload, centralize preset version/product-type sourcing in configuration properties (as current phase baseline), and enforce cross-field conditional rules in `InitService` before preview generation. Surface preset product type in `/api/v1/device/info` for frontend auto-rendering. - -**Tech Stack:** JDK 17, Spring Boot 3.5, Jakarta Bean Validation, JUnit 5. - ---- - -### Task 1: Add failing tests for init request rule validation - -**Files:** -- Create: `src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Write failing tests** -- Add tests for: - - missing preset product type should reject init preview. - - enterprise + TLQ should require `tlqLicenseFileId`. - - direct + `RABBITMQ_CFMQ` should require `cfmqConfigFileId`, `cfgZipFileId`, and sign server fields. - - valid enterprise request should pass and generate summary. - -**Step 2: Run targeted tests to verify red** -- Run: `mvn -q -Dtest=InitServiceTest test` -- Expected: FAIL because `InitService` still uses old DTO and has no rule engine. - -### Task 2: Implement strong-typed init request DTO model - -**Files:** -- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java` - -**Step 1: Replace old placeholder fields** -- Remove `version/nodeCount`. -- Add nested models for: - - basic institution fields - - deploy mode + nodes - - mq settings - - licenses - - sign server - -**Step 2: Add validation annotations** -- Add required constraints for common fields (`orgCodeType`, `orgCode`, `orgNameCn`, `deployMode`, `node01Ip`, `mqType`, `channelUsername`, `channelPassword`, `receiverLicenseFileId`). - -**Step 3: Keep model minimal and serializable** -- Use static inner classes with getters/setters only. - -### Task 3: Add preset product type source and expose in device info - -**Files:** -- Create: `src/main/java/com/cisd/tms/common/config/properties/CisdPresetProperties.java` -- Modify: `src/main/java/com/cisd/tms/modules/device/dto/DeviceInfoResponse.java` -- Modify: `src/main/java/com/cisd/tms/modules/device/service/DeviceService.java` -- Modify: `src/main/resources/application.yml` - -**Step 1: Add configuration properties bean** -- Prefix: `tms.cisd.preset` -- Fields: `productType`, `version`, `source`. - -**Step 2: Extend device status response** -- Add `presetProductType`, `presetVersion`, `presetSource`. - -**Step 3: Populate response from preset config** -- Inject `CisdPresetProperties` into `DeviceService` and map values. - -### Task 4: Implement rule validation in InitService - -**Files:** -- Modify: `src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPreviewResponse.java` -- Modify: `src/main/java/com/cisd/tms/modules/init/dto/InitPlanTemplateResponse.java` - -**Step 1: Add preset guard** -- If preset product type missing/invalid, throw `BizException` and block preview/template. - -**Step 2: Add product-type conditional validation** -- Enterprise/Indirect: - - deploy mode only `SINGLE/DUAL` - - mq type only `RABBITMQ/TLQ` - - TLQ requires `tlqLicenseFileId` - - DUAL requires `node02Ip` -- Direct: - - deploy mode `SINGLE/DUAL/QUAD` - - mq type `RABBITMQ_TLQ/RABBITMQ_CFMQ` - - `cfgZipFileId` required - - sign server fields required - - TLQ requires `tlqLicenseFileId` - - CFMQ requires `cfmqConfigFileId` - - DUAL/QUAD require `node02Ip`; QUAD require `node03Ip/node04Ip` - -**Step 3: Produce meaningful preview summary** -- Set response fields: resolved product type, step count estimate, and concise summary. - -### Task 5: Add developer-facing validation spec doc - -**Files:** -- Create: `docs/plans/2026-03-02-cisd-init-request-schema-spec.md` - -**Step 1: Document payload JSON schema shape** -- Include common object structure and conditional fields by product type. - -**Step 2: Document prefilled vs user-input fields** -- Explicitly list DB creds and RabbitMQ admin creds as prefilled-only. - -### Task 6: Verify and stabilize - -**Files:** -- N/A - -**Step 1: Run targeted tests** -- `mvn -q -Dtest=InitServiceTest test` - -**Step 2: Run compile check** -- `mvn -q -DskipTests compile` - -**Step 3: Run full test suite if stable** -- `mvn -q test` - -**Step 4: Record results in response** -- Include changed files, command outputs summary, remaining risks. diff --git a/docs/plans/2026-03-06-cisd-standard-init-support-mode-design.md b/docs/plans/2026-03-06-cisd-standard-init-support-mode-design.md deleted file mode 100644 index dc3cf5c..0000000 --- a/docs/plans/2026-03-06-cisd-standard-init-support-mode-design.md +++ /dev/null @@ -1,70 +0,0 @@ -# CISD 标准版初始化支持方式设计 - -## 背景 -当前 TMS 将标准版初始化统一抽象为 `mqType=RABBITMQ|TLQ`。这与实际部署介质不完全一致: -- `ENTERPRISE` 支持 `RABBITMQ` 和 `TLQ` 两种互斥模式。 -- `INDIRECT` 支持 `仅 RabbitMQ` 和 `RabbitMQ + TLQ` 两种模式。 -- `INDIRECT` 的 `RabbitMQ + TLQ` 并不是纯 `TLQ`,仍需执行 RabbitMQ 用户、队列和应用配置。 - -## 目标 -在不破坏现有接口字段名的前提下,修正标准版初始化参数校验、步骤编排和执行条件,使其与部署介质和脚本行为一致。 - -## 约束 -- 保留前端请求字段 `mq.mqType`,避免接口字段名变更带来的联调成本。 -- 仅修改 `modules/init` 范围内代码和 `docs/openapi/cisd-init` 文档。 -- 不调整出厂前预装边界;本次仍只覆盖初始化阶段。 - -## 方案选择 -### 方案 A:重命名字段为 `supportMode` -优点:语义最准确。 -缺点:破坏现有接口,前后端和历史任务数据都要联动修改。 - -### 方案 B:保留 `mqType` 字段名,按产品解释枚举值 -优点:改动最小,能直接修正行为。 -缺点:字段名与实际语义存在轻微偏差,需要通过文档解释。 - -### 方案 C:继续保留当前模型,仅靠执行器特殊判断 -优点:表面改动更少。 -缺点:校验、预检、步骤预览、OpenAPI 全部失真,后续维护成本更高。 - -## 采用方案 -采用方案 B。 - -## 调整后的 `mqType` 语义 -- `ENTERPRISE`: `RABBITMQ` | `TLQ` -- `INDIRECT`: `RABBITMQ` | `RABBITMQ_TLQ` -- `DIRECT`: `RABBITMQ_TLQ` | `RABBITMQ_CFMQ` - -## 标准版步骤编排 -### ENTERPRISE + RABBITMQ -`RENDER_CONFIG -> FILE_PREPARE -> SET_RABBITMQ -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY` - -### ENTERPRISE + TLQ -`RENDER_CONFIG -> FILE_PREPARE -> SET_TLQ -> TLQ_CONF_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> VERIFY` - -### INDIRECT + RABBITMQ -`RENDER_CONFIG -> FILE_PREPARE -> SET_RABBITMQ -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY` - -### INDIRECT + RABBITMQ_TLQ -`RENDER_CONFIG -> FILE_PREPARE -> SET_TLQ -> TLQ_CONF_APPLY -> MQ_USER_APPLY -> MQ_QUEUE_APPLY -> DB_INIT -> DEPLOY_RECEIVER -> APP_MQ_CREDENTIALS_APPLY -> VERIFY` - -## 脚本映射 -- `SET_RABBITMQ` -> `cpackage/toolsh/setfraq.sh` -- `SET_TLQ` -> `cpackage/toolsh/setftq.sh` -- `TLQ_CONF_APPLY` -> `cpackage/toolsh/settlq.sh` -- `DB_INIT` -> `cpackage/toolsh/setsql.sh` -- `DEPLOY_RECEIVER` -> `cpackage/toolsh/setsptp.sh` -- `MQ_USER_APPLY` -> 标准版 `setuprabq.sh` staging 执行 -- `MQ_QUEUE_APPLY` -> 标准版 `addrabq_R_01.sh` / `addrabq_R_02.sh` staging 执行 - -## 执行条件 -- `ENTERPRISE + TLQ` 跳过 RabbitMQ 用户、队列和应用账号写回。 -- `INDIRECT + RABBITMQ_TLQ` 保留 RabbitMQ 用户、队列和应用账号写回。 -- `FILE_PREPARE` 在 `TLQ` 或 `RABBITMQ_TLQ` 模式下均需准备 TLQ license。 - -## 测试重点 -- `ENTERPRISE + TLQ` 预检通过且步骤中包含 `TLQ_CONF_APPLY`,不包含 RabbitMQ 相关步骤。 -- `INDIRECT + RABBITMQ_TLQ` 预检通过且步骤中同时包含 `TLQ_CONF_APPLY` 与 RabbitMQ 相关步骤。 -- `INDIRECT + TLQ` 作为非法值被拒绝。 -- `ENTERPRISE + RABBITMQ_TLQ` 作为非法值被拒绝。 -- `APP_MQ_CREDENTIALS_APPLY` 在 `ENTERPRISE + TLQ` 下跳过,在 `INDIRECT + RABBITMQ_TLQ` 下执行。 diff --git a/docs/plans/2026-03-06-cisd-standard-init-support-mode-plan.md b/docs/plans/2026-03-06-cisd-standard-init-support-mode-plan.md deleted file mode 100644 index 826c9af..0000000 --- a/docs/plans/2026-03-06-cisd-standard-init-support-mode-plan.md +++ /dev/null @@ -1,121 +0,0 @@ -# CISD Standard Init Support Mode Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** 修正标准版 CISD 初始化中 `ENTERPRISE` 和 `INDIRECT` 的支持方式建模、步骤编排和执行条件。 - -**Architecture:** 保留 `mqType` 字段名,但将其解释为按产品区分的支持方式枚举;服务层负责校验和步骤编排,执行器负责按产品与模式判定脚本是否实际执行或跳过。 - -**Tech Stack:** Java 17, Spring Boot 3, JUnit 5, OpenAPI YAML/JSON - ---- - -### Task 1: 固化设计与枚举语义 - -**Files:** -- Create: `docs/plans/2026-03-06-cisd-standard-init-support-mode-design.md` -- Create: `docs/plans/2026-03-06-cisd-standard-init-support-mode-plan.md` - -**Step 1: 保存设计文档** -保存版本差异、步骤编排和脚本映射。 - -**Step 2: 保存实施计划** -记录测试先行的修改顺序。 - -### Task 2: 先补服务层失败测试 - -**Files:** -- Modify: `src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: 写 ENTERPRISE TLQ 的预检和步骤测试** -断言 `TLQ_CONF_APPLY` 存在,`MQ_USER_APPLY/MQ_QUEUE_APPLY/APP_MQ_CREDENTIALS_APPLY` 不存在。 - -**Step 2: 写 INDIRECT RABBITMQ_TLQ 的预检和步骤测试** -断言 `TLQ_CONF_APPLY`、`MQ_USER_APPLY`、`MQ_QUEUE_APPLY`、`APP_MQ_CREDENTIALS_APPLY` 同时存在。 - -**Step 3: 写非法组合测试** -覆盖 `INDIRECT + TLQ`、`ENTERPRISE + RABBITMQ_TLQ` 被拒绝。 - -**Step 4: 运行定向测试,确认红灯** -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: 至少新增用例失败。 - -### Task 3: 实现服务层校验和编排 - -**Files:** -- Modify: `src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `src/main/resources/initplan/step-command-profiles.json` - -**Step 1: 调整标准版允许枚举** -按 `productType` 区分 `ENTERPRISE` 与 `INDIRECT`。 - -**Step 2: 调整标准版 license 校验** -`ENTERPRISE + TLQ` 与 `INDIRECT + RABBITMQ_TLQ` 都要求 `tlqLicenseFileId`。 - -**Step 3: 新增 `TLQ_CONF_APPLY` 编排** -更新 `defaultSteps` 和命令模板。 - -**Step 4: 运行服务层测试,确认绿灯** -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: PASS - -### Task 4: 先补执行器失败测试 - -**Files:** -- Modify: `src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: 写 ENTERPRISE TLQ 下 RabbitMQ 应用配置应跳过的测试** - -**Step 2: 写 INDIRECT RABBITMQ_TLQ 下 RabbitMQ 用户步骤应执行的测试** - -**Step 3: 写 `TLQ_CONF_APPLY` 命令解析或任务步骤断言测试** - -**Step 4: 运行定向测试,确认红灯** -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: 至少新增用例失败。 - -### Task 5: 实现执行器条件修正 - -**Files:** -- Modify: `src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Modify: `src/main/java/com/cisd/tms/modules/init/config/InitCommandProfileService.java`(如需补充注释/兼容逻辑) - -**Step 1: 抽取标准版 RabbitMQ 是否启用的判断** -- `ENTERPRISE`: 仅 `RABBITMQ` -- `INDIRECT`: `RABBITMQ` 和 `RABBITMQ_TLQ` - -**Step 2: 修正 `MQ_USER_APPLY` / `MQ_QUEUE_APPLY` 条件** - -**Step 3: 修正 `APP_MQ_CREDENTIALS_APPLY` 条件** - -**Step 4: 运行执行器测试,确认绿灯** -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: PASS - -### Task 6: 同步 OpenAPI 文档 - -**Files:** -- Modify: `docs/openapi/cisd-init.openapi.yaml` -- Modify: `docs/openapi/cisd-init.openapi.json` - -**Step 1: 更新 `mqType` 描述** -明确不同产品的合法取值。 - -**Step 2: 更新请求示例和步骤含义说明** -体现 `TLQ_CONF_APPLY` 与 `INDIRECT` 的双通道模式。 - -### Task 7: 完整验证 - -**Files:** -- Verify only - -**Step 1: 运行模块定向测试** -Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 2: 运行编译验证** -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 3: 人工检查关键路径** -检查 `ENTERPRISE + TLQ`、`INDIRECT + RABBITMQ_TLQ` 的任务步骤和命令模板。 diff --git a/docs/plans/2026-03-09-auto-deploy-refactor.md b/docs/plans/2026-03-09-auto-deploy-refactor.md deleted file mode 100644 index 5182bdd..0000000 --- a/docs/plans/2026-03-09-auto-deploy-refactor.md +++ /dev/null @@ -1,289 +0,0 @@ -# CIPS Auto Deployment Refactor Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** 在保留“基础环境预置”的前提下,将 CISD/CIPS 初始化从“cpconfig.cfg 驱动 vendor shell”逐步升级为“TMS 后端接管客户化渲染、输出物管理和执行编排”的自动化部署流程。 - -**Architecture:** 运维继续负责操作系统、目录、基础软件、介质上传解压、数据库和中间件平台级账号密码等与客户无关的预置动作;TMS 负责根据前端参数生成部署上下文,输出渲染后的配置和 SQL,按版本/支持方式编排客户化初始化步骤,并产出可审计的日志、配置快照和结果摘要。vendor 原始脚本默认只读,优先采用 staging 临时渲染执行,而不是直接改写介质本体。 - -**Tech Stack:** Spring Boot 3, Shell staging execution, 模板渲染, TiDB SQL 初始化, RabbitMQ/TLQ, CMSP/CMTP, Nginx/Web 发布 - ---- - -### Task 1: 固化“预置层 / 初始化层”边界 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` - -**Step 1: 明确定义预置层** -预置层仅包含与客户参数无关的动作: -- OS 用户、用户组、目录、权限创建 -- JDK、RabbitMQ/TLQ/TiDB/Nginx 安装 -- 防火墙和服务注册 -- 安装介质上传、解压、静态资源预放置 -- 数据库账号密码、中间件管理员账号密码等平台级凭据预置 -- 许可证预置(如果出厂前已拿到) - -**Step 2: 明确定义初始化层** -初始化层仅包含客户化动作: -- 机构号 / BIC / CIPS ID / LEI -- 节点 IP / 数据库地址 -- RabbitMQ 通道账号密码 -- RabbitMQ 用户 / 队列 / VHost 初始化 -- TLQ 配置替换 -- SQL 渲染与导库编排 -- CMSP / CMTP / filetrans 配置渲染 -- Nginx upstream / organization.json / Web 发布 -- 服务启动与验收 - -**Step 3: 删除“初始化阶段执行预置脚本”的需求** -以下脚本只保留为预置脚本,不纳入 TMS 初始化主流程: -- `setpd.sh` -- `opencport.sh` -- `install_newpackage.sh` -- `setrabqstart.sh` -- `setxsd.sh` -- `setngservice.sh` -- `pongx.sh` - -### Task 2: 固化部署上下文模型 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` - -**Step 1: 区分“前端输入参数”和“后端部署上下文”** -前端输入参数只承载业务输入;后端部署上下文承载可直接渲染文件和执行脚本的派生值。 - -**Step 2: 部署上下文仅保留初始化阶段所需客户化字段** -部署上下文至少应包含: -- `productType` -- `supportMode` -- `myCipsIdOrBic` -- `mq01Ip` -- `mq02Ip` -- `app01Ip` -- `app02Ip` -- `dbIp` -- `bicCode` -- `cipsId` -- `leiCode` -- `organizationNameCn` -- `organizationNameEn` -- `signVendor` -- `signIp` -- `signPort` -- `signDn` -- `signPasswordEnc` - -**Step 3: 平台级凭据不进入初始化上下文** -以下内容由预置层提供,不作为初始化接口输入: -- 数据库用户名 / 密码 -- RabbitMQ 管理员账号 / 密码 -- TiDB 管理员账号 / 密码 - -**Step 4: supportMode 显式按产品定义** -- `ENTERPRISE`: `RABBITMQ` / `TLQ` -- `INDIRECT`: `RABBITMQ` / `RABBITMQ_TLQ` -- `DIRECT`: `RABBITMQ_TLQ` / `RABBITMQ_CFMQ` - -### Task 3: 优先接管数据库初始化 - -**Status (2026-03-09):** 标准版已完成第一阶段落地,初始化编排已拆为 `DB_RENDER -> DB_APPLY`,并在 task staging 目录生成渲染后 SQL 包;后续仍需补强真实导库命令与结果校验。 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setsql.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/CMEP-DML.sql` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/sql_script_tmp/CMTP-01-raq.sql` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sql_script/sql_script_tmp/CMTP-01-tlq.sql` - -**Step 1: 让后端输出渲染后的 SQL 包** -输出至少包含: -- `CMTP-01.sql` -- `CMEP-DML.sql` -- 其他导库所需脚本快照 - -**Step 2: 数据库导入凭据继续由预置层提供** -初始化阶段不再输入和修改数据库账号密码;TMS 只负责: -- 渲染 SQL -- 组织导入顺序 -- 记录执行结果 - -**Step 3: DB_INIT 从“纯脚本黑盒”升级为“渲染 + 执行”双阶段** -拆成: -- `DB_RENDER` -- `DB_APPLY` - -**Step 4: 保留 vendor 导库脚本作为执行器,而不是模板引擎** -如果短期不能完全替代 `setsql.sh`,则至少做到: -- 模板由后端渲染 -- vendor 脚本只负责导入,不再负责替换占位符 - -### Task 4: 接管应用配置输出物 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setsptp.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/application-prd-ci01.properties` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmtp/01/application-prd-ci01.properties` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/filetrans.properties` - -**Step 1: 后端直接输出以下配置快照** -- `application-prd*.properties` -- `filetrans.properties` -- 标准版 RabbitMQ 通道账号密码回写结果 - -**Step 2: 数据库连接凭据保持预置,不由初始化阶段改写** -应用配置接管范围仅覆盖客户化字段,不覆盖预置层数据库连接凭据。 - -**Step 3: 将 setsptp.sh 从“渲染 + 拷贝”降级为“拷贝器”** -短期目标: -- 配置替换由后端完成 -- `setsptp.sh` 仅做 JAR / 目录拷贝 - -**Step 4: 禁止敏感信息输出到步骤日志** -渲染日志中不得出现密码明文或密文。 - -### Task 5: 接管 Nginx / Web 客户化 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/setngx.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setweb.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/nginx.conf` - -**Step 1: 新增 Nginx/Web 相关步骤** -至少新增: -- `NGINX_CONFIG_APPLY` -- `WEB_CONFIG_APPLY` - -**Step 2: 后端渲染输出物** -- `nginx.conf` -- `organization.json` -- Web 发布目录快照或发布日志 - -**Step 3: 不再把 setweb.sh 作为首批高收益改造对象本体** -优先由后端接管组织名称和 nginx upstream 渲染,再决定是否保留 `setweb.sh` 作为拷贝器。 - -### Task 6: 建立显式启动顺序 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sh/sh/stcmep_cent.sh` - -**Step 1: 将“部署”和“启动”拆开** -当前 `DEPLOY_RECEIVER` 不能同时承载“拷贝应用”和“启动服务”两种职责。 - -**Step 2: 新增启动步骤** -建议新增: -- `START_CMSP_CMTP` -- `START_NGINX` -- `POST_CHECK` - -**Step 3: 定义启动顺序** -推荐顺序: -1. 参数校验 -2. 渲染配置和 SQL -3. 准备 license -4. 初始化 RabbitMQ / TLQ -5. 初始化数据库 -6. 下发 CMSP / CMTP 配置 -7. 下发 Nginx / Web 配置 -8. 启动 CMSP / CMTP -9. 启动 Nginx -10. 验收检查 - -### Task 7: 建立失败边界和输出物 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` - -**Step 1: 明确失败即停边界** -- MQ 初始化失败后停止后续步骤 -- 数据库导入失败后不启动应用 -- 应用配置失败后不覆盖旧版本 -- Web 发布失败不影响已启动后台服务 - -**Step 2: 输出四类审计产物** -每次部署任务至少输出: -- 渲染后的配置快照 -- 渲染后的 SQL 包 -- 步骤执行日志 -- 最终部署结果摘要 - -### Task 8: 第一批高收益实施顺序 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: 第一优先级** -- 标准版 SQL 渲染输出物 -- DB_INIT 拆分为渲染与执行 -- 数据库导入结果可审计化 - -**Step 2: 第二优先级** -- CMSP / CMTP / filetrans 配置输出物 -- RabbitMQ / TLQ 初始化后的验收 - -**Step 3: 第三优先级** -- Nginx / Web 渲染与发布 -- 显式启动顺序和启动后检查 - -### Task 9: 验收标准 - -**Files:** -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(企业信创版)-V1.3.2.pdf` - -**Step 1: 参数层验收** -确认后端输入能完整覆盖初始化阶段真正需要的客户化字段,特别是: -- 支持方式 -- 组织名称 -- Nginx/Web 所需字段 -- RabbitMQ 通道账号密码 - -**Step 2: 配置层验收** -确认输出物中不再残留以下占位符: -- `AAAABBBBXXX` -- `sptp.01app.ip` -- `sptp.02app.ip` -- `sptp.01db.ip` -- `01tlq.ip` -- `02tlq.ip` -- `mybiccode` -- `mycipsid` -- `myleicode` - -**Step 3: 部署层验收** -确认: -- MQ / TLQ 正常可连 -- TiDB 库和 schema 正常创建 -- CMSP / CMTP 正常启动 -- Nginx 正常代理 -- Web 首页可访问 -- `organization.json` 为客户实际机构名称 - -### Task 10: 非目标项 - -**Step 1: 明确本轮不做** -以下内容不作为本轮主线: -- 大规模直接修改 vendor 原始脚本 -- 修改介质 readme/document 作为交付主成果 -- 将所有 cpconfig 依赖一次性彻底移除 -- 将平台级凭据纳入初始化接口输入 - -**Step 2: 后续演进原则** -优先让 TMS 接管“产物和编排”,再逐步削弱 vendor shell 的模板职责。 diff --git a/docs/plans/2026-03-09-standard-db-render-apply-plan.md b/docs/plans/2026-03-09-standard-db-render-apply-plan.md deleted file mode 100644 index 051acd6..0000000 --- a/docs/plans/2026-03-09-standard-db-render-apply-plan.md +++ /dev/null @@ -1,175 +0,0 @@ -# Standard DB Render Apply Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** 将标准版初始化中的数据库步骤从黑盒 `DB_INIT` 拆分为 `DB_RENDER` 和 `DB_APPLY`,生成可审计的 SQL 输出物,并保留数据库凭据在预制层处理。 - -**Architecture:** 标准版步骤编排改为先在 task staging 目录生成渲染后的 SQL 包,再由单独的 `DB_APPLY` 步骤将 SQL 包落位到标准收发器数据库加载目录,并按预置命令执行导库。渲染逻辑直接基于 `sql_script_tmp` 模板和 `CMEP-DML.sql/CMEP.sql`,不依赖 vendor 脚本副作用,也不修改 vendor 原始介质。 - -**Tech Stack:** Java 17, Spring Boot 3.5, Jackson, JUnit 5, Maven - ---- - -### Task 1: 固化步骤编排与计划文档 - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-standard-db-render-apply-plan.md` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Write the failing test** - -在 `InitServiceTest` 增加标准版断言: -- `ENTERPRISE + RABBITMQ` 不再包含 `DB_INIT` -- 改为包含 `DB_RENDER` 和 `DB_APPLY` -- `ENTERPRISE + TLQ`、`INDIRECT + RABBITMQ`、`INDIRECT + RABBITMQ_TLQ` 同样断言 - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: FAIL,提示仍存在 `DB_INIT` 或缺少 `DB_RENDER/DB_APPLY` - -**Step 3: Write minimal implementation** - -修改 `InitService.defaultSteps()` 与 `step-command-profiles.json`: -- 标准版统一把 `DB_INIT` 替换成 `DB_RENDER`、`DB_APPLY` -- 直参版保持 `DB_INIT` -- 标准版 `DB_RENDER` 使用 `internal::db_render` -- 标准版 `DB_APPLY` 使用 `internal::db_apply` - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: PASS - -### Task 2: 先写标准版 SQL 渲染失败用例 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` - -**Step 1: Write the failing test** - -新增两个执行器测试: -- `shouldRenderStandardDatabaseSqlPackageForEnterpriseRabbitmq` - - 在临时目录准备 `cpconfig.cfg`、`sql_script/CMEP-DML.sql`、`sql_script/CMEP.sql`、`sql_script/SCHEMA-DDL.sql`、`sql_script/UP-ORG-INFO.sql`、`sql_script/sql_script_tmp/CMTP-01-raq.sql` - - 执行 `internal::db_render` - - 断言 staging 下存在 `db/sql/CMTP-01.sql`、`CMEP-DML.sql`、`CMEP.sql` 等文件 - - 断言 `AAAABBBBXXX`、`01tlq.ip`、`02tlq.ip`、`sptp.01app.ip` 被替换 -- `shouldApplyStandardDatabaseSqlPackageToLoadDir` - - 基于上一步产物执行 `internal::db_apply` - - 断言 SQL 被复制到 configured load dir - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: FAIL,提示不支持 `db_render/db_apply` 或目标文件不存在 - -**Step 3: Define minimal config surface** - -为标准版数据库处理增加配置项: -- `standard-db-script-base-dir` -- `standard-db-load-dir` -- `standard-db-apply-command` -- `standard-db-entry-sql-file-name` - -并在两个 `application.yml` 中补注释和默认值。 - -**Step 4: Re-run focused test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: 仍失败,但失败点只剩未实现逻辑 - -### Task 3: 实现标准版 DB_RENDER - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Add internal step dispatch** - -在 `executeInternal()` 新增: -- `case "db_render" -> executeStandardDbRender(task, step)` - -**Step 2: Implement render behavior** - -新增最小实现: -- 仅对标准版生效;直参版返回 skipped -- 从 `standard-db-script-base-dir` 读取: - - `sql_script/CMEP-DML.sql` - - `sql_script/CMEP.sql` - - `sql_script/SCHEMA-DDL.sql` - - `sql_script/UP-ORG-INFO.sql` - - `sql_script/sql_script_tmp/CMTP-01-raq.sql` 或 `CMTP-01-tlq.sql` -- 渲染输出到 `staging//db/sql/` -- 输出文件名固定为: - - `CMEP-DML.sql` - - `CMEP.sql` - - `SCHEMA-DDL.sql` - - `UP-ORG-INFO.sql` - - `CMTP-01.sql` -- 渲染规则复用 `buildStandardReplacements()`,并补充 SQL 占位映射: - - `AAAABBBBXXX -> orgCode` - - `01tlq.ip -> mq_01_ip` - - `02tlq.ip -> mq_02_ip` - - `sptp.01app.ip -> sptp_01app_ip` - - `sptp.02app.ip -> sptp_02app_ip` - - `mybiccode/mycipsid/myleicode -> 对应机构号映射` -- `CMEP.sql` 里的 `source /home/cmep4i/mysql/loadfilepath/...` 保持不变,不在渲染阶段改路径 - -**Step 3: Run render test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldRenderStandardDatabaseSqlPackageForEnterpriseRabbitmq test` -Expected: PASS - -### Task 4: 实现标准版 DB_APPLY - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Add internal step dispatch** - -在 `executeInternal()` 新增: -- `case "db_apply" -> executeStandardDbApply(task, step)` - -**Step 2: Implement apply behavior** - -最小实现: -- 仅对标准版生效;直参版返回 skipped -- 从 `staging//db/sql/` 读取渲染后 SQL 包 -- 复制到 `standard-db-load-dir` -- `SIMULATE` 模式只校验 staging 产物存在并返回 success -- `LOCAL` 模式: - - 若 `standard-db-apply-command` 为空,只做落位并返回 success - - 若不为空,则以该命令执行导库,工作目录指向 `standard-db-load-dir` -- 成功日志中明确输出 staging 路径、load dir、是否执行导库命令 - -**Step 3: Run apply test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldApplyStandardDatabaseSqlPackageToLoadDir test` -Expected: PASS - -### Task 5: 全量回归与最小文档同步 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Sync plan wording** - -在重构计划中把 Task 3 结果更新为已实现方向:标准版数据库改为 `DB_RENDER / DB_APPLY`。 - -**Step 2: Run targeted tests** - -Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 3: Run compile verification** - -Run: `mvn -q -DskipTests compile` -Expected: PASS diff --git a/docs/plans/2026-03-10-deployment-doc-zh-plan.md b/docs/plans/2026-03-10-deployment-doc-zh-plan.md deleted file mode 100644 index 5159164..0000000 --- a/docs/plans/2026-03-10-deployment-doc-zh-plan.md +++ /dev/null @@ -1,51 +0,0 @@ -# Deployment Doc Chinese Localization Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Convert the full TMS deployment manual and deployment-related README sections to Chinese while preserving commands, paths, config keys, and interface names. - -**Architecture:** Keep the existing document structure and only localize human-readable prose. Do not change command examples, file paths, YAML keys, API paths, or script names. Limit the scope to `docs/deployment/tms-deployment.md` and the deployment-related part of `README.md`. - -**Tech Stack:** Markdown documentation - ---- - -### Task 1: Localize the deployment manual - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` - -**Step 1: Translate headings and narrative text** - -Convert the deployment manual to Chinese, preserving commands, paths, config keys, API paths, and script names. - -**Step 2: Keep structure and examples stable** - -Do not reorder sections or alter shell/YAML examples except for surrounding explanatory text. - -### Task 2: Localize deployment-related README content - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md` - -**Step 1: Translate deployment entry and notes** - -Convert the deployment guide link, Jar deployment section title, and deployment-related notes to Chinese. - -**Step 2: Avoid unrelated README changes** - -Keep non-deployment sections as-is. - -### Task 3: Consistency review - -**Files:** -- Verify only - -**Step 1: Review focused diff** - -Run: `git diff -- README.md docs/deployment/tms-deployment.md` -Expected: only prose localization changes. - -**Step 2: Spot-check for path/config drift** - -Verify commands, paths, config keys, and script names remain unchanged. diff --git a/docs/plans/2026-03-10-file-upload-fileid-design.md b/docs/plans/2026-03-10-file-upload-fileid-design.md deleted file mode 100644 index 4320614..0000000 --- a/docs/plans/2026-03-10-file-upload-fileid-design.md +++ /dev/null @@ -1,214 +0,0 @@ -# File Upload FileId Design - -**Date:** 2026-03-10 - -## Goal - -为 TMS 提供一个通用文件上传能力,前端在初始化页面选择文件后先上传,后端返回 `fileId`,初始化任务创建和执行阶段继续只引用 `fileId`,不直接传输文件流。 - -## Scope - -本设计只覆盖: -- 通用文件上传接口 -- 文件元信息记录 -- 与 CISD 初始化的 `fileId` 约定 -- 前端调用时序 - -本设计不覆盖: -- 文件下载 -- 文件删除回收 -- 秒传/去重 -- 文件内容级业务校验 -- 初始化主流程改造 - -## Current State - -当前初始化接口: -- `/api/v1/init/preview` -- `/api/v1/init/tasks` - -都只接收 JSON `InitPreviewRequest`,不接收 `multipart/form-data`。 - -当前初始化模块已经完整依赖以下 `fileId` 字段: -- `licenses.receiverLicenseFileId` -- `licenses.cfgZipFileId` -- `mq.tlqLicenseFileId` -- `mq.cfmqConfigFileId` - -当前执行器通过 `upload-base-dir/` 或 `upload-base-dir//` 解析文件。 - -## Design Choice - -采用:`通用上传接口 + 初始化继续引用 fileId` - -不采用:`初始化任务接口直接接收 MultipartFile` - -原因: -- 初始化主流程已经基于 `fileId`,继续沿用改动最小 -- 上传与初始化创建失败语义不同,拆分更清晰 -- 通用上传能力后续可被证书、升级、备份等模块复用 - -## API Design - -### 1. Upload API - -`POST /api/v1/files/upload` - -Content-Type:`multipart/form-data` - -表单字段: -- `file`: 必填,文件本体 -- `bizType`: 可选,默认 `GENERIC` - -返回示例: - -```json -{ - "success": true, - "code": 200, - "msg": "success", - "data": { - "fileId": "f_20260310_ab12cd34", - "bizType": "INIT", - "originalFilename": "cmep.license", - "contentType": "application/octet-stream", - "size": 2048, - "storagePath": "/home/tms/uploads/f_20260310_ab12cd34/cmep.license" - }, - "timestamp": 1741600000000, - "traceId": "xxx" -} -``` - -### 2. File Detail API - -`GET /api/v1/files/{fileId}` - -用于页面回显和排障,不参与初始化主链路。 - -## Storage Design - -### Storage root - -- `/home/tms/uploads` - -### Directory layout - -- `/home/tms/uploads//` -- `/home/tms/uploads//` - -这样做的原因: -- 与当前执行器解析逻辑兼容 -- 保留原始文件名,便于排查 -- 每个 `fileId` 单独目录,避免同名覆盖 - -## Database Design - -新增表:`sys_file_record` - -字段建议: -- `id` bigint pk -- `file_id` varchar(128) unique not null -- `biz_type` varchar(32) not null -- `original_filename` varchar(256) not null -- `stored_filename` varchar(256) not null -- `storage_path` varchar(512) not null -- `content_type` varchar(128) null -- `file_size` bigint not null -- `sha256` varchar(64) null -- `status` varchar(16) not null -- `create_time` datetime not null -- `update_time` datetime not null - -状态值当前只需要: -- `ACTIVE` -- `DELETED` - -## Backend Module Layout - -新增模块: - -```text -src/main/java/com/cisd/tms/modules/file -├── controller/internal -│ └── FileInternalController.java -├── dto -│ ├── FileUploadResponse.java -│ └── FileDetailResponse.java -├── entity -│ └── FileRecordEntity.java -├── repository -│ └── FileRecordRepository.java -└── service - └── FileService.java -``` - -资源文件: - -```text -src/main/resources/mapper/file/FileRecordMapper.xml -src/main/resources/db/migration/V3__create_sys_file_record.sql -``` - -## Validation Boundary - -### Upload API validates - -- 文件非空 -- 原始文件名非空 -- 文件大小不超过配置上限 -- `bizType` 枚举合法 - -### Init API continues to validate - -- `fileId` 格式 -- 按版本和 `mqType` 的必填规则 -- 执行阶段按 `fileId` 是否能找到对应文件 - -## Frontend Flow - -1. 用户在初始化页面选择文件 -2. 前端立即调用上传接口 -3. 上传成功后拿到 `fileId` -4. 前端将 `fileId` 保存到表单状态 -5. 用户点击“预检”或“创建任务”时,仅提交 JSON - -字段映射: -- 收发器 license -> `licenses.receiverLicenseFileId` -- TLQ 配置/许可证 -> `mq.tlqLicenseFileId` -- CFMQ 配置 -> `mq.cfmqConfigFileId` -- 直参 cfg 包 -> `licenses.cfgZipFileId` - -## Configuration - -建议新增: - -```yaml -tms: - file: - upload-base-dir: /home/tms/uploads - max-file-size-mb: 50 -``` - -后续可考虑让初始化执行器复用同一配置根,而不是再单独维护一份路径配置。 - -## Risks - -1. 当前初始化执行器已有 `tms.init.executor.upload-base-dir`,如果新增 `tms.file.upload-base-dir` 而两者不一致,会导致上传成功但执行阶段找不到文件。 -2. 如果上传接口只保留原始文件名而不做额外清洗,需要限制危险文件名字符。 -3. 目前不做业务文件类型校验,上传成功不代表该文件一定适合初始化使用。 - -## Recommendation - -先实现最小闭环: -- 上传接口 -- 查询接口 -- 文件元信息表 -- 与初始化 `fileId` 流程对齐 - -不在第一版加入: -- 下载 -- 删除 -- 清理任务 -- 哈希去重 -- 扩展名白名单 diff --git a/docs/plans/2026-03-10-file-upload-fileid-plan.md b/docs/plans/2026-03-10-file-upload-fileid-plan.md deleted file mode 100644 index dd8dea1..0000000 --- a/docs/plans/2026-03-10-file-upload-fileid-plan.md +++ /dev/null @@ -1,251 +0,0 @@ -# File Upload FileId Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Add a reusable file upload module that stores uploaded files under `/home/tms/uploads`, returns `fileId`, and keeps CISD initialization flowing through existing `fileId` fields. - -**Architecture:** Introduce a small `modules/file` module with internal upload and query APIs, one metadata table, and a service that owns fileId generation plus filesystem persistence. Keep the init module unchanged at the API boundary except for sharing the same upload storage root and documenting the front-end workflow. - -**Tech Stack:** Spring Boot MVC multipart upload, MyBatis-Plus repository pattern, Flyway SQL migration, JUnit 5 - ---- - -### Task 1: Add file upload persistence contract - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/db/migration/V3__create_sys_file_record.sql` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/mapper/file/FileRecordMapper.xml` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java` - -**Step 1: Write the failing test** - -Add a test that expects file metadata to be persisted with: -- generated `fileId` -- original file name -- absolute storage path -- `ACTIVE` status - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test` -Expected: FAIL because file module classes and table mapping do not exist. - -**Step 3: Write minimal implementation** - -Implement the entity, mapper/repository, and migration with only the fields needed by upload/query. - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add src/main/resources/db/migration/V3__create_sys_file_record.sql \ - src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java \ - src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java \ - src/main/resources/mapper/file/FileRecordMapper.xml \ - src/test/java/com/cisd/tms/modules/file/FileServiceTest.java -git commit -m "feat: add file upload persistence contract" -``` - -### Task 2: Implement upload service - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/service/FileService.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java` - -**Step 1: Write the failing test** - -Add tests that assert: -- uploaded file is saved under `//` -- blank file upload is rejected -- oversize upload is rejected -- returned DTO contains `fileId`, size, storagePath - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=FileServiceTest test` -Expected: FAIL because service and properties do not exist. - -**Step 3: Write minimal implementation** - -Implement: -- `fileId` generation -- file name sanitization -- directory creation -- file save -- metadata insert -- detail query by `fileId` - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=FileServiceTest test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add src/main/java/com/cisd/tms/modules/file/service/FileService.java \ - src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java \ - src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java \ - src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java \ - src/main/resources/application.yml config/application.yml.example \ - src/test/java/com/cisd/tms/modules/file/FileServiceTest.java -git commit -m "feat: implement file upload service" -``` - -### Task 3: Expose internal file APIs - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java` - -**Step 1: Write the failing test** - -Add controller tests for: -- `POST /api/v1/files/upload` -- `GET /api/v1/files/{fileId}` - -Verify upload uses multipart, returns `ApiResponse`, and query returns stored metadata. - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=FileInternalControllerTest test` -Expected: FAIL because controller does not exist. - -**Step 3: Write minimal implementation** - -Expose two endpoints only: -- upload -- detail query - -Keep them internal-only under `/api/v1/files`. - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=FileInternalControllerTest test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java \ - src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java \ - src/test/java/com/cisd/tms/modules/file/FileServiceTest.java -git commit -m "feat: expose internal file upload api" -``` - -### Task 4: Align init module with shared upload root and docs - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Write the failing test** - -Add or update tests to assert: -- init executor upload root matches the shared upload root config -- docs clearly state init APIs accept `fileId`, not multipart files -- README documents front-end flow: upload first, then create init task - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test` -Expected: FAIL because docs/config are not aligned yet. - -**Step 3: Write minimal implementation** - -Align configuration and docs without changing init request DTO semantics. - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java \ - src/main/resources/application.yml config/application.yml.example \ - docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json README.md \ - src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java -git commit -m "docs: align init fileId flow with upload api" -``` - -### Task 5: Add upload API OpenAPI spec - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java` - -**Step 1: Write the failing test** - -Add a documentation test or assertion that the upload route and response fields are present in the OpenAPI output. - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test` -Expected: FAIL because the route is not documented yet. - -**Step 3: Write minimal implementation** - -Document: -- upload API -- query API -- multipart request -- `fileId` response -- init API references to upload-first workflow - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json \ - src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java -git commit -m "docs: add file upload api spec" -``` - -### Task 6: Final verification - -**Files:** -- Verify only - -**Step 1: Run file module tests** - -Run: `mvn -q -Dtest=FileServiceTest,FileInternalControllerTest test` -Expected: PASS - -**Step 2: Run init-related tests** - -Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 3: Run compile** - -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 4: Review focused diff** - -Run: `git diff -- src/main/java/com/cisd/tms/modules/file src/main/resources/db/migration/V3__create_sys_file_record.sql src/main/resources/mapper/file src/main/resources/application.yml config/application.yml.example README.md docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json` -Expected: only file upload module, config, README, and OpenAPI/doc alignment changes. diff --git a/docs/plans/2026-03-10-init-execute-async-resume-design.md b/docs/plans/2026-03-10-init-execute-async-resume-design.md deleted file mode 100644 index 19789d4..0000000 --- a/docs/plans/2026-03-10-init-execute-async-resume-design.md +++ /dev/null @@ -1,211 +0,0 @@ -# Init Execute Async Resume Design - -**Date:** 2026-03-10 - -## Goal - -解决初始化执行接口同步阻塞导致的请求超时问题,并支持任务在失败后从第一个未成功步骤继续执行,而不是每次都从头开始。 - -## Scope - -本设计覆盖: -- `/api/v1/init/tasks/{taskId}/execute` 改为异步受理 -- 初始化任务后台执行模型 -- 步骤级断点续跑规则 -- 同一任务的重复触发保护 -- 现有查询接口与状态语义调整 - -本设计不覆盖: -- 分布式任务调度 -- 多实例间执行协调 -- 服务重启后的自动恢复调度 -- 新增前端页面 -- 初始化步骤编排本身的变更 - -## Current State - -当前执行入口是同步的: -- 控制器直接调用 `InitService.executeTask(taskId)` -- 服务层在请求线程内串行执行全部步骤 -- 任一步骤失败后立刻中断 - -当前问题有两个: -- 任务执行时间较长时,HTTP 请求容易超时 -- 再次执行时没有跳过已成功步骤的逻辑,会从第一步重新开始 - -当前已有可复用基础: -- 任务主表 `tms_init_task` -- 任务步骤表 `tms_init_task_step` -- 步骤状态字段:`PENDING` / `RUNNING` / `SUCCESS` / `FAILED` -- 现有步骤详情和日志查询接口 - -## Design Choice - -采用:`应用内异步执行 + 基于步骤状态续跑` - -不采用:`继续同步执行` - -原因: -- 无法避免请求超时 -- 与实际长耗时初始化场景不匹配 - -不采用:`数据库任务队列 + 独立 worker` - -原因: -- 当前需求重点是先解决超时和重跑问题 -- 现阶段引入完整调度系统成本过高 - -## API Design - -### Execute API - -`POST /api/v1/init/tasks/{taskId}/execute` - -接口语义调整为: -- 只负责受理执行请求 -- 不等待全部步骤完成 -- 返回当前任务快照 - -返回字段继续复用 `InitTaskExecuteResponse`,但语义变为: -- `taskId`: 任务号 -- `status`: 受理后的当前状态,通常为 `RUNNING` -- `totalSteps`: 总步骤数 -- `successSteps`: 当前已成功步骤数 - -前端后续继续通过以下接口轮询: -- `GET /api/v1/init/tasks/{taskId}` -- `GET /api/v1/init/tasks/{taskId}/steps` -- `GET /api/v1/init/tasks/{taskId}/steps/{stepNo}/log` - -## Execution Model - -### 1. Request thread - -请求线程只做以下事情: -- 校验任务存在且有步骤 -- 检查是否已经在执行中 -- 将任务状态置为 `RUNNING` -- 提交后台执行任务 -- 立即返回 - -### 2. Background worker - -后台线程负责真正串行执行步骤: -- 重新加载任务与步骤 -- 识别续跑起点 -- 逐步执行 -- 每步结束后立刻落库状态、消息、日志路径、退出码 -- 汇总任务最终状态 - -### 3. Single-task guard - -同一 `taskId` 在一个应用实例内只允许一个执行线程: -- 若任务已在本实例执行中,再次调用 `execute` 不再重复启动 -- 接口直接返回当前快照 - -实现上可使用进程内 `ConcurrentHashMap>` 或等价结构维护活动任务。 - -## Resume Rule - -再次执行时采用以下规则: - -1. 所有 `SUCCESS` 步骤直接跳过,不重跑 -2. 从第一个非 `SUCCESS` 步骤开始继续 -3. 后续步骤按原顺序执行 -4. 若本次再次失败,当前失败步骤状态记为 `FAILED`,任务状态记为 `FAILED` - -### RUNNING residue handling - -如果上一次执行过程中服务异常退出,可能残留 `RUNNING` 步骤。 - -本设计约定: -- 新一轮执行开始前,将残留 `RUNNING` 步骤视为未完成 -- 统一重置为 `FAILED` -- 续跑时从第一个非 `SUCCESS` 步骤开始 - -这样可以保留“上次停在这里”的事实,并避免把 `RUNNING` 误判为仍在健康执行。 - -## Status Semantics - -### Task status - -- `PENDING`: 任务已创建,尚未开始 -- `RUNNING`: 已受理且后台执行中 -- `SUCCESS`: 全部步骤成功 -- `FAILED`: 某一步失败并已停止 - -### Step status - -- `PENDING`: 从未执行 -- `RUNNING`: 当前正在执行 -- `SUCCESS`: 已成功,后续重试跳过 -- `FAILED`: 最近一次执行失败,后续重试从此处继续 - -## Concurrency Policy - -### Same task - -同一任务重复点击执行: -- 若本实例检测到该任务已在执行,直接返回当前状态 -- 不再启动第二个后台线程 - -### Different tasks - -不同任务是否允许并发执行,第一版保持当前默认: -- 允许不同 `taskId` 并行受理 -- 不额外加全局串行锁 - -原因: -- 当前需求只明确要求单任务避免重入 -- 是否需要全局串行,取决于目标主机资源和脚本互斥关系,后续再单独设计 - -## Data Changes - -本设计优先复用现有表结构,不新增表字段。 - -依赖现有字段即可表达: -- 任务当前状态 -- 步骤当前状态 -- 失败消息 -- 日志路径 -- 退出码 - -## Testing Strategy - -需要补的测试重点: - -1. 异步受理 -- `execute` 调用应快速返回 -- 后台线程继续推进步骤状态 - -2. 失败后续跑 -- 首次执行在某步失败 -- 再次执行时跳过已 `SUCCESS` 步骤 -- 从失败步骤重新执行并继续后续步骤 - -3. 残留 `RUNNING` -- 构造上一次异常中断留下的 `RUNNING` 步骤 -- 重试时应从该步骤继续 - -4. 单任务重复触发保护 -- 同一个 `taskId` 在执行中再次调用 -- 不应重复启动第二个执行线程 - -## Risks - -1. 应用内异步执行依赖当前进程存活,若服务重启,运行中的任务不会自动恢复。 -2. 若底层初始化脚本本身不具备完全幂等性,虽然步骤级跳过已成功步骤可以减少重复执行,但失败步骤重试仍可能触发环境冲突。 -3. 当前只做单实例内去重;若后续部署多实例,需要补分布式锁或数据库抢占机制。 - -## Recommendation - -先实现最小闭环: -- `execute` 异步受理 -- 单任务进程内防重入 -- 从第一个非 `SUCCESS` 步骤续跑 -- 残留 `RUNNING` 视为失败点恢复 - -不在第一版加入: -- 分布式调度 -- 自动恢复未完成任务 -- 新状态枚举或额外任务队列表 diff --git a/docs/plans/2026-03-10-init-execute-async-resume-plan.md b/docs/plans/2026-03-10-init-execute-async-resume-plan.md deleted file mode 100644 index 7596bf9..0000000 --- a/docs/plans/2026-03-10-init-execute-async-resume-plan.md +++ /dev/null @@ -1,188 +0,0 @@ -# Init Execute Async Resume Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Make `/api/v1/init/tasks/{taskId}/execute` return immediately after accepting work, then run init steps in the background and resume from the first non-`SUCCESS` step on retry. - -**Architecture:** Keep the existing task table and step table as the source of truth. Split `InitService.executeTask` into an accept-and-dispatch path plus a background execution path, and use existing step statuses to determine where to resume. Add a lightweight in-process guard so one `taskId` cannot be started twice concurrently in the same application instance. - -**Tech Stack:** Spring Boot service/controller layer, Java concurrency utilities, MyBatis-style repositories already present in the module, JUnit 5 - ---- - -### Task 1: Lock down current behavior with service tests - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Write the failing tests** - -Add tests that assert: -- `executeTask(taskId)` returns before a deliberately blocking executor finishes all steps -- retry skips steps already marked `SUCCESS` and resumes from the first `FAILED` step -- residual `RUNNING` steps are treated as the resume point on retry -- duplicate execute calls for the same running task do not launch a second execution - -**Step 2: Run tests to verify they fail** - -Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` -Expected: FAIL because execution is still synchronous and always starts from step 1. - -**Step 3: Write minimal test scaffolding** - -Extend the in-memory executor/repository helpers in the test file so they can: -- block on a latch or sleep -- count executed step codes -- fail a chosen step once and succeed on retry - -Do not change production code in this step. - -**Step 4: Run tests to verify RED is stable** - -Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` -Expected: FAIL with assertion mismatches that prove the new behavior is not implemented yet. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 2: Introduce async dispatch in `InitService` - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Implement minimal async acceptance path** - -Refactor `InitService` so `executeTask(taskId)`: -- loads task and steps -- returns a snapshot response quickly -- submits real work to a background executor - -Use a small in-process dispatcher owned by `InitService`: -- `ExecutorService` or equivalent -- active-task map keyed by `taskId` - -**Step 2: Keep the real execution logic in a dedicated method** - -Create a private method such as `executeTaskInBackground(taskId)` that: -- reloads task and steps from repository -- updates statuses -- runs steps serially -- persists each step result immediately -- updates final task status - -**Step 3: Run focused tests** - -Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` -Expected: PASS - -**Step 4: Refactor for readability** - -Extract helpers only if needed: -- build response snapshot -- mark task running -- remove active-task entry in `finally` - -Do not add extra features. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 3: Implement resume-from-first-non-success semantics - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Implement step selection logic** - -Before running steps in the background: -- convert residual `RUNNING` steps to `FAILED` -- skip every step already marked `SUCCESS` -- start execution at the first non-`SUCCESS` step - -Preserve current semantics after the resume point: -- mark current step `RUNNING` -- on success mark `SUCCESS` -- on failure mark `FAILED` and stop - -**Step 2: Preserve response counters** - -Ensure `successSteps` in `InitTaskExecuteResponse` reflects the current number of successful steps, including successes from earlier runs. - -**Step 3: Run focused tests** - -Run: `mvn -q -Dtest=InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test` -Expected: PASS - -**Step 4: Run the earlier async tests again** - -Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test` -Expected: PASS - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 4: Align controller and API-facing semantics - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - -**Step 1: Make the API comments and DTO semantics match async behavior** - -Update JavaDoc/comments so they describe: -- execute endpoint only accepts and starts background work -- polling should use existing detail/step/log APIs - -If needed, add a field only if tests prove it is necessary. Prefer reusing the current DTO unchanged. - -**Step 2: Run focused verification** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: PASS for all service tests, including the pre-existing create/query/execute cases. - -**Step 3: Review the controller surface** - -Check that: -- route path stays unchanged -- response wrapper stays unchanged -- no new endpoint is introduced unnecessarily - -**Step 4: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 5: Final verification - -**Files:** -- Verify only - -**Step 1: Run init service tests** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: PASS - -**Step 2: Run init executor regression tests touched by earlier behavior changes** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldInjectDatabaseCredentialsWhenExecutingStandardDbApplyCommand,ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates,ConfigurableInitStepExecutorTest#shouldStartStandardCmspCmtpWithConfiguredCommand test` -Expected: PASS - -**Step 3: Run compile** - -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 4: Review focused diff** - -Run: `git diff -- src/main/java/com/cisd/tms/modules/init/service/InitService.java src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java docs/plans/2026-03-10-init-execute-async-resume-design.md docs/plans/2026-03-10-init-execute-async-resume-plan.md` -Expected: only async-dispatch, resume logic, and related documentation changes. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. diff --git a/docs/plans/2026-03-10-standard-init-script-templates-plan.md b/docs/plans/2026-03-10-standard-init-script-templates-plan.md deleted file mode 100644 index edac172..0000000 --- a/docs/plans/2026-03-10-standard-init-script-templates-plan.md +++ /dev/null @@ -1,115 +0,0 @@ -# Standard Init Script Templates Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Add standard CISD post-init script templates to the repository and document how TMS should reference them after deployment to `/home/tms/bin`. - -**Architecture:** Keep the runtime command model unchanged in TMS. Add script templates under the repository so deployment has a clear source of truth, then point `application.yml.example` and `README.md` to the deployed absolute paths. Tests only verify the repository artifacts and expected command content, not real database or nginx execution. - -**Tech Stack:** Shell scripts, Spring Boot config examples, JUnit 5 filesystem assertions - ---- - -### Task 1: Add repository script templates - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/apply_standard_db.sh` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/start_standard_apps.sh` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/start_standard_nginx.sh` -- Create: `/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/check_standard_runtime.sh` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Write the failing test** - -Add tests that assert the four script files exist in `scripts/standard-init/` and contain the expected key commands: -- DB script references `SCHEMA-DDL.sql`, `CMEP.sql`, `UP-ORG-INFO.sql` -- App start script references `start_cmsp.sh` and `start_cmtp.sh` -- Nginx start script references `/usr/local/nginx/sbin/nginx` -- Post-check script references CMSP/CMTP/nginx process checks and `organization.json` - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates test` -Expected: FAIL because the scripts do not exist yet. - -**Step 3: Write minimal implementation** - -Create the four scripts with: -- `#!/bin/bash` -- `set -euo pipefail` -- environment variable placeholders for preset credentials where needed -- comments limited to critical operational assumptions - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add scripts/standard-init src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java -git commit -m "feat: add standard init script templates" -``` - -### Task 2: Wire deployment-facing config examples - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Write the failing test** - -Add a test that asserts: -- `application.yml.example` points the four command properties to `/home/tms/bin/*.sh` -- `README.md` documents the repository source path `scripts/standard-init/` and the target deploy path `/home/tms/bin` - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: FAIL because the docs/config are not updated yet. - -**Step 3: Write minimal implementation** - -Update example config and README with: -- exact deployed command values -- copy/deploy note from `scripts/standard-init/` to `/home/tms/bin` -- required environment variables for DB script - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: PASS - -**Step 5: Commit** - -```bash -git add config/application.yml.example README.md src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java -git commit -m "docs: wire standard init script template deployment" -``` - -### Task 3: Final verification - -**Files:** -- Verify only - -**Step 1: Run focused tests** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 2: Run init test suite** - -Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 3: Run compile** - -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 4: Review git diff** - -Run: `git diff -- scripts/standard-init config/application.yml.example README.md src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -Expected: only script templates, config example, README, and tests changed. diff --git a/docs/plans/2026-03-10-standard-post-deploy-completion-plan.md b/docs/plans/2026-03-10-standard-post-deploy-completion-plan.md deleted file mode 100644 index 911d595..0000000 --- a/docs/plans/2026-03-10-standard-post-deploy-completion-plan.md +++ /dev/null @@ -1,249 +0,0 @@ -# Standard Post Deploy Completion Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** 补齐标准版初始化在部署文档后半段缺失的动作,包括真实导库、CMSP/CMTP 启动与检查、nginx 配置与启动、WEB 发布。 - -**Architecture:** 保持“预置层负责基础安装与平台凭据,初始化层负责客户化和运行配置”边界不变。TMS 继续负责生成配置和 SQL 输出物,并在标准版流程中新增后半段步骤:真实导库、应用启动、nginx 配置与启动、WEB 发布、启动后检查。vendor 原始脚本继续只读,优先通过 staging 配置和显式命令编排补齐流程,而不扩散成新的黑盒主导链路。 - -**Tech Stack:** Java 17, Spring Boot 3.5, Jackson, JUnit 5, Maven, Shell command orchestration - ---- - -### Task 1: 固化标准版后半段步骤编排 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/initplan/step-command-profiles.json` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(企业信创版)-V1.3.2.doc` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(间参版)-V1.3.2/document/CIPS标准收发器安装部署手册1.0(金融机构信创版)-V1.3.2.doc` - -**Step 1: Write the failing test** - -在 `InitServiceTest` 新增标准版步骤断言: -- `ENTERPRISE + RABBITMQ` 包含:`DB_RENDER`、`DB_APPLY`、`DEPLOY_RECEIVER`、`NGINX_CONFIG_APPLY`、`WEB_CONFIG_APPLY`、`START_CMSP_CMTP`、`START_NGINX`、`POST_CHECK` -- `ENTERPRISE + TLQ` 同样包含上述后半段步骤 -- `INDIRECT + RABBITMQ`、`INDIRECT + RABBITMQ_TLQ` 同样断言 -- 直参版仍不包含这些标准版步骤 - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: FAIL,提示步骤未生成 - -**Step 3: Write minimal implementation** - -修改 `InitService.defaultSteps()` 和 `step-command-profiles.json`: -- 在标准版 `DEPLOY_RECEIVER` 后追加: - - `NGINX_CONFIG_APPLY` - - `WEB_CONFIG_APPLY` - - `START_CMSP_CMTP` - - `START_NGINX` - - `POST_CHECK` -- 命令模板统一先挂到 internal step: - - `internal::nginx_config_apply` - - `internal::web_config_apply` - - `internal::start_cmsp_cmtp` - - `internal::start_nginx` - - `internal::post_check` - -**Step 4: Run test to verify it passes** - -Run: `mvn -q -Dtest=InitServiceTest test` -Expected: PASS - -### Task 2: 增加配置面与失败测试 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Write the failing tests** - -新增执行器测试: -- `shouldApplyStandardNginxConfigFromTemplate` -- `shouldPublishStandardWebAssetsAndOrganizationJson` -- `shouldStartStandardCmspCmtpWithConfiguredCommand` -- `shouldStartStandardNginxWithConfiguredCommand` -- `shouldRunStandardPostCheck` - -测试目标: -- `NGINX_CONFIG_APPLY` 会输出替换后的 `nginx.conf` -- `WEB_CONFIG_APPLY` 会生成 `organization.json` 并发布 `front.zip` 内容 -- `START_CMSP_CMTP` 会调用预置启动命令或脚本 -- `START_NGINX` 会调用 nginx 启动命令 -- `POST_CHECK` 会执行配置的检查命令并记录日志 - -**Step 2: Run test to verify it fails** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: FAIL,提示 internal step 未实现或配置缺失 - -**Step 3: Define minimal config surface** - -为标准版后半段补齐配置项: -- `standard-nginx-template-path` -- `standard-nginx-target-path` -- `standard-web-front-zip-path` -- `standard-web-work-dir` -- `standard-web-target-dir` -- `standard-web-organization-json-path` -- `standard-app-start-command` -- `standard-nginx-start-command` -- `standard-post-check-command` - -说明: -- 真实命令由环境配置注入,TMS 只编排,不硬编码具体 systemd/脚本形态 -- 默认值可沿用文档建议路径 - -**Step 4: Re-run focused test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest test` -Expected: 仍失败,但仅剩实现缺失 - -### Task 3: 实现标准版 Nginx 配置落地 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/setngx.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/software/nginx.conf` - -**Step 1: Add internal step dispatch** - -在 `executeInternal()` 新增: -- `case "nginx_config_apply" -> executeStandardNginxConfigApply(task, step)` - -**Step 2: Implement minimal behavior** - -实现逻辑: -- 仅对标准版生效 -- 读取 `standard-nginx-template-path` -- 复用 `buildStandardReplacements()` 替换 `sptp.01app.ip`、`sptp.02app.ip` -- 将渲染结果先输出到 `staging//nginx/nginx.conf` -- LOCAL 模式复制到 `standard-nginx-target-path` -- SIMULATE 模式仅产出 staging 文件 - -**Step 3: Run focused test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldApplyStandardNginxConfigFromTemplate test` -Expected: PASS - -### Task 4: 实现标准版 WEB 发布 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/toolsh/setweb.sh` - -**Step 1: Add internal step dispatch** - -在 `executeInternal()` 新增: -- `case "web_config_apply" -> executeStandardWebConfigApply(task, step)` - -**Step 2: Implement minimal behavior** - -实现逻辑: -- 仅对标准版生效 -- 从 `standard-web-front-zip-path` 读取 `front.zip` -- 解压到 `staging//web/` -- 生成 `organization.json`,内容来自 `request.orgNameCn` -- LOCAL 模式将解压产物发布到 `standard-web-target-dir` -- 同步 `organization.json` 到 `standard-web-organization-json-path` -- SIMULATE 模式仅生成 staging 产物 - -**Step 3: Run focused test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldPublishStandardWebAssetsAndOrganizationJson test` -Expected: PASS - -### Task 5: 实现标准版启动与检查 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/sh/sh/stcmep_cent.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmsp/01/start_cmsp.sh` -- Reference: `/Users/waner/Work/CISD/文档/CIPS部署文档/标准收发器安装介质及部署手册(企业信创版)-V1.3.2/cpackage/cmtp/01/start_cmtp.sh` - -**Step 1: Add internal step dispatch** - -在 `executeInternal()` 新增: -- `case "start_cmsp_cmtp" -> executeStandardStartApp(task, step)` -- `case "start_nginx" -> executeStandardStartNginx(task, step)` -- `case "post_check" -> executeStandardPostCheck(task, step)` - -**Step 2: Implement minimal behavior** - -实现逻辑: -- `START_CMSP_CMTP` - - 仅对标准版生效 - - 执行 `standard-app-start-command` -- `START_NGINX` - - 执行 `standard-nginx-start-command` -- `POST_CHECK` - - 执行 `standard-post-check-command` -- 三者都要求: - - SIMULATE 模式返回模拟成功 - - LOCAL 模式走统一 `runCommand` 逻辑 - - 日志记录命令、cwd、exit code - -**Step 3: Run focused tests** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldStartStandardCmspCmtpWithConfiguredCommand,ConfigurableInitStepExecutorTest#shouldStartStandardNginxWithConfiguredCommand,ConfigurableInitStepExecutorTest#shouldRunStandardPostCheck test` -Expected: PASS - -### Task 6: 将 DB_APPLY 收敛为“真实导库”入口 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutor.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Tighten DB_APPLY contract** - -修改 `DB_APPLY` 行为: -- 标准版 LOCAL 模式下,如果 `standard-db-apply-command` 为空,直接失败而不是跳过 -- 错误信息明确提示“导库命令未配置” - -**Step 2: Add test** - -新增测试: -- `shouldFailDbApplyWhenStandardDbApplyCommandMissingInLocalMode` -- `shouldExecuteStandardDbApplyCommandWhenConfigured` - -**Step 3: Run focused test** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldFailDbApplyWhenStandardDbApplyCommandMissingInLocalMode,ConfigurableInitStepExecutorTest#shouldExecuteStandardDbApplyCommandWhenConfigured test` -Expected: PASS - -### Task 7: 文档同步与回归验证 - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-09-auto-deploy-refactor.md` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Sync plan wording** - -将标准版初始化主链路更新为: -- `... -> DB_APPLY -> DEPLOY_RECEIVER -> NGINX_CONFIG_APPLY -> WEB_CONFIG_APPLY -> START_CMSP_CMTP -> START_NGINX -> POST_CHECK -> VERIFY` - -**Step 2: Refresh API/Doc examples if needed** - -如果接口示例中已有步骤说明,补充新增标准版后半段步骤说明。 - -**Step 3: Run targeted tests** - -Run: `mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test` -Expected: PASS - -**Step 4: Run compile verification** - -Run: `mvn -q -DskipTests compile` -Expected: PASS diff --git a/docs/plans/2026-03-10-tms-deployment-doc-design.md b/docs/plans/2026-03-10-tms-deployment-doc-design.md deleted file mode 100644 index ea1ecb7..0000000 --- a/docs/plans/2026-03-10-tms-deployment-doc-design.md +++ /dev/null @@ -1,114 +0,0 @@ -# TMS Deployment Document Design - -**Date:** 2026-03-10 - -## Goal - -维护一份面向现场部署和运维的 TMS 部署手册,覆盖 `/home/tms` 目录结构、jar 与脚本部署、配置文件、初始化依赖、文件上传目录、启动检查与常见故障定位。 - -## Audience - -- 现场运维 -- 集成交付人员 -- 后端开发/联调人员 - -## Document Style - -文档应以“可执行手册”为目标,而不是概念说明。要求: -- 直接给目录和命令 -- 标明哪些内容必须预置,哪些由 TMS 初始化处理 -- 区分标准版和直参版相关依赖,但不重复解释业务背景 -- 每节都有输入、操作、结果或检查点 - -## Scope - -纳入部署文档: -- TMS 运行环境要求 -- `/home/tms` 目录结构 -- jar、配置、脚本、上传目录部署 -- `application.yml` 关键配置说明 -- 标准版初始化脚本 `/home/tms/bin/*.sh` 的作用和依赖 -- 文件上传与 `fileId` 模型说明 -- TMS 启动、停止、状态检查 -- 初始化联调前检查 -- 常见故障与排查 - -不纳入: -- CIPS 标准收发器基础安装手册全文复述 -- 密码卡详细使用文档 -- OpenAPI 业务接口全集说明 - -## Proposed Document Location - -建议新增正式手册: -- `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` - -README 保留简版入口,完整运维说明进入该文档。 - -## Proposed Structure - -1. 文档目的与适用范围 -2. 环境要求 -3. 部署目录结构 -4. 部署物清单 -5. `/home/tms/config/application.yml` 关键配置 -6. `/home/tms/bin` 初始化脚本说明 -7. 文件上传与 `fileId` 约定 -8. 启动/停止/状态命令 -9. 初始化前置检查 -10. 常见故障排查 -11. 附录:推荐命令与检查项 - -## Key Content Decisions - -### 1. 明确边界 - -部署文档必须明确: -- TMS 只负责自身部署和 CISD 初始化编排 -- 标准收发器、RabbitMQ、TLQ、TiDB、nginx 的基础安装属于预置层 -- 初始化阶段负责客户化配置、落位、导库、发布和启动命令调用 - -### 2. 目录结构固定化 - -文档采用 `/home/tms` 作为标准路径: -- `/home/tms/tms-framework.jar` -- `/home/tms/config/application.yml` -- `/home/tms/scripts/tms.sh` -- `/home/tms/bin/*.sh` -- `/home/tms/uploads/` -- `/home/tms/logs/` -- `/home/tms/run/` -- `/home/tms/tmp/` - -### 3. 配置说明强调初始化相关参数 - -重点说明: -- `tms.file.storage.upload-base-dir` -- `tms.init.executor.*` -- 标准版脚本命令路径 -- RabbitMQ 预置管理员账号 -- 日志目录、staging 目录 - -### 4. 文件上传模型单独成节 - -必须明确: -- 初始化接口不接收 multipart 文件 -- 前端先上传文件,再使用 `fileId` -- 上传目录与初始化执行器解析规则保持一致 - -### 5. 故障排查按常见现场问题组织 - -优先纳入: -- jar 无法启动 -- `DB_APPLY` 命令为空 -- `cpconfig` 找不到 -- `fileId` 文件找不到 -- RabbitMQ 队列创建失败 -- nginx 未启动 -- WEB 未发布 - -## Output Expectation - -产出两类文档: -- `README.md` 中保留精简入口 -- `docs/deployment/tms-deployment.md` 作为完整部署手册 diff --git a/docs/plans/2026-03-10-tms-deployment-doc-plan.md b/docs/plans/2026-03-10-tms-deployment-doc-plan.md deleted file mode 100644 index faeaecc..0000000 --- a/docs/plans/2026-03-10-tms-deployment-doc-plan.md +++ /dev/null @@ -1,156 +0,0 @@ -# TMS Deployment Document Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Create a production-oriented TMS deployment manual that documents runtime files, directories, scripts, config, upload/fileId flow, and on-host verification for `/home/tms` deployments. - -**Architecture:** Keep `README.md` as the short entry point and move the full operational content into a dedicated deployment manual under `docs/deployment/`. Reuse existing runtime scripts and config examples instead of duplicating logic, and align every section with the current init/fileId implementation. - -**Tech Stack:** Markdown documentation, existing shell scripts, Spring Boot config examples - ---- - -### Task 1: Create deployment manual skeleton - -**Files:** -- Create: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md` - -**Step 1: Draft the document outline** - -Add section headers for: -- environment -- directory layout -- deployment artifacts -- config -- scripts -- file upload/fileId flow -- startup operations -- precheck -- troubleshooting - -**Step 2: Review against current repo assets** - -Verify each section maps to existing files: -- `scripts/tms.sh` -- `scripts/standard-init/*.sh` -- `config/application.yml.example` -- init/file upload config - -**Step 3: Write the initial manual content** - -Populate the outline with precise paths and commands using `/home/tms`. - -**Step 4: Link README to the new manual** - -Keep README concise and add a “see full deployment guide” link. - -### Task 2: Document deployment artifacts and directories - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` - -**Step 1: Add directory tree** - -Document: -- `/home/tms/tms-framework.jar` -- `/home/tms/config/application.yml` -- `/home/tms/scripts/tms.sh` -- `/home/tms/bin/*.sh` -- `/home/tms/uploads` -- `/home/tms/logs` -- `/home/tms/run` -- `/home/tms/tmp` - -**Step 2: Add artifact source mapping** - -State where each deployed file comes from in the repo. - -**Step 3: Add deployment commands** - -Include copy/chmod commands required on CentOS. - -### Task 3: Document config and init dependencies - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example` -- Reference: `/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml` - -**Step 1: Document mandatory config items** - -Explain required runtime settings: -- security token -- upload directory -- init executor mode -- standard script commands -- staging/log directories - -**Step 2: Document standard-init scripts** - -Describe purpose and prerequisites of: -- `apply_standard_db.sh` -- `start_standard_apps.sh` -- `start_standard_nginx.sh` -- `check_standard_runtime.sh` - -**Step 3: Document credential handling** - -Clarify which credentials stay in pre-provisioned env vars instead of `application.yml`. - -### Task 4: Document file upload and fileId flow - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` - -**Step 1: Describe upload-first workflow** - -State that init APIs do not accept multipart files and only accept `fileId`. - -**Step 2: Map init fields to uploaded files** - -Document: -- `receiverLicenseFileId` -- `tlqLicenseFileId` -- `cfmqConfigFileId` -- `cfgZipFileId` - -**Step 3: Explain storage layout** - -Describe `/home/tms/uploads//` and how the init executor resolves files. - -### Task 5: Add operations and troubleshooting sections - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md` - -**Step 1: Add start/stop/status commands** - -Document `tms.sh` usage and log locations. - -**Step 2: Add precheck guidance** - -Reference `scripts/cisd_init_precheck.sh` and describe expected pass/fail output. - -**Step 3: Add troubleshooting cases** - -Document diagnosis steps for: -- `standardDbApplyCommand is blank` -- `cpconfig not found` -- uploaded file not found by `fileId` -- RabbitMQ command/path errors -- WEB/NGINX publish/start issues - -### Task 6: Final review - -**Files:** -- Verify only - -**Step 1: Read the final manual top to bottom** - -Check for mismatches against current code/scripts/config. - -**Step 2: Review focused diff** - -Run: `git diff -- README.md docs/deployment/tms-deployment.md` -Expected: only deployment documentation changes. diff --git a/docs/plans/2026-03-11-controller-internal-convention-removal-design.md b/docs/plans/2026-03-11-controller-internal-convention-removal-design.md deleted file mode 100644 index 39baeb0..0000000 --- a/docs/plans/2026-03-11-controller-internal-convention-removal-design.md +++ /dev/null @@ -1,135 +0,0 @@ -# Controller Internal Convention Removal Design - -**Date:** 2026-03-11 - -## Goal - -去掉“非 openapi 接口必须使用 `controller/internal` 包和 `*InternalController` 命名”的项目约定,将内部业务接口控制器统一收敛到中性 `controller` 包和 `*Controller` 类名,同时保持现有 URL、鉴权和 Swagger 暴露行为完全不变。 - -## Scope - -本设计覆盖: -- `controller/internal` -> `controller` 的包路径调整 -- `*InternalController` -> `*Controller` 的类名调整 -- 测试引用、README、结构说明、命名约定同步更新 - -本设计不覆盖: -- `/api/**` 与 `/openapi/**` 路径变更 -- DTO 包结构调整 -- 鉴权规则变更 -- `openapi` 控制器命名风格调整 -- service/repository 结构重构 - -## Current State - -当前仓库对内部接口有一套强命名约定: -- 内部业务接口通常命名为 `*InternalController` -- 其中部分模块控制器位于 `controller/internal` -- README 明确规定:`Internal API controllers only in */controller/internal` - -实际代码状态并不统一: -- `auth`、`device`、`init`、`system` 使用 `controller` 包,但类名仍为 `*InternalController` -- `file` 使用 `controller/internal` 包,类名为 `FileInternalController` -- `sign` 模块同时存在 `controller/internal` 和 `controller/openapi` - -这意味着“internal controller”已经被项目文档和部分代码固化,但在包结构上并未完全一致。 - -## Design Choice - -采用:`统一改为 controller + *Controller` - -不采用:`只改文档,不改代码` - -原因: -- 用户目标是去掉该设定本身,而不是仅仅弱化描述 -- 如果只改文档,现有类名和包名仍然持续强化旧约定 - -不采用:`只改类名,不改包路径` - -原因: -- `controller/internal` 目录仍会继续表达旧分层含义 -- 无法真正完成约定清理 - -不采用:`新增一套中性 Controller,保留旧类做代理` - -原因: -- 没有兼容性收益 -- 会引入重复 Bean 或重复请求映射风险 - -## Naming Rule After Change - -调整后的规则: -- `/api/**` 控制器放在 `modules/*/controller` -- `/openapi/**` 控制器继续放在 `modules/*/controller/openapi` -- 内部控制器类名使用中性 `*Controller` -- 对外接口控制器命名不强制带 `Open` 前缀,但当前已有 `OpenSignController` 可暂时保留 - -## Class Rename Plan - -建议重命名如下: -- `AuthInternalController` -> `AuthController` -- `DeviceInternalController` -> `DeviceController` -- `CryptoCardInternalController` -> `CryptoCardController` -- `InitInternalController` -> `InitController` -- `HealthInternalController` -> `HealthController` -- `InternalSignController` -> `SignController` -- `FileInternalController` -> `FileController` - -对应包路径调整: -- `modules/file/controller/internal` -> `modules/file/controller` -- `modules/sign/controller/internal` -> `modules/sign/controller` - -其余当前已在 `controller` 包下的类,仅改类名即可。 - -## Compatibility Boundary - -以下内容必须保持不变: -- `@RequestMapping` 路径 -- 所有 `/api/v1/**` 路径 -- 所有 `/openapi/**` 路径 -- `WebMvcConfig` 的拦截规则 -- Swagger/OpenAPI 文档访问路径 -- 前端、脚本、curl 示例调用路径 - -也就是说,这次是纯 Java 命名与项目约定调整,不是 API 行为调整。 - -## Security Impact - -鉴权策略不变: -- `/api/**` 继续走内部 token 拦截器 -- `/openapi/**` 继续走 openapi 签名拦截器 - -因为拦截器是基于 URL 前缀,而不是控制器类名或包名,所以控制器重命名不会影响运行时鉴权行为。 - -## Testing Strategy - -需要验证三类内容: - -1. 编译与导入 -- 测试类中的 import、`standaloneSetup(...)`、构造器引用都更新完成 - -2. 运行时边界不变 -- 控制器路径不变 -- 鉴权拦截配置不变 - -3. 文档约定更新 -- README 中模块结构和 API Boundary Rules 不再要求 `controller/internal` -- 示例结构改为 `controller + controller/openapi` - -## Risks - -1. 类名和文件路径同时重命名,容易遗漏测试 import 或文档引用。 -2. 如果存在基于类名扫描或人工 grep 的脚本,需要同步更新引用。 -3. `sign` 与 `file` 模块同时涉及包移动,若未同步修改 package 声明会导致编译失败。 - -## Recommendation - -先做最小一致性改造: -- 统一内部控制器类名为 `*Controller` -- 去掉 `controller/internal` 包 -- 更新 README、测试和约定文档 - -不在这一轮处理: -- `openapi` 控制器风格统一 -- DTO 包命名统一 -- 额外的模块结构重构 diff --git a/docs/plans/2026-03-11-controller-internal-convention-removal-plan.md b/docs/plans/2026-03-11-controller-internal-convention-removal-plan.md deleted file mode 100644 index 313bb02..0000000 --- a/docs/plans/2026-03-11-controller-internal-convention-removal-plan.md +++ /dev/null @@ -1,193 +0,0 @@ -# Controller Internal Convention Removal Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Remove the project-wide `controller/internal` and `*InternalController` convention for non-openapi APIs while keeping all request paths, authentication behavior, and Swagger exposure unchanged. - -**Architecture:** Rename internal API controllers to neutral `*Controller` names and place them under `modules/*/controller`, but leave all `@RequestMapping` values and `WebMvcConfig` interceptor rules untouched. Update tests and README so the repository no longer encodes the old naming convention as a rule. - -**Tech Stack:** Spring Boot MVC, springdoc-openapi, JUnit 5, MockMvc - ---- - -### Task 1: Lock down URL and documentation invariants with tests - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java` -- Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java` - -**Step 1: Write the failing tests** - -Adjust or add tests that assert: -- file upload/query endpoints remain `/api/v1/files/**` -- Swagger/OpenAPI docs still mention the same URLs -- README no longer contains the hard rule `Internal API controllers only in */controller/internal` - -Do not rename production classes yet. - -**Step 2: Run tests to verify they fail** - -Run: `mvn -q -Dtest=FileInternalControllerTest,ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: FAIL because tests will still reference old controller names and README still encodes the old convention. - -**Step 3: Keep the tests minimal** - -Limit assertions to: -- unchanged routes -- removed convention wording -- continued `/home/tms/bin` deployment doc assertions already covered in existing tests - -**Step 4: Run tests again to confirm stable RED** - -Run: `mvn -q -Dtest=FileInternalControllerTest,ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: FAIL for the intended naming/documentation reasons only. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 2: Rename file and sign internal controllers first - -**Files:** -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java` -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/sign/controller/internal/InternalSignController.java` -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java` - -**Step 1: Write the minimal rename** - -Rename and relocate: -- `FileInternalController` -> `FileController` -- `InternalSignController` -> `SignController` - -Move them into `modules/*/controller`. - -Keep: -- package-level Spring scanning working -- all request mappings unchanged - -**Step 2: Update tests/imports** - -Update MockMvc standalone setup and imports to use new class names. - -**Step 3: Run focused tests** - -Run: `mvn -q -Dtest=FileInternalControllerTest test` -Expected: PASS - -**Step 4: Review for accidental URL changes** - -Check that no `@RequestMapping` strings changed. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 3: Rename the remaining internal controllers - -**Files:** -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/auth/controller/AuthInternalController.java` -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/device/controller/DeviceInternalController.java` -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/device/controller/CryptoCardInternalController.java` -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java` -- Move/Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/system/controller/HealthInternalController.java` -- Modify: imports/usages that reference those class names - -**Step 1: Apply the rename set** - -Rename: -- `AuthInternalController` -> `AuthController` -- `DeviceInternalController` -> `DeviceController` -- `CryptoCardInternalController` -> `CryptoCardController` -- `InitInternalController` -> `InitController` -- `HealthInternalController` -> `HealthController` - -Keep each class in `modules/*/controller`. - -**Step 2: Update all direct references** - -Use `rg` to find and fix: -- imports -- JavaDoc mentions -- comments that name concrete classes - -**Step 3: Run focused compile/test checks** - -Run: `mvn -q -Dtest=InitServiceTest,TmsApplicationTests test` -Expected: PASS - -**Step 4: Run compile if needed** - -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 4: Remove the repository-wide convention from README and docs - -**Files:** -- Modify: `/Users/waner/Work/CISD/文档/tms-framework/README.md` -- Modify: any design/plan/doc files that are actively used and explicitly enforce `controller/internal` - -**Step 1: Rewrite the structure guidance** - -Update README so it says: -- default module layout is `controller + service + repository + entity + dto` -- external APIs may additionally use `controller/openapi` - -Remove the hard rule: -- `Internal API controllers only in */controller/internal` - -Replace it with a neutral rule: -- `/api/**` controllers live under `controller` -- `/openapi/**` controllers live under `controller/openapi` - -**Step 2: Update structure tree examples** - -Replace `controller/internal` entries in the README tree with `controller`. - -**Step 3: Run focused documentation regression** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: PASS - -**Step 4: Manual diff review** - -Run: `git diff -- README.md` -Expected: naming and structure guidance changes only, no API path changes. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. - -### Task 5: Final verification - -**Files:** -- Verify only - -**Step 1: Run controller-related tests** - -Run: `mvn -q -Dtest=FileInternalControllerTest,InitServiceTest,TmsApplicationTests test` -Expected: PASS - -**Step 2: Run documentation regression tests** - -Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentStandardInitScriptTemplateDeployment test` -Expected: PASS - -**Step 3: Run compile** - -Run: `mvn -q -DskipTests compile` -Expected: PASS - -**Step 4: Review focused diff** - -Run: `git diff -- src/main/java/com/cisd/tms/modules README.md src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java docs/plans/2026-03-11-controller-internal-convention-removal-design.md docs/plans/2026-03-11-controller-internal-convention-removal-plan.md` -Expected: only controller renames, import updates, and documentation rule changes. - -**Step 5: Commit** - -Skip commit in the current dirty workspace per user instruction. diff --git a/openapi.yml b/openapi.yml deleted file mode 100644 index 8ad567f..0000000 --- a/openapi.yml +++ /dev/null @@ -1,2427 +0,0 @@ -openapi: 3.0.3 -info: - title: CISD TMS Crypto Card Internal API (Full) - version: 1.1.0 - description: | - 覆盖 CryptoCardController 与扩展密码卡接口的全部能力。 -servers: - - url: http://localhost:8080 - description: Local - -tags: - - name: CryptoAll - description: 密码卡全量接口 - -security: - - InternalTokenAuth: [] - -paths: - /api/v1/device/crypto/agreement/data-key/ecc: - post: - tags: [CryptoAll] - summary: generateAgreementDataAndKeyEcc - operationId: generateAgreementDataAndKeyEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoGenerateAgreementDataAndKeyEccInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/agreement/session-key/ecc: - post: - tags: [CryptoAll] - summary: generateSessionKeyEcc - operationId: generateSessionKeyEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoGenerateSessionKeyEccInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/decrypt/kek: - post: - tags: [CryptoAll] - summary: decryptKek - operationId: decryptKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoSymmetricKekInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/decrypt/plain: - post: - tags: [CryptoAll] - summary: decryptPlain - operationId: decryptPlain - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoSymmetricInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/device-conf: - get: - tags: [CryptoAll] - summary: getDeviceConf - operationId: getDeviceConf - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/device-count: - get: - tags: [CryptoAll] - summary: getDeviceCount - operationId: getDeviceCount - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/device-info: - get: - tags: [CryptoAll] - summary: getDeviceInfo - operationId: getDeviceInfo - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/digest: - post: - tags: [CryptoAll] - summary: digest - operationId: digest - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoDigestInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/encrypt/kek: - post: - tags: [CryptoAll] - summary: encryptKek - operationId: encryptKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoSymmetricKekInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/encrypt/plain: - post: - tags: [CryptoAll] - summary: encryptPlain - operationId: encryptPlain - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoSymmetricInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/envelope/exchange/ecc: - post: - tags: [CryptoAll] - summary: exchangeEnvelopeEcc - operationId: exchangeEnvelopeEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoExchangeEnvelopeEccInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/envelope/exchange/rsa: - post: - tags: [CryptoAll] - summary: exchangeEnvelopeRsa - operationId: exchangeEnvelopeRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoExchangeEnvelopeRsaInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/all-key/backup: - post: - tags: [CryptoAll] - summary: backupAllKey - operationId: backupAllKey - parameters: - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/all-key/restore: - post: - tags: [CryptoAll] - summary: restoreAllKey - operationId: restoreAllKey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Base64DataRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/device/factory-reset: - post: - tags: [CryptoAll] - summary: factoryReset - operationId: factoryReset - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/device/init-identify: - post: - tags: [CryptoAll] - summary: initIdentify - operationId: initIdentify - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Base64PairRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/device/status: - get: - tags: [CryptoAll] - summary: getDeviceStatus - operationId: getDeviceStatus - parameters: - - name: statusBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/external/decrypt: - post: - tags: [CryptoAll] - summary: eccExternalDecrypt - operationId: eccExternalDecrypt - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccExternalDecryptRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/external/encrypt: - post: - tags: [CryptoAll] - summary: eccExternalEncrypt - operationId: eccExternalEncrypt - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccExternalEncryptRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/external/sign: - post: - tags: [CryptoAll] - summary: eccExternalSign - operationId: eccExternalSign - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccExternalSignRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/external/verify: - post: - tags: [CryptoAll] - summary: eccExternalVerify - operationId: eccExternalVerify - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccExternalVerifyRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/internal/sign: - post: - tags: [CryptoAll] - summary: eccInternalSign - operationId: eccInternalSign - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccInternalSignRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ecc/internal/verify: - post: - tags: [CryptoAll] - summary: eccInternalVerify - operationId: eccInternalVerify - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EccInternalVerifyRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ik/backup: - post: - tags: [CryptoAll] - summary: backupIk - operationId: backupIk - parameters: - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ik/destroy: - post: - tags: [CryptoAll] - summary: destroyIk - operationId: destroyIk - parameters: - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ik/generate: - post: - tags: [CryptoAll] - summary: generateIk - operationId: generateIk - parameters: - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ik/recover: - post: - tags: [CryptoAll] - summary: recoverIk - operationId: recoverIk - parameters: - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ik/status: - get: - tags: [CryptoAll] - summary: statusIk - operationId: statusIk - parameters: - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/backup: - post: - tags: [CryptoAll] - summary: backupKek - operationId: backupKek - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/component/export: - post: - tags: [CryptoAll] - summary: exportKekComponent - operationId: exportKekComponent - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ExportKekComponentRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/component/import: - post: - tags: [CryptoAll] - summary: importKekComponent - operationId: importKekComponent - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/KekComponentRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/delete: - post: - tags: [CryptoAll] - summary: deleteKek - operationId: deleteKek - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/import: - post: - tags: [CryptoAll] - summary: importKek - operationId: importKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportKekRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/kek/recover: - post: - tags: [CryptoAll] - summary: recoverKek - operationId: recoverKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RecoverKekRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/key/update-backed: - post: - tags: [CryptoAll] - summary: updateBackedKey - operationId: updateBackedKey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateBackedKeyRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/ecc/generate: - post: - tags: [CryptoAll] - summary: generateKeyPairEcc - operationId: generateKeyPairEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyPairRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/ecc/import: - post: - tags: [CryptoAll] - summary: importKeyPairEcc - operationId: importKeyPairEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportKeyPairRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/ecc/import-encrypted: - post: - tags: [CryptoAll] - summary: importEncryptedKeyPairEcc - operationId: importEncryptedKeyPairEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportEncKeyPairEccRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/rsa/generate: - post: - tags: [CryptoAll] - summary: generateKeyPairRsa - operationId: generateKeyPairRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyPairRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/rsa/import: - post: - tags: [CryptoAll] - summary: importKeyPairRsa - operationId: importKeyPairRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportKeyPairRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/keypair/rsa/import-encrypted: - post: - tags: [CryptoAll] - summary: importEncryptedKeyPairRsa - operationId: importEncryptedKeyPairRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportEncKeyPairRsaRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/backup: - post: - tags: [CryptoAll] - summary: backupLmk - operationId: backupLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/backup-ex: - post: - tags: [CryptoAll] - summary: backupLmkEx - operationId: backupLmkEx - parameters: - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/destroy: - post: - tags: [CryptoAll] - summary: destroyLmk - operationId: destroyLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/generate: - post: - tags: [CryptoAll] - summary: generateLmk - operationId: generateLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/load: - post: - tags: [CryptoAll] - summary: loadLmk - operationId: loadLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/recover: - post: - tags: [CryptoAll] - summary: recoverLmk - operationId: recoverLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/lmk/recover-ex: - post: - tags: [CryptoAll] - summary: recoverLmkEx - operationId: recoverLmkEx - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Base64DataRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/private-key/access-right/get: - post: - tags: [CryptoAll] - summary: getPrivateKeyAccessRight - operationId: getPrivateKeyAccessRight - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PrivateKeyAccessRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/private-key/access-right/release: - post: - tags: [CryptoAll] - summary: releasePrivateKeyAccessRight - operationId: releasePrivateKeyAccessRight - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/private-key/password/change: - post: - tags: [CryptoAll] - summary: changePrivateKeyAccessPassword - operationId: changePrivateKeyAccessPassword - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ChangePrivateKeyPasswordRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/public-key/ecc/enc/export: - get: - tags: [CryptoAll] - summary: exportEncPublicKeyEcc - operationId: exportEncPublicKeyEcc - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/public-key/ecc/sign/export: - get: - tags: [CryptoAll] - summary: exportSignPublicKeyEcc - operationId: exportSignPublicKeyEcc - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/public-key/rsa/enc/export: - get: - tags: [CryptoAll] - summary: exportEncPublicKeyRsa - operationId: exportEncPublicKeyRsa - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/public-key/rsa/sign/export: - get: - tags: [CryptoAll] - summary: exportSignPublicKeyRsa - operationId: exportSignPublicKeyRsa - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/rsa/external/private-op: - post: - tags: [CryptoAll] - summary: rsaExternalPrivateOp - operationId: rsaExternalPrivateOp - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RsaExternalPrivateKeyOpRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/rsa/external/public-op: - post: - tags: [CryptoAll] - summary: rsaExternalPublicOp - operationId: rsaExternalPublicOp - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RsaExternalPublicKeyOpRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/rsa/internal/private-op: - post: - tags: [CryptoAll] - summary: rsaInternalPrivateOp - operationId: rsaInternalPrivateOp - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RsaInternalKeyOpRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/rsa/internal/public-op: - post: - tags: [CryptoAll] - summary: rsaInternalPublicOp - operationId: rsaInternalPublicOp - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RsaInternalKeyOpRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/ecc/epk/generate: - post: - tags: [CryptoAll] - summary: generateKeyWithEpkEcc - operationId: generateKeyWithEpkEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyWithEpkEccRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/ecc/ipk/generate: - post: - tags: [CryptoAll] - summary: generateKeyWithIpkEcc - operationId: generateKeyWithIpkEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyWithIpkEccRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/ecc/isk/import: - post: - tags: [CryptoAll] - summary: importKeyWithIskEcc - operationId: importKeyWithIskEcc - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportKeyWithIskEccRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/kek/generate: - post: - tags: [CryptoAll] - summary: generateKeyWithKek - operationId: generateKeyWithKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyWithKekRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/rsa/epk/generate: - post: - tags: [CryptoAll] - summary: generateKeyWithEpkRsa - operationId: generateKeyWithEpkRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyWithEpkRsaRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/rsa/ipk/generate: - post: - tags: [CryptoAll] - summary: generateKeyWithIpkRsa - operationId: generateKeyWithIpkRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GenerateKeyWithIpkRsaRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/session-key/rsa/isk/import: - post: - tags: [CryptoAll] - summary: importKeyWithIskRsa - operationId: importKeyWithIskRsa - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ImportKeyWithIskRsaRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/certificate/generate: - post: - tags: [CryptoAll] - summary: generateCertificate - operationId: generateCertificate - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Base64DataRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/generate: - post: - tags: [CryptoAll] - summary: generateUkey - operationId: generateUkey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UkeyGenerateRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/ik-component/read: - post: - tags: [CryptoAll] - summary: readUkeyIkComponent - operationId: readUkeyIkComponent - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/KeyTypePinRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/lmk-component/read: - post: - tags: [CryptoAll] - summary: readLmkComponent - operationId: readLmkComponent - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Base64DataRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/login: - post: - tags: [CryptoAll] - summary: loginUkey - operationId: loginUkey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UkeyLoginRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/login-status: - get: - tags: [CryptoAll] - summary: loginStatus - operationId: loginStatus - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/logout-admin: - post: - tags: [CryptoAll] - summary: logoutAdmin - operationId: logoutAdmin - parameters: - - name: adminIndex - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/pin/change: - post: - tags: [CryptoAll] - summary: changeUkeyPin - operationId: changeUkeyPin - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UkeyPinChangeRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/ukey/unlock: - post: - tags: [CryptoAll] - summary: unlockUkey - operationId: unlockUkey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UkeyUnlockRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/user-key/backup: - post: - tags: [CryptoAll] - summary: backupUserKey - operationId: backupUserKey - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - - name: outBufferSize - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/user-key/delete: - post: - tags: [CryptoAll] - summary: deleteUserKey - operationId: deleteUserKey - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/user-key/ecc/status: - get: - tags: [CryptoAll] - summary: statusUserKeyEcc - operationId: statusUserKeyEcc - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/user-key/recover: - post: - tags: [CryptoAll] - summary: recoverUserKey - operationId: recoverUserKey - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RecoverUserKeyRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/ext/user-key/rsa/status: - get: - tags: [CryptoAll] - summary: statusUserKeyRsa - operationId: statusUserKeyRsa - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - - name: keyType - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/file/create: - post: - tags: [CryptoAll] - summary: createFile - operationId: createFile - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoFileCreateInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/file/delete: - post: - tags: [CryptoAll] - summary: deleteFile - operationId: deleteFile - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoFileDeleteInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/file/read: - post: - tags: [CryptoAll] - summary: readFile - operationId: readFile - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoFileReadInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/file/write: - post: - tags: [CryptoAll] - summary: writeFile - operationId: writeFile - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoFileWriteInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/hmac: - post: - tags: [CryptoAll] - summary: hmac - operationId: hmac - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoHmacInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/kek/generate: - post: - tags: [CryptoAll] - summary: generateKek - operationId: generateKek - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoGenerateKekInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/kek/status: - get: - tags: [CryptoAll] - summary: kekStatus - operationId: kekStatus - parameters: - - name: keyIndex - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/lmk/check: - get: - tags: [CryptoAll] - summary: checkLmk - operationId: checkLmk - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/lmk/seed-mac: - get: - tags: [CryptoAll] - summary: exportLmkSeedMac - operationId: exportLmkSeedMac - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/mac/plain: - post: - tags: [CryptoAll] - summary: macPlain - operationId: macPlain - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoMacInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/random: - get: - tags: [CryptoAll] - summary: random - operationId: random - parameters: - - name: length - in: query - required: true - schema: - type: integer - format: int32 - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/self-test: - post: - tags: [CryptoAll] - summary: selfTest - operationId: selfTest - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/std/keypair/ecc: - post: - tags: [CryptoAll] - summary: generateStandardEccKeyPair - operationId: generateStandardEccKeyPair - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoGenerateStandardEccKeyPairInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - - /api/v1/device/crypto/std/keypair/rsa: - post: - tags: [CryptoAll] - summary: generateStandardRsaKeyPair - operationId: generateStandardRsaKeyPair - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CryptoGenerateStandardRsaKeyPairInternalRequest' - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalError' - -components: - securitySchemes: - InternalTokenAuth: - type: apiKey - in: header - name: X-Internal-Token - - responses: - BadRequest: - description: 参数错误 - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - InternalError: - description: 业务/系统错误(含密码卡调用失败) - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponseAny' - - schemas: - ApiResponseAny: - type: object - properties: - success: - type: boolean - code: - type: integer - msg: - type: string - data: - type: object - additionalProperties: true - nullable: true - timestamp: - type: integer - format: int64 - traceId: - type: string - nullable: true - path: - type: string - nullable: true - required: [success, code, msg, timestamp] - - Base64DataRequest: - type: object - additionalProperties: true - - Base64PairRequest: - type: object - additionalProperties: true - - ChangePrivateKeyPasswordRequest: - type: object - additionalProperties: true - - CryptoDigestInternalRequest: - type: object - additionalProperties: true - - CryptoExchangeEnvelopeEccInternalRequest: - type: object - additionalProperties: true - - CryptoExchangeEnvelopeRsaInternalRequest: - type: object - additionalProperties: true - - CryptoFileCreateInternalRequest: - type: object - additionalProperties: true - - CryptoFileDeleteInternalRequest: - type: object - additionalProperties: true - - CryptoFileReadInternalRequest: - type: object - additionalProperties: true - - CryptoFileWriteInternalRequest: - type: object - additionalProperties: true - - CryptoGenerateAgreementDataAndKeyEccInternalRequest: - type: object - additionalProperties: true - - CryptoGenerateKekInternalRequest: - type: object - additionalProperties: true - - CryptoGenerateSessionKeyEccInternalRequest: - type: object - additionalProperties: true - - CryptoGenerateStandardEccKeyPairInternalRequest: - type: object - additionalProperties: true - - CryptoGenerateStandardRsaKeyPairInternalRequest: - type: object - additionalProperties: true - - CryptoHmacInternalRequest: - type: object - additionalProperties: true - - CryptoMacInternalRequest: - type: object - additionalProperties: true - - CryptoSymmetricInternalRequest: - type: object - additionalProperties: true - - CryptoSymmetricKekInternalRequest: - type: object - additionalProperties: true - - EccExternalDecryptRequest: - type: object - additionalProperties: true - - EccExternalEncryptRequest: - type: object - additionalProperties: true - - EccExternalSignRequest: - type: object - additionalProperties: true - - EccExternalVerifyRequest: - type: object - additionalProperties: true - - EccInternalSignRequest: - type: object - additionalProperties: true - - EccInternalVerifyRequest: - type: object - additionalProperties: true - - ExportKekComponentRequest: - type: object - additionalProperties: true - - GenerateKeyPairRequest: - type: object - additionalProperties: true - - GenerateKeyWithEpkEccRequest: - type: object - additionalProperties: true - - GenerateKeyWithEpkRsaRequest: - type: object - additionalProperties: true - - GenerateKeyWithIpkEccRequest: - type: object - additionalProperties: true - - GenerateKeyWithIpkRsaRequest: - type: object - additionalProperties: true - - GenerateKeyWithKekRequest: - type: object - additionalProperties: true - - ImportEncKeyPairEccRequest: - type: object - additionalProperties: true - - ImportEncKeyPairRsaRequest: - type: object - additionalProperties: true - - ImportKekRequest: - type: object - additionalProperties: true - - ImportKeyPairRequest: - type: object - additionalProperties: true - - ImportKeyWithIskEccRequest: - type: object - additionalProperties: true - - ImportKeyWithIskRsaRequest: - type: object - additionalProperties: true - - KekComponentRequest: - type: object - additionalProperties: true - - KeyTypePinRequest: - type: object - additionalProperties: true - - PrivateKeyAccessRequest: - type: object - additionalProperties: true - - RecoverKekRequest: - type: object - additionalProperties: true - - RecoverUserKeyRequest: - type: object - additionalProperties: true - - RsaExternalPrivateKeyOpRequest: - type: object - additionalProperties: true - - RsaExternalPublicKeyOpRequest: - type: object - additionalProperties: true - - RsaInternalKeyOpRequest: - type: object - additionalProperties: true - - UkeyGenerateRequest: - type: object - additionalProperties: true - - UkeyLoginRequest: - type: object - additionalProperties: true - - UkeyPinChangeRequest: - type: object - additionalProperties: true - - UkeyUnlockRequest: - type: object - additionalProperties: true - - UpdateBackedKeyRequest: - type: object - additionalProperties: true