Просмотр исходного кода

docs(simulator): 完善第三方模拟器交付手册与验收核对

Pengxy 1 день назад
Родитель
Сommit
5722d5d10d

+ 71 - 0
doc/plan/系统集成/Ai-DOP第三方系统模拟器交付验收核对.md

@@ -0,0 +1,71 @@
+# Ai-DOP 第三方系统模拟器交付验收核对(任务书 §25)
+
+> 依据:《Ai-DOP第三方系统模拟器分阶段完整执行任务书》§25 最终交付验收。
+> 取证方式:代码层(git 提交与源文件)、配置层(环境变量/配置清单)、数据层(pytest 实测 + 真实联调流水)三层交叉核对;每条结论附可重跑证据。
+
+**验收日期**:2026-10-14
+
+**测试基线**:`pytest tools/integration-simulator/tests` → **171 passed, 1 failed**(唯一失败 `test_live_schema_load_and_increment`:报错 1045 `Access denied for user 'sim_user'@'221.234.162.114'`——本机家宽出口 IP 变化未在远端 MySQL 重新授权,属环境性问题,与代码无关;该用例此前在出口 IP 授权时实测通过)。
+
+**入库提交**:
+
+| 阶段 | commit | 内容 |
+|---|---|---|
+| 第一阶段 | f63842f25 | 模拟器初版(25 文件)+ 文档索引 + Server 版本 1.0.597 |
+| 第二阶段 | 9cf23c4a7 | N1-N4 异常测试能力(+1664/-26,含 UAT 截图) |
+| 第三阶段 | 9e70ca326 | §16-§21 受控压力测试 + 实体授权探测(+2386/-2) |
+
+---
+
+## 方式甲(DB_SYNC)
+
+| 验收项 | 结论 | 证据 |
+|---|---|---|
+| 可建立和装载模拟数据库 | ✅ 通过 | `POST /api/db/ensure` + `POST /api/db/load`;真实远端 MySQL 实测建成 `sim_item`(runId 20261008143742),SHOW TABLES/COUNT 三方一致;`assert_sim_database` 库名硬闸门防误写主库 |
+| 可完成正常全链路人工测试 | ✅ 通过 | 第一阶段 F2 验收完成:对象测试页签选 DB_SYNC → 预检 → 执行 → 三层结论 + 人工核验 SQL |
+| 可完成常见异常测试 | ✅ 通过 | N1 场景目录 10 项(guide 4 + auto 6);auto 场景实测一键预置/恢复 |
+| 可生成多档数据用于压力测试 | ✅ 通过 | `LOAD_SIZES` S/M/L(100/10000/100000 行);`/api/load/limits` 实测返回 `sizes:{S:100,M:10000,L:100000}`;S 档 100 行真实装载后清理实测通过 |
+| 可核对源端行数与增量值 | ✅ 通过 | `GET /api/db/stats/{objectCode}` 返回行数与最大增量;`sourceUpdatedAt` 递增实测 |
+
+## 方式乙(API_PULL)
+
+| 验收项 | 结论 | 证据 |
+|---|---|---|
+| 可启动第三方 Mock API | ✅ 通过 | `POST /api/mock-api/start` 真实端口绑定 :8018;带 Bearer `sim-mock-token` 拉 `/api/item` 实测 200、无令牌 401;生命周期回归测试 2 条 |
+| 可完成正常全链路人工测试 | ✅ 通过 | 第一阶段 F3 验收完成:TOKEN 鉴权 + cursor 分页实测 |
+| 可切换鉴权、延迟和错误 | ✅ 通过 | NONE/TOKEN/BASIC/APIKEY 四鉴权 + 延迟/超时/空响应/坏 JSON/错误 Content-Type/强制状态码(401/403/404/429/500/503)注入 |
+| 可承受并统计 Ai-DOP 拉取压力 | ✅ 通过 | P2 Mock 压力模式:page_size/total_rows_limit/random_delay/error_rate/rate_limit + `GET /__control/load-stats`(活跃/峰值/状态分类/延迟/QPS 窗口) |
+| 请求日志已脱敏 | ✅ 通过 | 审计按 `redact_obj` 处理;`tests/test_redaction.py` 覆盖 Secret/连接串/Bearer/AccessKey 后四位 |
+
+## 方式丙(API_INBOUND)
+
+| 验收项 | 结论 | 证据 |
+|---|---|---|
+| 可完成 26 契约预检 | ✅ 通过 | `GET /api/precheck` 26 实体逐 schema 探测;`test_catalog_covers_all_26_inbound_contracts` 通过;auth-probe 实测 26 实体中 20 授权/6 未授权、probeErrors 空 |
+| 可完成七类操作 | ✅ 通过 | `inbound_client` 七类推数操作(单条/批量/snapshot 等);`test_inbound_signature` 签名金标向量 5/5 |
+| 可完成正常与异常推送测试 | ✅ 通过 | F4 正常链路(MDM_ITEM push 202);N3 17 场景逐场景实测(`mdp_inbound_request` 流水 + `mdp_stg_item` 贴源三层取证) |
+| 可配置并发、QPS、批大小和持续时间 | ✅ 通过 | 压力测试页签方式丙参数(并发/QPS/阶梯/批大小/预热/持续时间);实测 33/33 全部 202 成功 |
+| 可实时停止并导出压力报告 | ✅ 通过 | 「立即停止」+ 报告保存/导出 Markdown(脱敏);停止后指标定格(回归测试 `test_snapshot_freezes_qps_after_finish`) |
+
+## 通用
+
+| 验收项 | 结论 | 证据 |
+|---|---|---|
+| 工具只模拟第三方一侧 | ✅ 通过 | 目录边界:只读预检 `aidop_probe` + 三通道模拟提供者;不进入 Ai-DOP 菜单 |
+| 不直接写 Ai-DOP 业务表 | ✅ 通过 | 库名硬闸门(含 aidopdev/aidop_uat/aidopprod/admin/mdp 拒绝)+ host 白名单硬阻断;`tests/test_guard.py` 覆盖 |
+| 不自动修改生产配置 | ✅ 通过 | Ai-DOP 侧登记全部由人工按生成清单执行;guide 类异常场景只出指引不落库 |
+| 人工全链路步骤清晰 | ✅ 通过 | [`人工操作手册`](./Ai-DOP第三方系统模拟器人工操作手册.md) 按三方式各 8 步 + 截图(与实际页面一致,2026-10-14 截取) |
+| 测试数据有 runId | ✅ 通过 | 业务键 `SIM-{runId}-` + 入站 syncBatchId + 压测唯一 runId(实测 `LOAD-5d3141eb2967`) |
+| 凭据不落盘 | ✅ 通过 | 8 项 `AIDOP_SIM_*` 环境变量注入;config.json 只存非敏感项且 gitignore;Secret 不由页面输入/不回显/不进浏览器 |
+| 报告已脱敏 | ✅ 通过 | 三类报告(基础打通/异常 N4/压力)保存前统一 `redact_obj`;AccessKey 仅留后四位 |
+| 无后台残留负载 | ✅ 通过 | 停止后 guard `noResidual=true`(实测);连续错误自动停止 + 收尾无残留实测通过 |
+
+---
+
+## 验收结论
+
+20 项全部通过(方式甲 5/5、方式乙 5/5、方式丙 5/5、通用 8/8)。
+
+```text
+第三方系统模拟器:三种集成方式基础、异常与压力测试能力交付完成
+```

