Pengxy 5722d5d10d docs(simulator): 完善第三方模拟器交付手册与验收核对 1 өдөр өмнө
..
catalog 6bca8c9818 fix(simulator): 完成三种方式基础人工联调(全链路报告/脱敏/导出) + mdp 入站参数绑定与响应修复; chore: bump server 1.0.600 3 өдөр өмнө
clients 9cf23c4a7a feat(simulator): 第二阶段异常测试能力N1-N4与真实联调缺陷修复 2 өдөр өмнө
load 9e70ca326f feat(simulator): 增加受控压力测试能力与实体授权探测 1 өдөр өмнө
providers 9e70ca326f feat(simulator): 增加受控压力测试能力与实体授权探测 1 өдөр өмнө
static 5722d5d10d docs(simulator): 完善第三方模拟器交付手册与验收核对 1 өдөр өмнө
tests 9e70ca326f feat(simulator): 增加受控压力测试能力与实体授权探测 1 өдөр өмнө
README.md 5722d5d10d docs(simulator): 完善第三方模拟器交付手册与验收核对 1 өдөр өмнө
app.py 9e70ca326f feat(simulator): 增加受控压力测试能力与实体授权探测 1 өдөр өмнө
config.example.json f63842f253 feat: 新增 Ai-DOP 第三方对接模拟器初版(tools/integration-simulator, P1-A~P1-H) + 系统集成文档索引登记; chore: bump server 1.0.597 2 долоо хоног өмнө
requirements.txt f63842f253 feat: 新增 Ai-DOP 第三方对接模拟器初版(tools/integration-simulator, P1-A~P1-H) + 系统集成文档索引登记; chore: bump server 1.0.597 2 долоо хоног өмнө

README.md

Ai-DOP 第三方对接模拟器

独立运行的本地第三方系统模拟器,用同一套可追踪业务样例分别模拟三种入站方式:

通道 模拟端 Ai-DOP 真实执行链
DB_SYNC providers/mock_db.py → 独立 MySQL schema aidop_integration_sim MdpSourcePullDispatcher → MdpDbPullExecutor
API_PULL providers/mock_api.py → 本地 GET Mock(默认 8018) MdpSourcePullDispatcher → MdpApiPullExecutor
API_INBOUND clients/inbound_client.py → HMAC 签名推数 MdpInboundController → 接收服务

派生文档:建设方案 · 分阶段完整执行任务书 · 人工操作手册

三阶段能力均已交付:第一阶段基础打通(F1-F5)→ 第二阶段异常测试(N1-N4)→ 第三阶段受控压力测试(§16-§21)。

本工具不写 Ai-DOP 贴源/标准/KPI 表,不修改 Ai-DOP 配置,不进入 Ai-DOP 菜单。


1. 环境要求

  • Python 3.11+(Windows 需真实解释器,非 Microsoft Store 别名占位)
  • 独立 MySQL 测试实例,具备建库建表权限;不得使用 Ai-DOP 库或其账号
  • 可访问的 Ai-DOP 开发/UAT 地址,且已准备测试租户与测试 AccessKey

    cd d:\DEMONET
    python -m venv .venv-sim
    .venv-sim\Scripts\pip install -r tools/integration-simulator/requirements.txt
    

2. 配置

Copy-Item tools/integration-simulator/config.example.json tools/integration-simulator/config.json
# 按本机修改 aidopBaseUrl / mockApiPort / allowedTargetHosts

config.json 已加入 .gitignore,且只放非敏感项。凭据一律走环境变量:

$env:AIDOP_SIM_MYSQL_HOST      = "127.0.0.1"
$env:AIDOP_SIM_MYSQL_PORT      = "3306"
$env:AIDOP_SIM_MYSQL_USER      = "sim_user"          # 专用账号,勿用 Ai-DOP 主库账号
$env:AIDOP_SIM_MYSQL_PASSWORD  = "<模拟库密码>"
$env:AIDOP_SIM_MYSQL_DATABASE  = "aidop_integration_sim"
$env:AIDOP_SIM_INBOUND_ACCESS_KEY = "<测试 AccessKey>"
$env:AIDOP_SIM_INBOUND_SECRET     = "<测试 Secret>"
$env:AIDOP_SIM_ADMIN_TOKEN        = "<可选:只读管理 API 用>"

缺任何一项时,页面顶部横幅会明确提示缺哪个变量;Secret 永远不由页面输入、不回显、不落盘。

3. 启动

.venv-sim\Scripts\python tools/integration-simulator/app.py
# 控制台:http://127.0.0.1:8017/

服务只绑定 127.0.0.1。目标 Ai-DOP host 必须命中 allowedTargetHosts,否则硬阻断。

