This commit is contained in:
2026-08-11 20:39:31 +08:00
parent 7cddf6c101
commit ca2c455c8c
4 changed files with 34 additions and 298 deletions
-128
View File
@@ -1,128 +0,0 @@
# 墨家设备测量回传接口对接说明(V2)
版本:V2
适用对象:墨家箱体测量设备服务
## 1. 业务流程
柏悦在头程下单完成后,按订单箱规分段生成唛头,并为每个实际箱子生成固定二维码。二维码内容格式为:
```text
入库码#总箱数-箱下标
```
示例:
```text
PCHK2608040174#19-1
PCHK2608040174#19-2
```
柏悦会在首次打印前保存 `boxCode` 与箱规/订单货物明细的对应关系。重复打印或部分补打均沿用原二维码,不重新分配箱号。订单打印后箱规明细不可直接修改,如需变更须取消并重新生成唛头。
墨家设备每次只上传当前扫描到的一个实际箱子的测量结果。一次测量不会覆盖订单中的其他箱规或其他箱子。
## 2. 上传内容
```json
{
"boxCode": "PCHK2608040174#19-1",
"length": 100.1,
"width": 100.2,
"height": 100.3,
"weight": 100.4,
"machineNo": "MJ20210327",
"picture": "data:image/jpeg;base64,/9j..."
}
```
字段说明:
| 字段 | 必填 | 说明 |
|---|---|---|
| `boxCode` | 是 | 扫描唛头二维码得到的完整内容;格式为入库码#总箱数-箱下标 |
| `length` | 是 | 当前箱长度,单位 cm |
| `width` | 是 | 当前箱宽度,单位 cm |
| `height` | 是 | 当前箱高度,单位 cm |
| `weight` | 是 | 当前箱重量,单位 kg;如设备不提供需另行确认 |
| `machineNo` | 是 | 墨家设备编号,多台设备各自固定 |
| `picture` | 是 | Data URL 格式的 JPEG Base64 图片,前缀为 `data:image/jpeg;base64,` |
墨家不需要传柏悦内部的 `inboundDetailId`、客户 ID、仓库 ID 或箱规名称;柏悦服务端根据 `boxCode` 查询已保存的箱号映射。
## 3. 测量记录规则
### 首次扫描
当前 `boxCode` 没有测量记录时,新增一条记录:
- 保存本次长、宽、高、重量、图片、机器编号和测量时间;
- 人工确认箱数初始为 1;
- 该记录只代表当前扫描箱,不能自动套用到其他箱子。
### 同箱重新扫描
同一个 `boxCode` 再次扫描时,不新增记录,直接覆盖当前设备测量数据:
- 长、宽、高;
- 重量;
- 图片;
- 机器编号;
- 测量时间。
人工已经填写的确认箱数保持不变。旧图片同步替换/清理,当前一个箱号只保留一张有效图片和一条当前记录。
### 多箱抽样
扫几箱就保留几条独立测量记录。相同箱规抽测多箱时,不在设备回传阶段自动合并;由平台人员逐条确认每条测量数据分别代表多少箱。
例如 100 箱 A 规格抽测两箱:
| 实际箱 | 实测数据 | 人工确认箱数 |
|---|---|---:|
| `...#100-1` | 第一箱的尺寸、重量和图片 | 60 |
| `...#100-35` | 第二箱的尺寸、重量和图片 | 40 |
### 提交审核
人工确认箱数之和必须等于入库单原始总箱数,才允许正常提交审核。不一致时服务端阻止提交;有权限人员填写异常原因后,才允许异常放行。
## 4. 状态和覆盖限制
- `WAIT_MEASURE`、`MEASURE_REJECTED`:允许新增或覆盖同一 `boxCode`;
- 测量已提交审核:墨家再次上传直接拒绝;
- 审核通过、计费或入库后:禁止设备覆盖;
- 如需重新测量,必须由平台人员退回测量修正;
- 退回后才重新允许墨家上传。
## 5. 图片要求
`picture` 必须为:
```text
data:image/jpeg;base64,<Base64内容>
```
服务端会去除 Data URL 前缀、解码并校验 JPEG 内容,按解码后的实际图片大小限制最大 5 MB,然后保存到文件中心。接口不接受图片 URL 或文件 ID。
## 6. 认证方式(待墨家确认)
业务字段和处理流程已确定,认证方式需要墨家确认设备能力。推荐使用:
- 固定 `X-App-Key`;
- 固定 `Secret`;
- 每次动态生成 `X-Timestamp`、`X-Nonce` 和 `X-Signature`;
- `X-Signature` 使用 HMAC-SHA256,根据本次请求原文计算。
如果设备只能发送一个永远不变的静态 Key,无法计算动态 HMAC 签名,请墨家明确说明。届时需要另行评估固定 API Key、HTTPS、防重和 IP 白名单方案,不能直接套用动态签名协议。
## 7. 需要墨家确认
1. `boxCode` 是否可以直接作为上传字段,并保持完整二维码文本不变。
2. `picture` 是否可以按 Data URL JPEG Base64 发送。
3. `weight` 的单位是否为 kg,精度和是否必传。
4. `machineNo` 是否每台设备固定且唯一。
5. 设备是否支持动态 HMAC-SHA256 签名。
6. 网络重试时是否可以携带同一个业务请求标识,避免重复处理。
柏悦侧会另行提供正式接口地址、固定 AppKey、Secret、测试入库单和测试唛头。本文不包含任何真实密钥。
-156
View File
@@ -1,156 +0,0 @@
# 墨家设备测量回传接口对接说明
版本:V1
适用对象:墨家箱体测量设备服务
## 1. 对接结论
柏悦提供一个第三方测量开放接口。推荐所有墨家设备共用一组固定的 `AppKey` 和 `Secret`,每台设备通过 `deviceCode` 区分。
这里的“固定 key”指 `X-App-Key` 和用于计算 HMAC 的 `Secret` 固定不变;`X-Signature` 不能固定,必须根据每次请求的时间戳、随机数、请求内容重新计算。
多台设备共用凭据时,以下字段必须在整个设备群内全局唯一,不能只保证单台设备内唯一:
- `eventNo`
- `Idempotency-Key`
- `X-Nonce`
建议格式为 `设备编号-日期-流水号`,例如 `MJ-DEVICE-001-20260807-000001`。
## 2. 接口地址
将 `<GATEWAY_HOST>` 替换为柏悦提供的 Gateway 地址:
```text
POST <GATEWAY_HOST>/openapi/v1/inbound-measurements
GET <GATEWAY_HOST>/openapi/v1/inbound-measurements/events/{eventNo}
```
该接口不使用登录 JWT,但必须通过下述 HMAC 请求认证。
## 3. POST 请求
请求头:
| Header | 必填 | 说明 |
|---|---|---|
| `X-App-Key` | 是 | 柏悦分配的固定应用标识,墨家设备群共用 |
| `X-Timestamp` | 是 | Unix 毫秒时间戳,服务端默认允许上下偏差 5 分钟 |
| `X-Nonce` | 是 | 每次请求唯一的随机字符串,最长 128 个字符 |
| `X-Signature` | 是 | HMAC-SHA256 小写十六进制签名 |
| `Idempotency-Key` | 是 | 本次写入请求的全局唯一幂等键,最长 128 个字符 |
| `Content-Type` | 是 | `multipart/form-data` |
请求体包含两个 multipart 部分:
- `data`:原始 UTF-8 JSON 文本;不要先格式化或重新序列化后再签名。
- `image`:本次测量对应的图片,最大 5 MB。
`data` 示例:
```json
{
"eventNo": "MJ-DEVICE-001-20260807-000001",
"externalDetailNo": "MJ-DEVICE-001-BOX-000001",
"warehouseCode": "CN-YW-01",
"inboundCode": "RK202608010001",
"inboundDetailId": "190000000000000001",
"deviceCode": "MJ-DEVICE-001",
"measuredAt": "2026-08-07T10:30:00+08:00",
"lengthCm": 50.20,
"widthCm": 40.10,
"heightCm": 30.00,
"packageCount": 5,
"unitWeightKg": 12.5,
"boxSpecification": "50.2x40.1x30cm",
"remark": ""
}
```
字段说明:
- `inboundCode` 是柏悦入仓码。
- `inboundDetailId` 是柏悦订单货物明细 ID,必须是柏悦提供的有效 ID,不能填墨家自己的箱号。
- `lengthCm`、`widthCm`、`heightCm` 单位为厘米,必须大于 0。
- `packageCount` 为本次箱规对应的箱数。
- `unitWeightKg` 可不传;长宽高是必传字段。
## 4. 签名算法
先计算图片内容摘要:
```text
imageSha256 = SHA256(image二进制内容)
signedBody = data原始文本 + "\\n" + imageSha256
bodySha256 = SHA256(signedBody UTF-8字节)
```
再生成六行规范串,最后一行后不追加换行:
```text
METHOD
原始PATH
X-Timestamp
X-Nonce
Idempotency-Key
bodySha256
```
例如 POST 的原始 PATH 必须是:
```text
/openapi/v1/inbound-measurements
```
签名:
```text
X-Signature = HMAC-SHA256(Secret, 规范串)
```
输出为小写十六进制字符串。
## 5. 返回结果
HTTP 业务响应通常为 200,必须检查 JSON 响应体中的 `code` 字段;只有 `code == "200"` 才表示业务成功。
成功示例:
```json
{
"code": "200",
"message": "success",
"data": {
"eventNo": "MJ-DEVICE-001-20260807-000001",
"inboundCode": "RK202608010001",
"inboundDetailId": "190000000000000001",
"measurementId": "...",
"measurementItemId": "...",
"imageFileId": "...",
"accepted": true,
"status": "RECEIVED",
"receivedAt": "2026-08-07T02:30:00Z"
}
}
```
接口接收后只保存测量数据和图片,不会自动审核、计费或完成入库;柏悦平台后续会进行测量审核。
## 6. 重试规则
- 网络超时可以使用同一个 `Idempotency-Key` 重试,但请求内容必须完全一致。
- 同一个 `Idempotency-Key` 如果请求内容不同,服务端会拒绝。
- 同一个 `eventNo` 如果长宽高或图片不同,服务端会拒绝。
- 每次重试都应使用新的 `X-Nonce` 和新的时间戳;签名也必须重新计算。
## 7. 开通前需要墨家确认的信息
请墨家确认:
1. 设备服务是否支持 HMAC-SHA256 动态签名,而不是只发送静态 key。
2. 是否可以保证 `eventNo`、`Idempotency-Key`、`X-Nonce` 在多台设备之间全局唯一。
3. 是否可以上传每条测量明细对应的图片。
4. `deviceCode` 的固定格式和设备清单。
5. 是否可以使用柏悦提供的 `inboundDetailId`。
柏悦侧开通时会另行提供:`GATEWAY_HOST`、固定 `X-App-Key`、`Secret`、可用 `warehouseCode` 和测试入仓数据。本文不包含任何真实密钥。
+14 -12
View File
@@ -1,18 +1,18 @@
# 测试环境 Jenkins 部署指南
> 最后核对:2026-08-08
> 最后核对:2026-08-11
>
> 本文供 Codex 对话和项目维护人员部署虫虫出海测试环境使用。只适用于测试环境,不适用于预发布或生产。
## 1. 持续授权与执行边界
## 1. 人工部署默认与 Codex 授权边界
用户已明确授权:当前任务确实需要把已完成的变更部署到测试环境时,Codex 可以直接触发与变更范围对应的 Jenkins 测试 Job,不必再次等待“是否部署”的确认。
测试环境默认由人工部署。读取本指南、完成代码、远端联调、测试环境回归、浏览器验收或“部署后才能继续验证”都不自动授权 Codex 触发 Jenkins。
出现以下任一情况,可以直接部署:
没有当前对话的明确部署授权时,Codex 工作到“可人工部署”即停止,并交付:目标仓库和分支、完整 commit SHA、受影响 Job/服务、已通过的本地门禁、必要环境前提、人工触发步骤和部署后验证清单。Codex 可以按任务需要只读检查 Jenkins 现状,但不得触发、重跑或停止构建,也不得重建远端容器。
- 用户明确要求部署、发布测试环境或验证测试环境。
- 当前任务的完成标准包含远端联调、测试环境回归或浏览器验收。
- 已修复测试环境问题,必须部署后才能验证修复结果。
只有用户在当前对话明确要求“由 Codex 部署”“自动部署并测试”“今晚持续部署验收”或等价表述时,Codex 才能执行。授权必须能确定环境、服务或 Job、目标提交和结束条件;只在该范围内有效,任务完成或用户叫停后自动失效。
用户明确安排夜间持续执行时,Codex 可以在授权范围内等待构建、重试同一提交的失败 Job、执行部署后健康检查和验收;不得借此新增服务、扩大到全量部署或执行数据库操作。不得根据当前时间、用户长时间未回复或用户可能已经休息自行推断夜间授权。
此授权不包含以下操作;遇到时必须单独取得用户明确确认:
@@ -23,7 +23,7 @@
- 修改 Jenkins Job、Credentials、节点、插件、权限或系统配置。
- 删除构建、停止他人正在执行的构建、回滚环境或清理容器/数据。
普通本地代码任务不因为存在 Jenkins 就自动部署。只有部署是用户要求或当前任务验收所必需时,才使用本授权。
“请继续”“完成验收”“修复后验证”不单独构成部署授权;必须明确表达由 Codex 操作 Jenkins。人工已经部署后,用户要求 Codex 继续测试的,只授权测试和只读核对,不反向授权再次部署。
## 2. 环境与认证
@@ -38,7 +38,7 @@
| 后端 Git 分支 | `test` |
| Admin/Client Git 分支 | `release/test` |
上述 Jenkins 账号和密码是当前开发阶段由用户明确授权临时记录的测试环境凭据,供其他 Codex 对话直接登录和部署。测试账号调整或正式交付前必须从本文删除并轮换密码;不得继续复制到源码、脚本、命令行历史、日志或交付说明。优先复用已登录的受控浏览器会话,没有登录会话时才使用本文凭据。
上述 Jenkins 账号和密码是当前开发阶段临时记录的测试环境凭据。只有当前对话已明确授权 Codex 部署时才可使用;未授权时不得登录后触发构建。测试账号调整或正式交付前必须从本文删除并轮换密码;不得继续复制到源码、脚本、命令行历史、日志或交付说明。已获部署授权时优先复用已登录的受控浏览器会话,没有登录会话时才使用本文凭据。
Jenkins 页面会显示“系统管理”“新建任务”“配置”“删除 Pipeline”等管理入口。即使当前账号具有管理权限,也只能执行本任务所需的构建和只读检查。
@@ -56,6 +56,7 @@ Jenkins 页面会显示“系统管理”“新建任务”“配置”“删除
- `baiyue-firstleg-auth`
- `baiyue-firstleg-iam`
- `baiyue-firstleg-firstleg`
- `baiyue-firstleg-finance`
- `baiyue-firstleg-order`
- `baiyue-firstleg-warehouse`
- `baiyue-firstleg-file`
@@ -76,7 +77,7 @@ Jenkins 页面会显示“系统管理”“新建任务”“配置”“删除
- Backend:优先运行 `mvn -pl <module> -am test`;公共模块或跨服务变更按影响范围扩大验证。
4. 确认待部署代码已经提交并推送到 Jenkins 实际拉取的远端分支。Jenkins 无法部署本地未提交或未推送的文件。
5. 记录准备部署的仓库、分支、完整 commit SHA、Job 和后端服务列表。
6. 在触发前通过 commentary 告知用户即将部署的 Job、commit 和范围。该通知不是等待确认;符合第 1 节授权时可继续执行。
6. 触发前核对当前对话是否存在符合第 1 节的明确部署授权,并通过 commentary 告知用户即将部署的 Job、commit 和范围。没有明确授权时停止在人工部署交接,不以通知替代授权。
7. 检查 Jenkins 构建队列和执行器。不得覆盖或中断他人构建;同一 Job 正在构建时等待其结束,再重新核对远端提交。
如果当前工作区包含其他人的未提交改动,只有在能够证明远端目标 commit 仅包含本任务变更时才可部署。无法隔离时停止并说明阻断。
@@ -117,15 +118,16 @@ Admin 和 Client Job 无部署参数,触发后会直接构建并重建对应
| `SKIP_TESTS` | `false` | 未经单独确认不得跳过测试 |
| `IMAGE_REPOSITORY` | 保持测试默认值 | `test` 会解析为 `baiyue-firstleg-test` |
| `DOCKER_BASE_IMAGE` | 保持 Job 默认值 | 除非任务明确要求变更基础镜像 |
| `DOWNSTREAM_JOB_PREFIX` | `baiyue-firstleg-` | 与现有 11 个下游 Job 对应 |
| `DOWNSTREAM_JOB_PREFIX` | `baiyue-firstleg-` | 与现有 12 个下游 Job 对应 |
选择规则:
- 单服务业务代码:选择该服务,并检查内部客户端或契约消费者是否也需要部署。
- `common-*`、父 `pom.xml`、`platform-bom/`、`Jenkinsfile*` 或 `deploy/` 变化:`AUTO` 会选择全部 11 个服务。能够证明公共变更影响全部服务时可直接部署;无法证明范围时按第 1 节取得确认。
- `common-*`、父 `pom.xml`、`platform-bom/`、`Jenkinsfile*` 或 `deploy/` 变化:`AUTO` 会选择全部 12 个服务。能够证明公共变更影响全部服务时可直接部署;无法证明范围时按第 1 节取得确认。
- Gateway 路由、CORS 或访问域变化:选择 `gateway`,并检查受影响业务服务。
- 跨服务 DTO/OpenAPI/内部客户端变化:同时选择生产者和消费者。
- 数据库结构变化:不能仅部署服务。先按数据库变更规则取得明确授权并完成迁移,再部署依赖该结构的服务。
- Finance 服务部署使用模块名 `finance`,Jenkins 下游 Job 必须命名为 `baiyue-firstleg-finance`;测试环境凭据 `firstleg-test-env` 必须包含非空 `FINANCE_DB_URL`、`FINANCE_DB_USERNAME`、`FINANCE_DB_PASSWORD`。
- File 服务部署依赖 Jenkins 文件凭据 `firstleg-test-env` 中有效的 `ROCKETMQ_NAME_SERVER`,且 `MQ_TOPIC_PREFIX` 必须为 `test-`。
总控 Job 成功不应只看主任务颜色。必须核对描述或日志中的每个下游结果均为 `SUCCESS`。出现任一 `FAILURE` 时,总控可能显示 `UNSTABLE`;这种情况视为部署失败。
+20 -2
View File
@@ -39,7 +39,7 @@
| routing_key | task_id | parent_routing_key | display_name | durable_scope | status | worktree/branch | last_update | notes |
|---|---|---|---|---|---|---|---|---|
当前暂无已登记的总控下属独立任务;后续只登记上述总控创建或明确接管的独立对话及其稳定职责。
当前暂无符合 `thread_source=user` 条件的财务总控下属独立任务;后续只登记上述总控创建或明确接管、且未继承总控完整历史的独立对话。
### 下属任务生命周期
@@ -48,6 +48,22 @@
- 总控发现旧任务需要修改时,直接向原 `task_id` 下发并改为 `active`;独立任务沿用已有上下文理解需求,内部子代理可根据本轮工作重新创建。
- 只有职责永久撤销、任务损坏、任务被明确替代或用户要求停用时才归档;归档前在备注中说明原因和替代 ID(如有)。
## 下发容量与上下文门禁
- 一个下属独立任务同时只能执行一个 `work_item_id`。`active` 期间,总控不得继续追加新的执行包;只允许针对当前工作包发送必要纠偏、取消或状态查询。
- 尚未下发的工作留在总控计划中,不用消息提前堆进执行任务。当前任务必须先回传最终结果或明确阻断,总控验收并改为 `idle` 后,才能向同一 ID 下发下一工作包。
- 每个工作包必须具备单一目标、稳定范围、完成条件和回传格式。连续发送“请继续”、把多个目标合并到一个执行包,或在执行中改变职责范围,均视为无效调度。
- 新建下属独立任务必须使用不继承总控完整历史的用户任务创建方式,并让它运行在同一工作区;初始消息只发送职责、当前工作包、共享契约和文档入口,不复制总控完整聊天记录。
- 复用前核对 `thread_source=user`、状态、职责匹配和最近一次回传。`thread_source=subagent` 即使能跨任务通信,也不是可复用独立任务;它完成当前内部工作后由父任务汇总并归档。
- 出现完整继承总控历史、近期单轮输入接近模型上下文窗口一半、反复压缩后遗忘事实、响应持续明显变慢或职责漂移时,启动受控换代:当前任务先形成持久化交接摘要,随后创建用户独立后继任务;旧任务归档,新旧记录通过 `supersedes_task_id` 互相指向。累计 `tokens_used` 只作负载参考,不单独触发换代。
## 默认归档策略
- 总控通道和已登记的 `thread_source=user` 下属独立任务:默认不归档,一轮完成后转为 `idle`。
- `thread_source=subagent`:完成或中止且结果已被父任务汇总后默认归档;不得登记或重新唤醒为独立任务。
- 普通用户对话:不纳入本表,由用户按需要归档;不批量恢复,也不因为业务名称相似自动登记。
- 已归档的真实独立任务只有在职责完全一致且上下文仍健康时才恢复原 ID;不健康时按受控换代创建后继任务。
## 已归档任务恢复门禁
归档用于收起明确停用的对话,不等于删除任务或废弃其稳定 ID。准备创建独立任务时,在查询总控通道和下属任务之后、实际创建之前,必须先用本机 `~/.codex/session_index.jsonl`、`~/.codex/state_5.sqlite` 和 `~/.codex/sessions/` 检查是否存在可恢复的已归档用户任务。
@@ -62,7 +78,7 @@
## 登记规则
- 总控和下属独立任务都必须登记稳定 `routing_key`;下属任务还必须登记 `parent_routing_key` 和可长期识别的 `durable_scope`,并作为后续复用的强制路由。未由已登记总控创建或明确接管的普通对话不得登记。
- 本表只登记本机元数据为用户独立任务的线程;`thread_source=subagent` 不得登记,完成或中止后由父线程归档。
- 本表只登记本机元数据为 `thread_source=user` 的用户独立任务;通过子代理创建接口或全量历史分叉产生的 `thread_source=subagent` 不得登记,完成或中止后由父任务汇总并归档。
- 独立任务创建成功并获得平台返回的稳定 ID 后立即登记;没有稳定 ID 不得写入临时名称或自行生成替代 ID。
- 任务名称可以修改,`task_id` 不得复用、改写或转给另一项工作。独立任务本轮完成后保留登记并改为 `idle`;后续原范围返工继续使用原 ID。重要业务结论必须写入对应业务、验收或进度文档。
- 跨任务共享契约由总控记录;独立任务回复必须带回自身 `routing_key`、`task_id`、`parent_routing_key`、状态、变更文件、验证结果、阻断项和建议下一步。
@@ -76,8 +92,10 @@ role: controller | independent_task
routing_key: <长期职责键>
task_id: <已登记 ID>
parent_routing_key: <所属总控键;总控自身填 self>
work_item_id: <当前工作包稳定 ID>
目标: <单一交付目标>
范围: <目录/模块>
完成条件: <可客观核验的结束门禁>
共享契约: <依赖的接口、模型或文件>
回传: <状态、变更文件、验证命令/结果、阻断项>
```