+ 280 - 0
doc/plan/系统集成/Ai-DOP第三方系统模拟器人工操作手册.md

@@ -0,0 +1,280 @@
+# Ai-DOP 第三方系统模拟器人工操作手册
+
+> 配套文档:[`分阶段完整执行任务书`](./Ai-DOP第三方系统模拟器分阶段完整执行任务书.md)(阶段与验收依据)· [`README`](../../../tools/integration-simulator/README.md)(环境准备、安装、配置、启动、故障排查)
+
+本手册按《分阶段完整执行任务书》§23 要求,分别给出三种对接方式的人工全链路操作步骤(模拟器准备 → Ai-DOP 配置 → 人工触发 → 模拟器证据 → Ai-DOP 流水 → 结果核验 → 异常恢复 → 数据清理),并补充异常测试(N1-N4)、压力测试(§16-§21)与报告脱敏(§24)操作。
+
+**安全边界(全文有效)**:模拟器只模拟第三方一侧——不写 Ai-DOP 贴源/标准/KPI 表,不修改 Ai-DOP 配置,不进入 Ai-DOP 菜单;凭据一律走环境变量、Secret 不落盘不进浏览器;Ai-DOP 侧登记全部由人工按模拟器生成的清单执行。
+
+---
+
+## 0. 阅读前提(模拟器准备,三方式通用)
+
+1. **环境**:Python 3.11+(Windows 用真实解释器)、独立 MySQL 测试实例、可访问的 Ai-DOP 开发/UAT 地址与测试租户。详见 README §1。
+2. **安装**:
+
+   ```powershell
+   cd d:\DEMONET
+   python -m venv .venv-sim
+   .venv-sim\Scripts\pip install -r tools/integration-simulator/requirements.txt
+   ```
+
+3. **配置**:
+
+   ```powershell
+   Copy-Item tools/integration-simulator/config.example.json tools/integration-simulator/config.json
+   ```
+
+   按本机修改 `aidopBaseUrl` / `mockApiPort` / `allowedTargetHosts`(config.json 只放非敏感项,已 gitignore)。
+
+4. **凭据**(环境变量,进程启动时注入,改后须重启模拟器):
+
+   | 变量 | 用途 | 必填 |
+   |---|---|---|
+   | `AIDOP_SIM_MYSQL_HOST` / `PORT` / `USER` / `PASSWORD` / `DATABASE` | 方式甲模拟库连接 | 方式甲必填 |
+   | `AIDOP_SIM_INBOUND_ACCESS_KEY` / `AIDOP_SIM_INBOUND_SECRET` | 方式丙 HMAC 签名凭据 | 方式丙必填 |
+   | `AIDOP_SIM_ADMIN_TOKEN` | 只读管理 API(可选) | 否 |
+
+   仅测方式乙(API_PULL)可全不设。
+
+5. **启动**:
+
+   ```powershell
+   .venv-sim\Scripts\python tools/integration-simulator/app.py
+   ```
+
+   控制台 `http://127.0.0.1:8017/`;Mock API 由控制台启停(默认 8018)。服务只绑 127.0.0.1,目标 host 受 `allowedTargetHosts` 白名单硬阻断。
+
+## 1. 控制台页签总览
+
+![对象测试页签](sim-manual-img/tab_run_对象测试.png)
+
+| 页签 | 用途 | 对应方式 |
+|---|---|---|
+| 对象测试 | 选对象/通道 → 加载适配样例 → 预检 → 执行 → 三层结论与人工核验 SQL | 甲/乙/丙通用 |
+| 业务场景 | 三组跨对象链路;不支持节点标红 | 演示 |
+| Mock API(API_PULL) | 启停 8018、鉴权切换、异常注入、脱敏审计 | 方式乙 |
+| 模拟 MySQL(DB_SYNC) | 建库建表、装载样例、行数/增量、配置清单、档位生成 | 方式甲 |
+| API_INBOUND | 26 契约预检、七类操作与必测用例 | 方式丙 |
+| 异常测试 | 三通道异常场景目录(10/16/17)+ N4 报告 | 甲/乙/丙 |
+| 压力测试 | 计划十项 + 开始/停止 + 实时指标 + 报告 | 甲/乙/丙 |
+| 全链路报告 | 基础打通报告(§24 三类报告之一) | 通用 |
+| 运行记录 | 最近运行(自动脱敏) | 通用 |
+| 环境安全 | 凭据加载状态、白名单、隔离约束 | 通用 |
+
+---
+
+## 2. 方式甲 DB_SYNC(数据库同步)人工全链路
+
+**链路**:模拟器 `mock_db.py` → 独立 MySQL schema `aidop_integration_sim` →(Ai-DOP 拉取)`MdpSourcePullDispatcher` → `MdpDbPullExecutor` → 贴源表。
+
+### 2.1 模拟器准备
+
+1. 打开「模拟 MySQL(DB_SYNC)」页签:
+
+   ![模拟 MySQL 页签](sim-manual-img/tab_db_模拟MySQL.png)
+
+2. 填「库名/主机」(默认 `aidop_integration_sim` / `127.0.0.1`),点 **建库建表**——内部执行 DDL(幂等),库名经硬闸门校验(非 `aidop_integration_sim` 前缀直接拒绝,防误写 Ai-DOP 主库)。
+3. 点 **装载样例**——按目录样例装载可追踪业务数据(业务键 `SIM-{runId}-`,增量列 `sourceUpdatedAt` 递增)。
+4. 在「行数与最大增量」区确认装载行数与当前最大增量值,作为后续核验基准。
+
+### 2.2 Ai-DOP 配置(人工执行)
+
+1. 点 **生成 Ai-DOP 配置清单**(`GET /api/db/aidop-config/{objectCode}`),得到建议登记项。
+2. 在 Ai-DOP 配置页人工登记:
+   - `mdp_source`:`SIM_MODE3_DB`(`system_code=SIM_MODE3`,与另两通道**不得共用 source_code**);
+   - `mdp_entity`:源表 `sim_{objectCode}`、目标贴源表、业务键、增量列 `sourceUpdatedAt`。
+3. 确认不抢占现有 T8/165/自建单等生产权威来源。
+
+### 2.3 Ai-DOP 人工触发
+
+在 Ai-DOP「数据源管理」对 `SIM_MODE3_DB` 执行拉取(或按既定调度触发)。
+
+### 2.4 模拟器证据查看
+
+- 「行数与最大增量」区查看拉取后增量是否推进;
+- 「运行记录」页签查看最近运行与三层结论。
+
+### 2.5 Ai-DOP 流水查看
+
+- Ai-DOP 拉取调度流水(`MdpSourcePullDispatcher` 运行日志);
+- 模拟库侧可用核验 SQL 直接查行数:
+
+  ```sql
+  SELECT COUNT(*), MAX(sourceUpdatedAt) FROM aidop_integration_sim.sim_item;
+  ```
+
+### 2.6 目标结果核验
+
+按「对象测试」页签执行后给出的**人工核验 SQL**,在 Ai-DOP 贴源表核对行数与业务键。三层结论不得混为一谈:HTTP 202 不代表业务全链路跑通,贴源写入与否以核验 SQL 为准。
+
+### 2.7 异常恢复
+
+「异常测试」页签 → 方式甲分组(10 个场景),每个 auto 场景带 **恢复** 按钮一键还原(重建表/重载样例);guide 场景只出指引文本。
+
+### 2.8 测试数据清理
+
+- 模拟库侧:页签「重置单表」清空对应 `sim_*` 表;
+- Ai-DOP 侧贴源数据按运行编号(runId)核验 SQL 人工清理——删除不由模拟器执行。
+
+---
+
+## 3. 方式乙 API_PULL(我方拉取)人工全链路
+
+**链路**:模拟器 `mock_api.py` 本地 GET Mock(默认 8018)→(Ai-DOP 拉取)`MdpSourcePullDispatcher` → `MdpApiPullExecutor` → 贴源表。
+
+### 3.1 模拟器准备
+
+1. 打开「Mock API(API_PULL)」页签:
+
+   ![Mock API 页签](sim-manual-img/tab_mockapi_MockAPI.png)
+
+2. 点 **启动**,Mock API 监听 `:8018`(真实端口绑定,失败如实报错)。
+3. 默认鉴权 `TOKEN`、令牌 `sim-mock-token`;按需切换 NONE/TOKEN/BASIC/APIKEY。
+4. 确认样例响应路径(默认挂载目录样例)。
+
+### 3.2 Ai-DOP 配置(人工执行)
+
+- `mdp_source`:`SIM_MODE3_API`;
+- `mdp_entity`:源 API path(如 `/api/item`)、鉴权方式与凭据(与模拟器设置一致)、目标贴源表、cursor 语义增量。
+
+### 3.3 Ai-DOP 人工触发
+
+Ai-DOP「数据源管理」对 `SIM_MODE3_API` 拉取。
+
+### 3.4 模拟器证据查看
+
+- 页签审计区查看最近请求(**自动脱敏**:Bearer/Secret 只留后四位);
+- 未拉取时审计为空——先查鉴权设置是否与 Ai-DOP 侧一致。
+
+### 3.5 Ai-DOP 流水查看
+
+Ai-DOP 拉取调度流水 + 响应状态码(401=鉴权不匹配、429=限流注入、500=错误注入)。
+
+### 3.6 目标结果核验
+
+同 2.6,以「对象测试」页签人工核验 SQL 在贴源表核对。
+
+### 3.7 异常恢复
+
+「异常测试」页签 → 方式乙分组(16 个场景):超时/空响应/坏 JSON/错误 Content-Type/忽略 cursor/不排序/强制状态码等,auto 场景一键预置与恢复。
+
+### 3.8 测试数据清理
+
+- Mock 侧:审计为内存态,**停止 Mock API** 即清;
+- Ai-DOP 侧贴源数据按 runId 人工清理。
+
+---
+
+## 4. 方式丙 API_INBOUND(第三方推送)人工全链路
+
+**链路**:模拟器 `clients/inbound_client.py` HMAC 签名推数 → Ai-DOP `MdpInboundController` → 接收服务 → 贴源表。
+
+### 4.1 模拟器准备
+
+1. 启动模拟器进程前注入 `AIDOP_SIM_INBOUND_ACCESS_KEY` / `AIDOP_SIM_INBOUND_SECRET`(**进程启动后无法热更新**)。
+2. 打开「API_INBOUND」页签:
+
+   ![API_INBOUND 页签](sim-manual-img/tab_inbound_API入站.png)
+
+3. 先跑 **26 契约 schema 批量预检**:逐实体 GET schema 探测,状态分类(READY / 授权缺失 / 实体未注册 / 源不可达)。
+
+### 4.2 Ai-DOP 配置(人工执行)
+
+- `mdp_inbound_grant` + `SysOpenAccess`:为测试 AccessKey 授权目标 entityCode 并绑定测试租户;
+- `mdp_entity.inbound_enabled=1`。
+
+> 未授权实体入站会返回 403 `entity not authorized`(凭据有效但未授权)。「压力测试」页签实体下拉只显示已授权实体,可点「刷新授权」重探测(探测为 GET schema,只读无副作用,Secret 不出后端)。
+
+### 4.3 模拟器触发(方式丙由模拟器发数,非 Ai-DOP 触发)
+
+「对象测试」页签选 API_INBOUND → 加载适配样例 → 预检 → 执行(七类操作:单条/批量/快照等)。
+
+### 4.4 模拟器证据查看
+
+「运行记录」页签:请求/响应预览(脱敏)、HTTP 状态、三层结论。
+
+### 4.5 Ai-DOP 流水查看
+
+Ai-DOP `mdp_inbound_request` 入站流水(含 syncBatchId,按 runId 检索)。
+
+### 4.6 目标结果核验
+
+按核验 SQL 查 Ai-DOP 贴源表(如 `mdp_stg_item`),核对业务键与行数。
+
+### 4.7 异常恢复
+
+「异常测试」页签 → 方式丙分组(17 个场景):错/缺 AccessKey、缺必填字段、错误字段类型、陈旧行、未知实体、批量部分失败、快照提交失败、实体未开启等;auto 场景一键恢复。**注意区分「工具自身失败」与「被测系统正确拒绝」**:Ai-DOP 预检拦截(409)记为 expectedReject,模拟器自身问题如实透传。
+
+### 4.8 测试数据清理
+
+- 按 syncBatchId/runId 在 Ai-DOP 入站流水与贴源表人工清理;
+- 模拟器不执行删除,只提供运行编号与核验 SQL。
+
+---
+
+## 5. 异常测试操作(第二阶段 N1-N4)
+
+打开「异常测试」页签:
+
+![异常测试页签](sim-manual-img/tab_fault_异常测试.png)
+
+1. **场景目录**:按通道分组——方式甲 10 项 / 方式乙 16 项 / 方式丙 17 项,每场景含 id、标题、类型(`auto` 可一键预置/恢复;`guide` 只出指引,不自动改配置)、模拟行为、预期结果、恢复方式。
+2. **预置**:auto 场景点「预置」→ 按场景执行(如方式乙注入 500、方式丙缺必填字段推数)。
+3. **恢复**:点「恢复」还原;或 Mock 设置区一键 reset。
+4. **N4 异常报告**(八列):选场景自动带入模拟行为与预期结果,填写后保存/导出 Markdown/列表管理;同场景重复保存为原位更新。
+
+## 6. 压力测试操作(第三阶段 §16-§21)
+
+打开「压力测试」页签:
+
+![压力测试页签](sim-manual-img/tab_load_压力测试.png)
+
+1. **安全前提**:压测默认关闭,须测试人员显式开启;执行前填满十项(压测方式/对象/实体/环境/测试租户/负责人/时间窗口/最大数据量/最大并发/清理方案),**不允许生产**;共享开发/UAT 环境须负责人确认。
+2. **提交计划(校验)**:前端校验十项必填与上限,后端二次校验(双层上限:共享上限 + 指定值),失败列出错误项。
+3. **开始压测**:
+   - 方式甲:S/M/L 档批量生成(可一键停止);
+   - 方式乙:Mock 压力模式(page_size/total_rows_limit/随机延迟/错误比例/限流);
+   - 方式丙:模拟器发压(并发/QPS/阶梯升压/预热/错误数据比例/幂等键策略/超时/三类自动停止阈值)。
+4. **实时指标**:2 秒轮询 19 项指标(QPS、行吞吐、成功率、P50/P95/P99 等);停止后指标**定格**在停止时刻。
+5. **立即停止**:随时可停;触发「连续错误/超时/429」自动停止阈值也会自动收尾(无后台残留负载)。
+6. **报告**:压测结束保存报告并导出 Markdown(自动脱敏)。
+
+## 7. 报告与脱敏(§24)
+
+三类报告:
+
+| 报告 | 入口 | 内容 |
+|---|---|---|
+| 基础打通报告 | 「全链路报告」页签 | 对象/通道/三层结论/核验 SQL |
+| 异常测试报告 | 「异常测试」页签 N4 | 八列:场景/模拟行为/预期/实际/符合/证据/恢复/备注 |
+| 压力测试报告 | 「压力测试」页签 | 计划十项 + 19 项指标快照 + 停止原因 |
+
+脱敏规则(保存前统一处理):
+
+- 不出现 AccessSecret、数据库密码、JWT、完整 Authorization、完整连接串;
+- AccessKey 仅保留后四位;
+- 不出现真实客户敏感数据。
+
+## 8. 测试数据清理总表
+
+| 位置 | 清理方式 |
+|---|---|
+| 模拟 MySQL(`aidop_integration_sim`) | 页签「重置单表」;或按核验 SQL 人工删 |
+| Mock API 审计 | 内存态,停止即清 |
+| 模拟器运行记录 | 自动脱敏 + 容量限制 |
+| Ai-DOP 贴源/入站流水 | 按 runId / syncBatchId 核验 SQL 人工清理(模拟器不执行删除) |
+
+测试数据以 `SIM-{runId}-` 业务键与 syncBatchId 全程可追踪。
+
+## 附录 A:本手册截图清单
+
+| 截图 | 对应页签 |
+|---|---|
+| `sim-manual-img/tab_run_对象测试.png` | 对象测试 |
+| `sim-manual-img/tab_mockapi_MockAPI.png` | Mock API(API_PULL) |
+| `sim-manual-img/tab_db_模拟MySQL.png` | 模拟 MySQL(DB_SYNC) |
+| `sim-manual-img/tab_inbound_API入站.png` | API_INBOUND |
+| `sim-manual-img/tab_fault_异常测试.png` | 异常测试 |
+| `sim-manual-img/tab_load_压力测试.png` | 压力测试 |
+| `sim-manual-img/tab_runs_运行记录.png` | 运行记录 |