4. 页面用法

页签 用途
对象测试 选对象 → 选通道 → 加载/编辑适配样例 → 预检 → 执行 → 看三层结论与核验 SQL
业务场景 三组跨对象链路(订单制造链 / 采购执行链 / 库存与成品链);不支持的节点标红「该通道不支持」
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/阶梯
运行记录 最近运行(自动脱敏)
环境安全 凭据加载状态、白名单、隔离约束说明

5. Ai-DOP 侧登记(人工执行)

模拟器只生成建议配置(GET /api/db/aidop-config/{objectCode}),不自动写库。需在 Ai-DOP 配置页登记:

  • mdp_source:三个专用测试来源 SIM_MODE3_DB / SIM_MODE3_API / SIM_MODE3_INBOUND,共用 system_code=SIM_MODE3;
  • mdp_entity:源表/源 API path、目标贴源表、业务键、增量列(DB_SYNC 用 sourceUpdatedAt,API_PULL 用 cursor 语义);
  • mdp_inbound_grant + SysOpenAccess:测试 AccessKey 授权目标 entityCode 并绑定测试租户;
  • mdp_entity.inbound_enabled=1。

三通道不得共用 source_code,且不得抢占现有 T8/165/自建单等生产权威来源。

6. 结果分层(不得混为一谈)

代码层:SUPPORTED / UNSUPPORTED
配置层:READY / CONFIG_NOT_REGISTERED / CONFIG_NOT_ENABLED / GRANT_MISSING / SOURCE_UNREACHABLE
数据层:NOT_RUN / ACCEPTED / STAGING_WRITTEN / TRANSFORM_PENDING / RUN_FAILED

第一阶段无安全的只读管理 API 核对贴源结果时,报告 TRANSFORM_PENDING 并给出人工核验 SQL, 不把 HTTP 202 说成业务全链路跑通,不把配置未开通说成代码未实现。

7. 测试

.venv-sim\Scripts\pytest tools/integration-simulator/tests -v
文件 覆盖
tests/test_inbound_signature.py 签名金标向量(与独立实现交叉验证)、SHA256/HMAC、签名头不外泄
tests/test_sample_adapters.py 目录三通道完整性、26 契约覆盖、样例路径存在、SIM-{runId}- 业务键、契约字段名、缺必填如实上报
tests/test_mock_api.py cursor 过滤、四种鉴权、401/403/429/500 注入、响应路径切换、样例挂载、审计脱敏
tests/test_mock_api_lifecycle.py 真实端口启停生命周期:绑定成功且可连通、重复调用幂等、端口占用如实报错(回归 uvicorn 0.30+ 无 startup_error 导致的 500)
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. 目录

tools/integration-simulator/
├─ app.py                     # 本地控制服务(只绑 127.0.0.1)+ 三层报告 + 运行记录
├─ requirements.txt
├─ config.example.json        # 仅非敏感默认项;复制为 config.json(已 gitignore)
├─ clients/
│  ├─ inbound_client.py       # HMAC 签名与七类推数操作
│  ├─ aidop_probe.py          # 只读预检与白名单闸门
│  └─ redaction.py            # 脱敏
├─ providers/
│  ├─ 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          # 三组跨对象基础场景
│  └─ sample_adapters.py      # canonical 样例 → 三通道适配
├─ static/                    # 本地页面
└─ tests/

复用但不迁移、不修改的既有资产:

doc/db/mdp/mock_api/endpoints.json
doc/db/mdp/mock_api/samples/*.json
tools/mock/inbound/push_demo.py

9. 能力边界

  • 只做 MySQL 方言,不做 SQL Server;全链路自动对账、CLI/CI/容器化未做(Docker 属可选交付);
  • 压测为受控压力测试:默认关闭、计划十项必填、负责人确认、不允许生产环境、双层上限、连续错误自动停止;
  • 不为无契约对象伪造 API_INBOUND 接口(销售订单头、合同评审、发货计划/发货单、工序计划、MRP、采购申请、交货计划、现存量、过程检验、成品入库);
  • 删除测试数据不由模拟器执行,只提供运行编号与核验 SQL 清单;
  • 本工具只模拟第三方一侧:不写 Ai-DOP 贴源/标准/KPI 表,不修改 Ai-DOP 配置,不进入 Ai-DOP 菜单。

10. 常见故障排查

现象 原因 处理
启动报 [Errno 10048] 端口被占用 上一个模拟器进程未退出仍监听 8017 `netstat -ano
预检 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 或文件方式更稳
压测停止后指标仍变动(历史版本) 滚动窗口实时计算随时间衰减 现版本停止时冻结指标,停止后不再变动