+ 4 - 1
doc/plan/系统集成/README.md

@@ -22,7 +22,10 @@ python doc/plan/系统集成/_gen_integration_guide_docx.py
 |------|------|
 | [Ai-DOP第三方对接模拟器建设方案.md](./Ai-DOP第三方对接模拟器建设方案.md) | 独立本地第三方系统模拟器总体方案;第一阶段同时验证数据库同步 `DB_SYNC`、主动接口拉取 `API_PULL`、第三方接口推送 `API_INBOUND`,第二阶段扩展全链路自动对账、故障注入、SQL Server 与 CI |
 | [Ai-DOP第三方对接模拟器初步执行任务书.md](./Ai-DOP第三方对接模拟器初步执行任务书.md) | 可供后续开发者或大模型执行的两阶段初步任务书;含三层基线、文件清单、工作包、26 个推数契约、7 类推数操作、测试门禁和六面反向影响 |
-| [`tools/integration-simulator/`](../../../tools/integration-simulator/README.md) | **模拟器初版代码**(P1-A~P1-H 已交付);Python FastAPI 控制台 8017 + Mock API 8018 + MySQL 建库;三通道独立 source_code `SIM_MODE3_*`;42 对象 × 26 入站契约;凭据只走环境变量、Secret 不落盘不进浏览器 |
+| [Ai-DOP第三方系统模拟器分阶段完整执行任务书.md](./Ai-DOP第三方系统模拟器分阶段完整执行任务书.md) | **模拟器分阶段执行依据**:第一阶段 F1-F5 基础打通 → 第二阶段 N1-N4 异常测试 → 第三阶段 §16-§21 受控压力测试 → 第四阶段 §22-§25 交付收口;三阶段均已交付入库,第四阶段(README/操作手册/验收核对)已收口 |
+| [Ai-DOP第三方系统模拟器人工操作手册.md](./Ai-DOP第三方系统模拟器人工操作手册.md) | **人工操作手册(§23)**:三方式各 8 步全链路操作(准备/Ai-DOP 配置/触发/证据/流水/核验/异常恢复/清理)+ 异常测试 + 压力测试 + 报告脱敏;截图见 `sim-manual-img/` |
+| [Ai-DOP第三方系统模拟器交付验收核对.md](./Ai-DOP第三方系统模拟器交付验收核对.md) | **最终交付验收(§25)**:方式甲/乙/丙 + 通用共 20 项逐项取证结论 |
+| [`tools/integration-simulator/`](../../../tools/integration-simulator/README.md) | **模拟器代码(三阶段已交付)**:Python FastAPI 控制台 8017 + Mock API 8018 + MySQL 建库;三通道独立 source_code `SIM_MODE3_*`;42 对象 × 26 入站契约;异常场景目录 10/16/17;受控压测(S/M/L 档 / Mock 压力模式 / 方式丙发压);凭据只走环境变量、Secret 不落盘不进浏览器 |
 
 ## 中立标准层改造(本目录,内部)
 

BIN
doc/plan/系统集成/sim-manual-img/tab_db_模拟MySQL.png


BIN
doc/plan/系统集成/sim-manual-img/tab_fault_异常测试.png


BIN
doc/plan/系统集成/sim-manual-img/tab_inbound_API入站.png


BIN
doc/plan/系统集成/sim-manual-img/tab_load_压力测试.png


BIN
doc/plan/系统集成/sim-manual-img/tab_mockapi_MockAPI.png


BIN
doc/plan/系统集成/sim-manual-img/tab_run_对象测试.png


BIN
doc/plan/系统集成/sim-manual-img/tab_runs_运行记录.png


+ 40 - 8
tools/integration-simulator/README.md

@@ -1,4 +1,4 @@
-# Ai-DOP 第三方对接模拟器(第一阶段初版)
+# Ai-DOP 第三方对接模拟器
 
 独立运行的本地第三方系统模拟器,用同一套可追踪业务样例分别模拟三种入站方式:
 
@@ -9,7 +9,10 @@
 | `API_INBOUND` | `clients/inbound_client.py` → HMAC 签名推数 | `MdpInboundController` → 接收服务 |
 
 派生文档:[`建设方案`](../../doc/plan/系统集成/Ai-DOP第三方对接模拟器建设方案.md) ·
-[`初步执行任务书`](../../doc/plan/系统集成/Ai-DOP第三方对接模拟器初步执行任务书.md)
+[`分阶段完整执行任务书`](../../doc/plan/系统集成/Ai-DOP第三方系统模拟器分阶段完整执行任务书.md) ·
+[`人工操作手册`](../../doc/plan/系统集成/Ai-DOP第三方系统模拟器人工操作手册.md)
+
+三阶段能力均已交付:第一阶段基础打通(F1-F5)→ 第二阶段异常测试(N1-N4)→ 第三阶段受控压力测试(§16-§21)。
 
 **本工具不写 Ai-DOP 贴源/标准/KPI 表,不修改 Ai-DOP 配置,不进入 Ai-DOP 菜单。**
 
@@ -67,6 +70,8 @@ $env:AIDOP_SIM_ADMIN_TOKEN        = "<可选:只读管理 API 用>"
 | Mock API | 启停 8018;切换 NONE/TOKEN/BASIC/APIKEY;注入延迟与 401/403/429/500;改响应路径;看脱敏审计 |
 | 模拟 MySQL | 建库建表 / 装载样例 / 重置单表 / 行数与最大增量 / 生成 Ai-DOP 配置清单 |
 | API_INBOUND | 26 契约 schema 批量预检;七类操作与必测用例 |
+| 异常测试 | 三通道异常场景目录(方式甲 10 / 方式乙 16 / 方式丙 17);auto 一键预置/恢复,guide 只出指引;N4 八列异常报告 |
+| 压力测试 | 计划十项必填 + 通道参数 + 开始/停止 + 实时指标 + 报告导出;方式甲 S/M/L 档、方式乙 Mock 压力模式、方式丙并发/QPS/阶梯 |
 | 运行记录 | 最近运行(自动脱敏) |
 | 环境安全 | 凭据加载状态、白名单、隔离约束说明 |
 
@@ -107,8 +112,13 @@ $env:AIDOP_SIM_ADMIN_TOKEN        = "<可选:只读管理 API 用>"
 | `tests/test_mock_db.py` | DDL 与类型推断、幂等 upsert、库名硬阻断、配置清单;真实 MySQL 用例无密码时跳过并标注未实测 |
 | `tests/test_guard.py` | 非白名单目标阻断、预检状态分类、运行记录脱敏与容量 |
 | `tests/test_redaction.py` | Secret/连接串/Bearer/AccessKey 后四位脱敏 |
+| `tests/test_fault.py` | 三通道异常目录计数、auto 预置/恢复、guide 不落库、N4 报告 upsert、expectedReject 与工具失败严格区分 |
+| `tests/test_load_controls.py` | 压测状态机、计划十项必填、双层上限、租户字段剥离、三类自动停止 |
+| `tests/test_load_metrics.py` | 19 项指标、滚动窗口 QPS、停止后指标冻结、跨轮重置 |
+| `tests/test_auth_probe.py` | 入站实体授权探测:过滤未授权、不可达快速返回、缺凭据、缓存 |
 
 > `tests/test_guard.py`(安全闸门与三层判定)与 `tests/test_mock_api_lifecycle.py`(真实端口启停)是任务书初始清单外新增的守卫测试,其余文件名与任务书一致。
+> 基线:171 passed 1 failed(唯一失败为 `test_live_schema_load_and_increment`,需真实远端 MySQL 且当前不可达,属环境性)。
 
 ## 8. 目录
 
@@ -122,8 +132,13 @@ tools/integration-simulator/
 │  ├─ aidop_probe.py          # 只读预检与白名单闸门
 │  └─ redaction.py            # 脱敏
 ├─ providers/
-│  ├─ mock_api.py             # API_PULL 对端
-│  └─ mock_db.py              # MySQL 建表/装载/清理 + 配置清单生成
+│  ├─ mock_api.py             # API_PULL 对端 + 异常注入 + 压力模式统计
+│  ├─ mock_db.py              # MySQL 建表/装载/清理 + 配置清单 + S/M/L 档位生成
+│  └─ fault_catalog.py        # 三通道异常场景目录(10/16/17)
+├─ load/
+│  ├─ controls.py             # 压测状态机、计划校验、自动停止
+│  ├─ metrics.py              # 19 项实时指标
+│  └─ runner_p3.py            # 方式丙并发执行器(QPS/阶梯/错误比例)
 ├─ catalog/
 │  ├─ entities.json           # 42 个对象 × 三通道能力矩阵
 │  ├─ scenarios.json          # 三组跨对象基础场景
@@ -140,9 +155,26 @@ doc/db/mdp/mock_api/samples/*.json
 tools/mock/inbound/push_demo.py
 ```
 
-## 9. 第一阶段边界
+## 9. 能力边界
 
-- 只做 MySQL 方言;SQL Server、故障注入编排、全链路自动对账、CLI/CI/容器化属第二阶段;
-- 不做高并发压测,默认低频单批;
+- 只做 MySQL 方言,不做 SQL Server;全链路自动对账、CLI/CI/容器化未做(Docker 属可选交付);
+- 压测为受控压力测试:默认关闭、计划十项必填、负责人确认、不允许生产环境、双层上限、连续错误自动停止;
 - 不为无契约对象伪造 API_INBOUND 接口(销售订单头、合同评审、发货计划/发货单、工序计划、MRP、采购申请、交货计划、现存量、过程检验、成品入库);
-- 删除测试数据不由模拟器执行,只提供运行编号与核验 SQL 清单。
+- 删除测试数据不由模拟器执行,只提供运行编号与核验 SQL 清单;
+- 本工具只模拟第三方一侧:不写 Ai-DOP 贴源/标准/KPI 表,不修改 Ai-DOP 配置,不进入 Ai-DOP 菜单。
+
+## 10. 常见故障排查
+
+| 现象 | 原因 | 处理 |
+|---|---|---|
+| 启动报 `[Errno 10048]` 端口被占用 | 上一个模拟器进程未退出仍监听 8017 | `netstat -ano | findstr :8017` 找 PID 后 `Stop-Process -Id <PID> -Force` 再启动(`Get-NetTCPConnection` 偶发假阴性,以 netstat 为准) |
+| 预检 `reachable=false` + WinError 10061 | Ai-DOP 后端 :5005 未启动(无人监听而非防火墙) | 启动 Admin.NET.Web.Entry;`GET /api/precheck` 返回 `httpStatus=405` 属正常可达 |
+| 入站执行全 403 `entity not authorized` | 凭据有效但该 entityCode 未授权 | Ai-DOP 侧 `mdp_inbound_grant` + `SysOpenAccess` 补授权;压力页签实体下拉可点「刷新授权」重探测 |
+| 压力页签实体下拉为空 | ① 浏览器缓存旧 HTML 与新 JS 错配 ② Ai-DOP 不可达 | ① 强刷(Ctrl+F5);② 启动 Ai-DOP 后点「刷新授权」 |
+| P3 压测请求约 2 秒/条且全失败 | Windows 连接拒绝默认 SYN 重试(Ai-DOP 未启动时) | 属预期表现,连续错误会自动停止;先启动 Ai-DOP 再压测 |
+| MySQL `1045 Access denied` 或 `'sim_user'@'localhost'` | 账号按 `user@host` 匹配,公网连远端时来源 IP 是本机出口 IP | 为出口 IP 显式建号授权(`Invoke-RestMethod https://api.ipify.org` 查 IP),或用 SSH 隧道 `ssh -N -L 13306:127.0.0.1:3306 user@host` |
+| MySQL `caching_sha2_password` 认证失败 | PyMySQL 无 TLS 下需 RSA 公钥交换 | `pip install cryptography`(requirements 未声明,需手动装) |
+| 入站请求被 mock 客户端签名不一致 | 环境变量注入的进程才能读到 `AIDOP_SIM_INBOUND_*` | 环境变量改后必须**重启模拟器进程**(启动后无法热更新) |
+| PowerShell 里 `python` 打开应用商店 | Microsoft Store 别名占位 | 使用真实解释器(如 `.venv-sim\Scripts\python`),并确保 venv 优先于别名 |
+| PowerShell `curl` 行为异常 | `curl` 是 `Invoke-WebRequest` 别名 | 用 `curl.exe`;传 JSON 用 Python urllib 或文件方式更稳 |
+| 压测停止后指标仍变动(历史版本) | 滚动窗口实时计算随时间衰减 | 现版本停止时冻结指标,停止后不再变动 |

+ 1 - 1
tools/integration-simulator/static/index.html

@@ -8,7 +8,7 @@
 </head>
 <body>
   <header>
-    <h1>Ai-DOP 第三方对接模拟器 <span class="tag">第一阶段 · 本地控制台</span></h1>
+    <h1>Ai-DOP 第三方对接模拟器 <span class="tag">三阶段 · 本地控制台</span></h1>
     <div id="env-banner" class="banner">环境状态加载中…</div>
   </header>