chore(repo): 导入 M-Z 业务底座 V1.9 基线并建立仓库规范
按周工交付的 SEC-Z-01 清理后源码建立 M-Z 主干,并按 Git 仓库惯例重排目录。 - aomin-gateway/ 后端工程 87 文件,原样保留,路径与构建命令未变 - demo/ 演示前端与设备模拟器 9 文件(原 02_前端与设备端),非正式三端 - docs/handover/ 交付与安全清理材料 6 份,内容未改 - docs/contract/ J-00 规格、OpenAPI、内部五接口、状态机、Mock 样例 - docs/reference/ 指纹与校验清单,含 84 个源码文件的 sha256 清单 目录重排只动位置不动内容:源码树 84 文件哈希与交付一致,逐文件自校验通过; 12 条 Flyway 迁移与交付包内镜像逐字节一致。 未纳入:迁移镜像目录(与工程内一套重复,改留指纹)、target/、证据 raw、 应急恢复脚本、评审用虚构台账数据。 安全:SEC-Z-01 15 处明文已清零,导入前重新扫描无新增命中,本仓库无历史污染。 行尾按交付字节原样保存(.gitattributes 设 * -text),不做归一化以免整树摘要失效。
This commit is contained in:
commit
a7605ef8b8
121 files changed
+23629
No files matched your search
@@ -0,0 +1,79 @@
|
||||
# 包内容与使用说明
|
||||
|
||||
> 本包是 **M-Z 业务底座的受控源码**(SEC-Z-01 清理后),只覆盖中段业务层,不含其他段的东西。
|
||||
> 用途:陈工按 AM-S1-GOV-020 §6.2(1) 接收此源码,建立唯一主干。
|
||||
|
||||
---
|
||||
|
||||
## 一、包里有什么(108 个条目)
|
||||
|
||||
| 目录 / 文件 | 数量 | 是什么 |
|
||||
|---|---|---|
|
||||
| `aomin-gateway/` | 87 | **M-Z 业务层完整 Maven 工程**:`pom.xml`、`src/main`(84 个文件:controller / service / dao / biz / engine / 迁移脚本 / 配置)、`README.md`、`start-gateway.bat` |
|
||||
| `03_数据库与Flyway迁移/` | 13 | **迁移镜像**:12 条 SQL(V1.0.0~V1.0.28)+ 迁移说明。与 `aomin-gateway/src/main/resources/db/migration` **逐字节一致**,供"应用与镜像同源"核对 |
|
||||
| `04_OpenAPI与内部IoT契约/` | 6 | J-00 接入接口规格(md + OpenAPI yaml)、内部五接口定义、状态机、Mock 样例、使用说明 |
|
||||
| `01_SEC-Z-01_最小安全清理差异清单.md` | 1 | 15 处明文逐处改了什么 |
|
||||
| `02_SEC-Z-01_敏感信息扫描报告.md` | 1 | 扫描范围、结果、复算方法、盲区、轮换结论 |
|
||||
| `03_Z-02_清理后哈希与构建说明.md` | 1 | 清理前后指纹、构建步骤、入库顺序(**先清后推**) |
|
||||
| `04_155条证据适用边界.md` | 1 | 155 条重跑结果,以及**它不能证明什么** |
|
||||
| `gitignore_建议.txt` | 1 | 建主干时直接用的 `.gitignore` |
|
||||
| `SHA256SUMS_包内.txt` | 1 | 包内文件哈希,解压后在包根执行 `sha256sum -c` 即可校验 |
|
||||
|
||||
---
|
||||
|
||||
## 二、包里**没有**什么,为什么
|
||||
|
||||
| 没给 | 原因 |
|
||||
|---|---|
|
||||
| `02_前端与设备端源码`(8 文件,演示前端) | 三端由陈工按 §6.2(3) 统一接入。这是评审用演示前端,给了反而分不清哪套是主干。**需要对照可以单独要** |
|
||||
| `06_统一闭环题自测证据/raw`(12 份结果 JSON、11 份日志) | 体积大、每轮重跑全变。证据按受控目录交付,不进代码主干;要复跑见 `04` 里的命令 |
|
||||
| `99_应急恢复(非正式路径)` | 明确是应急手段,不是主干迁移序列。给进去容易被当成常规路径 |
|
||||
| `评审用虚构台账数据.sql` | 演示数据,不属于主干 |
|
||||
| `09_代码与版本/SHA256SUMS.txt`(131 项全包清单) | 那是整个评审包的清单,路径以评审包为根;本包用 `SHA256SUMS_包内.txt`,路径与包内一致,可直接校验 |
|
||||
| 明文口令 | 已按 SEC-Z-01 清空,**一个字符都没有** |
|
||||
|
||||
---
|
||||
|
||||
## 三、怎么用(三步)
|
||||
|
||||
```bash
|
||||
# 1) 校验(在解压后的包根)
|
||||
sha256sum -c SHA256SUMS_包内.txt
|
||||
|
||||
# 2) 编译(JDK 21;离线仓库按你们环境改)
|
||||
cd aomin-gateway
|
||||
mvn -o -q -s <settings.xml> -DskipTests clean package
|
||||
# 产物 target/aomin-gateway-0.0.1-SNAPSHOT.jar,约 43.5 MB
|
||||
|
||||
# 3) 启动(必须带 DB_PASS,否则启动中止、退出码 1)
|
||||
set DB_PASS=<口令>
|
||||
java -jar target/aomin-gateway-0.0.1-SNAPSHOT.jar --server.port=8080 --server.address=0.0.0.0
|
||||
curl http://127.0.0.1:8080/health
|
||||
# 预期 db=connected、tables=87、flyway=1.0.28、status=UP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、建主干前必读的两条
|
||||
|
||||
**① 顺序不能反:先清后推。**
|
||||
当前目录**不是 git 仓库**,是干净起点。`git init` 必须在 15 处清理完成之后——一旦推上去,即使删除文件,第一条提交里仍有明文,只能重写全部历史。详见 `03_Z-02_清理后哈希与构建说明.md` §4.2。
|
||||
|
||||
**② 迁移只有一套序列。**
|
||||
`aomin-gateway/src/main/resources/db/migration` 与 `03_数据库与Flyway迁移/` 是同一套 12 条的两次出现,**不是两套**。主干只保留一套默认序列;若两者路径必须二选一,以应用内那份为准,镜像目录作对照。
|
||||
|
||||
---
|
||||
|
||||
## 五、已知边界(不让接收方误判)
|
||||
|
||||
| 项 | 状态 |
|
||||
|---|---|
|
||||
| A-Z-01/02/03 | **未关闭**。作者自测通过,仍需接收方复验签认;本包不构成关闭 |
|
||||
| 并发 PULL | 未覆盖(`v20` 是串行 10 条),由谢工按完整矩阵补测 |
|
||||
| 真机 | 未覆盖,等黄工真机窗口 |
|
||||
| 前端三端 | 不在本包范围 |
|
||||
| 口令轮换 | **未轮换**,登记为待确认(见 `02` §4) |
|
||||
|
||||
---
|
||||
|
||||
*对应 GOV-020:Z-01(差异+扫描+轮换结论)、Z-02(哈希+构建说明+155 条边界)。*
|
||||
@@ -0,0 +1,126 @@
|
||||
# SEC-Z-01 最小安全清理差异清单(Z-01)
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| 依据 | AM-S1-GOV-020 §4.2「第一优先级:完成 SEC-Z-01 最小安全清理」 |
|
||||
| 执行人 | 周工 |
|
||||
| 执行时间 | 2026-11-13 11:20–11:45 |
|
||||
| 范围 | **15 处明文** + **1 处启动守卫**(为满足"缺参明确失败") |
|
||||
| 是否升版 | **否**,V1.9 内做最小安全清理,未升 V1.10,无无关重构 |
|
||||
| 口令复述 | **本件不含原口令任何字符**,差异表中一律写作「(原值已脱敏)」 |
|
||||
|
||||
---
|
||||
|
||||
## 一、清理前后总览
|
||||
|
||||
| 项 | 清理前 | 清理后 |
|
||||
|---|---|---|
|
||||
| 含明文口令的文件 | **15 个** | **0** |
|
||||
| 明文出现次数 | 15 处(每文件 1 处) | 0 |
|
||||
| 配置层(yml) | 带非空默认值 | 无默认值,缺参启动中止 |
|
||||
| 脚本层(py) | 带非空默认值 | 无默认值,缺参直接退出 |
|
||||
| 文档层(md) | 写出明文示例 | 改为占位符 |
|
||||
| 历史包 | 6 个 zip 内含旧凭据 | 已移入受控归档目录,标注禁止外发 |
|
||||
|
||||
---
|
||||
|
||||
## 二、逐处差异(15 处)
|
||||
|
||||
### A 类:后端配置(1 处)
|
||||
|
||||
| # | 文件 | 位置 | 改前 | 改后 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `01_后端源码/src/main/resources/application.yml` | `spring.datasource.password` | `${DB_PASS:<原值已脱敏>}` | `${DB_PASS}` |
|
||||
|
||||
同时把上方两行自相矛盾的注释("包里不再有第二处明文"——实际上还有 14 处)改成实际口径。
|
||||
|
||||
### B 类:Python 证据脚本(12 处)
|
||||
|
||||
12 个脚本写法相同,改法相同。以一处示意:
|
||||
|
||||
| 改前 | 改后 |
|
||||
|---|---|
|
||||
| `DB_PASS = os.environ.get("AOMIN_DB_PASS", "<原值已脱敏>")` | `DB_PASS = os.environ.get("AOMIN_DB_PASS")`<br>加 4 行守卫:为空则 `raise SystemExit(...)`,打印设置方法 |
|
||||
|
||||
| # | 文件 |
|
||||
|---|---|
|
||||
| 2 | `06_统一闭环题自测证据/alarm_retry_test.py` |
|
||||
| 3 | `06_统一闭环题自测证据/closed_loop_test.py` |
|
||||
| 4 | `06_统一闭环题自测证据/cmd_chain_test.py` |
|
||||
| 5 | `06_统一闭环题自测证据/run_evidence.py` |
|
||||
| 6 | `06_统一闭环题自测证据/scope_test.py` |
|
||||
| 7 | `06_统一闭环题自测证据/v15_fix_test.py` |
|
||||
| 8 | `06_统一闭环题自测证据/v16_fix_test.py` |
|
||||
| 9 | `06_统一闭环题自测证据/v17_merge_test.py` |
|
||||
| 10 | `06_统一闭环题自测证据/v18_fix_test.py` |
|
||||
| 11 | `06_统一闭环题自测证据/v19_gov008_test.py` |
|
||||
| 12 | `06_统一闭环题自测证据/v20_node_test.py` |
|
||||
| 13 | `06_统一闭环题自测证据/stamp_evidence.py`(特殊:原为内联调用 `"-p" + os.environ.get(...)`,改为在模块顶部定义 `DB_PASS` 并加同样的守卫,调用处改引用常量) |
|
||||
|
||||
### C 类:说明文档(2 处)
|
||||
|
||||
| # | 文件 | 位置 | 改前 | 改后 |
|
||||
|---|---|---|---|---|
|
||||
| 14 | `05_启动构建与测试说明/启动构建与测试说明.md` | §5 启动 | `export DB_PASS=<原值已脱敏>` | `export DB_PASS=<口令>`,注释改为"必需:配置里已无默认值,未设置时启动直接失败" |
|
||||
| 15 | `09_代码与版本/README.md` | 环境变量表 | 默认值列写出明文 | `root` / **必需,无默认值**;说明未设置时脚本直接退出 |
|
||||
|
||||
---
|
||||
|
||||
## 三、新增 1 处启动守卫(为什么必须有)
|
||||
|
||||
**这是本次唯一的代码改动,不是重构,是为满足 §4.2「缺少必需口令时明确失败」。**
|
||||
|
||||
### 问题:只删默认值,并没有"明确失败"
|
||||
|
||||
先按最省事的方式改(`password: ${DB_PASS}` 不设默认值)实测了一次,结果不是报"缺少 DB_PASS",而是:
|
||||
|
||||
```
|
||||
Access denied for user 'root'@'localhost' (using password: YES)
|
||||
```
|
||||
|
||||
原因:Spring Boot 的占位符解析在“解析不到”时是**忽略**而不是报错,于是拿空口令去连库。表现出来像"口令错了",实际是"根本没配"——这正是不允许的静默回退。
|
||||
|
||||
### 处理:在 `main` 里提前拦住
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `src/main/java/cn/aomin/gateway/GatewayApplication.java` | `main()` 首行调用 `requireEnv("DB_PASS", "数据库口令")`;新增私有方法 `requireEnv`,为空则打印提示并 `System.exit(1)` |
|
||||
|
||||
改后实测输出(退出码 **1**):
|
||||
|
||||
```
|
||||
[启动中止] 缺少必需的环境变量 DB_PASS(数据库口令)。
|
||||
SEC-Z-01:程序不再内置任何默认口令,也不会回退到包内明文。
|
||||
设置方法:Windows set DB_PASS=<口令> Linux/macOS export DB_PASS=<口令>
|
||||
```
|
||||
|
||||
**只校验"有没有",不校验"对不对",也不打印任何取值。**
|
||||
|
||||
---
|
||||
|
||||
## 四、构建产物与缓存清理
|
||||
|
||||
| 对象 | 处理 |
|
||||
|---|---|
|
||||
| `target/classes/application.yml` | 旧副本含明文;`mvn clean package` 后已由新文件覆盖,实测 jar 内配置 **0 命中** |
|
||||
| `__pycache__` / `*.pyc` | 已删除(编译产物里会残留字符串常量) |
|
||||
| 应用日志 `G:/aomin-dev/logs` | 实测 **0 命中**,保留(不含凭据,且是运行证据) |
|
||||
| `target/` 其余内容 | 43 MB 构建产物,已随 `clean` 重建;**不入代码仓库**(见 `03` 的 `.gitignore`) |
|
||||
|
||||
---
|
||||
|
||||
## 五、历史包处置
|
||||
|
||||
`_历史包/` 下 6 个 zip 都含旧凭据(解开后逐成员扫描,命中 13~15 处)。直接按字节搜 zip 查不出来,因为内容被 deflate 压缩过。
|
||||
|
||||
| 处理 | 说明 |
|
||||
|---|---|
|
||||
| 目录改名 | `_历史包/` → **`_历史包_含旧凭据_禁止外发/`** |
|
||||
| 登记 | 同目录 `_清单_含旧凭据.md` 记录每个 zip 的字节数、SHA-256、含旧口令文件数 |
|
||||
| 约束 | **禁止外发、禁止入代码库、禁止上传公共 AI**;仅作内部留档 |
|
||||
|
||||
> 这是"轮换结论"要覆盖的一部分:口令一旦进过包,就不能假设它只存在于一个地方。
|
||||
|
||||
---
|
||||
|
||||
*后续:清理后哈希、构建说明、155 条证据边界见同目录 `03_…` 与 `04_…`。*
|
||||
@@ -0,0 +1,113 @@
|
||||
# SEC-Z-01 敏感信息扫描报告(Z-01 附件)
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| 扫描时间 | 2026-11-13 11:45 |
|
||||
| 扫描人 | 周工 |
|
||||
| 结论 | 包内、源码树、构建产物、日志 **全部 0 命中**;历史归档包 6 个含旧凭据,已隔离 |
|
||||
| 模式 | 原口令字面值(大小写不敏感)+ URL 编码形式 `%40` |
|
||||
|
||||
---
|
||||
|
||||
## 一、扫描范围与结果
|
||||
|
||||
| # | 位置 | 类型 | 命中 |
|
||||
|---|---|---|---|
|
||||
| 1 | `候选模型评审包/`(全部文件,含 md / yml / py / json / xml) | 文本 | **0** |
|
||||
| 2 | `候选模型评审包/`(全部文件,**按字节**,含 pyc 等二进制) | 二进制 | **0** |
|
||||
| 3 | `01_后端源码/src` + `pom.xml`(工作目录 `G:/aomin-dev/app/aomin-gateway`) | 文本 | **0** |
|
||||
| 4 | `aomin-gateway-0.0.1-SNAPSHOT.jar` → `BOOT-INF/classes/application.yml` | 二进制 | **0** |
|
||||
| 5 | `target/`(全部,43 MB,构建产物) | 二进制 | **0** |
|
||||
| 6 | `G:/aomin-dev/logs`(全部,6.1 MB) | 二进制 | **0** |
|
||||
| 7 | `_历史包_含旧凭据_禁止外发/`(6 个 zip,**解压后逐成员**) | 文本 | **13~15 处/包,已隔离** |
|
||||
|
||||
### 第 7 项明细(历史包)
|
||||
|
||||
| 文件 | 含旧口令文件数 |
|
||||
|---|---|
|
||||
| 周工_V1.9定点修复包_20261112_上午版.zip | 15 |
|
||||
| 周工_V1.9定点修复包_20261112_第二版.zip | 15 |
|
||||
| 周工_候选模型评审去敏精简包_V1.6_20261111.zip | 13 |
|
||||
| 周工_候选模型评审去敏精简包_V1.8_20261111.zip | 15 |
|
||||
| 周工_候选模型评审去敏精简包_V1.9.1_20261112.zip | 15 |
|
||||
| 周工_候选模型评审去敏精简包_V1.9_20261111.zip | 13 |
|
||||
|
||||
**处置**:整个目录改名为 `_历史包_含旧凭据_禁止外发`,同目录 `_清单_含旧凭据.md` 登记每个包的字节数与 SHA-256。禁止外发、禁止入代码库、禁止上传公共 AI。
|
||||
|
||||
> 这一条要特别说明:**直接对 zip 做字节搜索是查不出来的**,因为成员内容被 deflate 压缩过,第一遍按字节扫全部返回"否",是错的。必须解开逐成员扫。
|
||||
|
||||
---
|
||||
|
||||
## 二、复算方法(陈工可原样执行)
|
||||
|
||||
```python
|
||||
import os, zipfile
|
||||
|
||||
SECRET = b"<原口令>" # 自行填入,不要写进任何文件
|
||||
hits = []
|
||||
|
||||
for root in [r"<包根>", r"<源码根>/src", r"<源码根>/target", r"<日志目录>"]:
|
||||
for dp, dn, fn in os.walk(root):
|
||||
for f in fn:
|
||||
p = os.path.join(dp, f)
|
||||
try:
|
||||
if os.path.getsize(p) > 30 * 1024 * 1024:
|
||||
continue
|
||||
if SECRET in open(p, "rb").read():
|
||||
hits.append(p)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 压缩包必须解开再扫
|
||||
for zp in [r"<_历史包>/*.zip"]:
|
||||
import glob
|
||||
for p in glob.glob(zp):
|
||||
with zipfile.ZipFile(p) as z:
|
||||
for nm in z.namelist():
|
||||
try:
|
||||
if SECRET in z.read(nm):
|
||||
hits.append(p + "!" + nm)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print("命中:", len(hits))
|
||||
for h in hits:
|
||||
print(" ", h)
|
||||
```
|
||||
|
||||
判读规则:
|
||||
|
||||
- **文本命中和字节命中分开看**。只 grep 文本会漏掉 pyc、jar、zip;
|
||||
- **zip / jar 必须解压后扫**,压缩态下的字节搜索没有意义;
|
||||
- 只扫"当前工作副本",不扫 git 历史——**本次交付时尚无 git 仓库**(见下节)。
|
||||
|
||||
---
|
||||
|
||||
## 三、盲区声明(扫描覆盖不到什么)
|
||||
|
||||
| 盲区 | 说明 |
|
||||
|---|---|
|
||||
| Git 历史 | 当前 `G:/aomin-dev/app/aomin-gateway` **不是 git 仓库**,包内也没有 `.git`。所以不存在历史污染;这也是必须在首次 `git init` **之前**完成清理的原因 |
|
||||
| 数据库内部 | 本扫描只查文件。数据库用户表里的口令哈希不属于"明文口令",另行按鉴权设计处理 |
|
||||
| 其他凭据 | 本次只针对 SEC-Z-01 指出的那一处数据库口令。若后续新增 token、AK/SK,需另做一次扫描 |
|
||||
| 聊天记录与截图 | 不在本次范围。已在回执中说明"不得在回复、截图、差异表或本通知中复述原口令" |
|
||||
| 已外发的旧包 | 6 个历史包若曾通过群聊或邮件发出,**接收方副本无法回收**——按 GOV-020 §4.2,这是"检查历史包、受控配置和访问记录"要求的部分,如实列出,不隐瞒 |
|
||||
|
||||
---
|
||||
|
||||
## 四、轮换结论(要求 Z-01 必须给的一句)
|
||||
|
||||
**结论:不轮换,但登记为"待确认项",由仇总/陈工判断是否升级。**
|
||||
|
||||
理由(如实写,不美化):
|
||||
|
||||
1. 该口令是 **评审机本地 MySQL 演示库** 的 `root` 口令(库名 `aomin_dev`),不是生产凭据,也不是任何对外服务的入口;
|
||||
2. 该库仅监听 `127.0.0.1:3306`,未对公网开放;
|
||||
3. **但**:它已经进过 6 个历史包,若这些包曾被外发(群聊、邮件、他人机器),则等于该口令已离开本机;
|
||||
4. 因此本件的表述是:**本地场景不需要轮换;一旦确认历史包曾外发,立即轮换并重跑 155 条**(重跑约 13 分钟,成本可控)。
|
||||
|
||||
> 不写"已轮换"——因为确实没换,换了就要重跑全部证据,那是另一件事,不能混在这次清理里糊过去。
|
||||
|
||||
---
|
||||
|
||||
*扫描与复算脚本、结果均可在本机重现;如需基线比对,见 `03_Z-02_清理后哈希与构建说明.md`。*
|
||||
@@ -0,0 +1,175 @@
|
||||
# Z-02 清理后源码树哈希、包哈希与构建说明
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| 依据 | AM-S1-GOV-020 §4.4「Z-02」 |
|
||||
| 交付人 | 周工 |
|
||||
| 时间 | 2026-11-13 |
|
||||
| 结论 | 清理后指纹已重算;155 条在本基线**真实重跑并全过**,不是沿用旧结果 |
|
||||
|
||||
---
|
||||
|
||||
## 一、清理前后指纹对比
|
||||
|
||||
| 指纹 | 清理前(V1.9 第二版) | 清理后(本件) | 变化原因 |
|
||||
|---|---|---|---|
|
||||
| 源码树摘要(`01_后端源码/src`,84 文件) | `60FA6938…`(上批) | **`5E9F894B0D1071969A968F2A9B1451279ADF39D423148186886BFD064398F286`** | 改了 1 个 java(启动守卫)+ yml 注释与默认值 |
|
||||
| 可执行 jar | `43,516,447 B` / `652E1602…` | **`43,517,256 B`** / **`1F38F527605F09AA45E9E54528AFB11230469E1B197FA001C06E8725FD102192`** | 重新构建,含新配置与新类 |
|
||||
| 契约版本 | `1.8.1` | `1.8.1` | **未变** |
|
||||
| 迁移版本 | `1.0.28`(12 条) | `1.0.28`(12 条) | **未变**(本次不动 DDL) |
|
||||
| 明文口令 | 15 处 | **0 处** | 本件清理目标 |
|
||||
|
||||
> 源码树摘要算法:把 `01_后端源码/src` 下每个文件的「相对路径 + 该文件 SHA-256」按路径排序后拼接,再整体算一次 SHA-256。改一个字节即变,等效于"这一棵树"的指纹(不是 Git commit)。
|
||||
|
||||
---
|
||||
|
||||
## 二、本次改动文件逐个哈希(16 个)
|
||||
|
||||
| # | 文件 | 字节 | SHA-256(改后) |
|
||||
|---|---|---|---|
|
||||
| 1 | `01_后端源码/src/main/resources/application.yml` | 9,636 | `3912006F4C6432965DAF2F590D229509363A1FEAFF9D7FB60DF6F93E5D6C16C9` |
|
||||
| 2 | `01_后端源码/src/main/java/cn/aomin/gateway/GatewayApplication.java` | 2,639 | `2C315FCBABD70D5282AE33CA00DCEAFB352D14253C6B3D33D9C2A3FC717DC1B6` |
|
||||
| 3 | `05_启动构建与测试说明/启动构建与测试说明.md` | 16,116 | `D4AAF430598FD1DB121697B5519F0206D7CFA5552C6C400292CABF18730A8BC1` |
|
||||
| 4 | `09_代码与版本/README.md` | 5,845 | `50F128904869F1F56676DA06A42794C77106154C946D91AEA95BF24A02CFA365` |
|
||||
| 5 | `06_统一闭环题自测证据/alarm_retry_test.py` | 6,708 | `24F062EAE16BF449170FA5D7A9404364F16950262108C9247C378DC2C9966E2A` |
|
||||
| 6 | `06_统一闭环题自测证据/closed_loop_test.py` | 9,579 | `F17E59D6B9F7B63CE7818108D4D574EEF60EB16FEB0E8E708EA91F15B5054C8E` |
|
||||
| 7 | `06_统一闭环题自测证据/cmd_chain_test.py` | 17,290 | `1C4FD7CF30D7A4ADBA4D61683449B8954D2FA630E5FEB079C97E9BCC3958035B` |
|
||||
| 8 | `06_统一闭环题自测证据/run_evidence.py` | 21,551 | `478D672726193874CD9544EAEDB92D6FA887A2BAAB7D211F753290204822CA37` |
|
||||
| 9 | `06_统一闭环题自测证据/scope_test.py` | 11,005 | `ACE8150FBC566D5AF796D4FADA14CC9927E4C8D6114DB919C883F307309E0651` |
|
||||
| 10 | `06_统一闭环题自测证据/stamp_evidence.py` | 10,670 | `DA33B7B431279FE5064420AD6C8BA7F48CED6E4B7EF79BC7AE0B3A0171D63035` |
|
||||
| 11 | `06_统一闭环题自测证据/v15_fix_test.py` | 11,575 | `C0C073AE6495717AF902F94552D9E40A69DCC67A8D840ECC3C130F322F6518EA` |
|
||||
| 12 | `06_统一闭环题自测证据/v16_fix_test.py` | 16,120 | `08C425D9620E414B56E2FEF59B9C632054F18BBA9EEBA92F640FB447CC3F51E7` |
|
||||
| 13 | `06_统一闭环题自测证据/v17_merge_test.py` | 11,748 | `A2BCBED23683554B1E661BD85304F056B55F2149272A7CBC72D7EE92546F7603` |
|
||||
| 14 | `06_统一闭环题自测证据/v18_fix_test.py` | 7,375 | `48EC29ACFA0F9E9EAE28971973B1095FBA77B7CF42C8027FBAC615D66C7197A4` |
|
||||
| 15 | `06_统一闭环题自测证据/v19_gov008_test.py` | 15,881 | `8599CBCF41E81E670598310D003FC03BAAD21CB0B0130EADAAB7A15A8858A4DC` |
|
||||
| 16 | `06_统一闭环题自测证据/v20_node_test.py` | 10,843 | `8DDBF8996B989D446D667D454DB222F2EAA15D0918F28C0033E4DAF53931088C` |
|
||||
|
||||
> 除以上 16 个,包内其余文件的哈希都在 `09_代码与版本/SHA256SUMS.txt` 里,本件已重新生成(原 131 项 → 现 131 项,内容更新)。
|
||||
|
||||
---
|
||||
|
||||
## 三、构建说明(可复现,约 21 秒)
|
||||
|
||||
### 环境
|
||||
|
||||
| 项 | 要求 |
|
||||
|---|---|
|
||||
| JDK | 21.0.2(`G:/aomin-dev/jdk-21.0.2`) |
|
||||
| Maven | 3.x,离线仓库 `G:/aomin-dev/downloads/settings.xml` |
|
||||
| 依赖 | 已预置在本地仓库,`-o` 离线模式可用 |
|
||||
|
||||
### 构建命令
|
||||
|
||||
```bash
|
||||
cd <源码根>/aomin-gateway
|
||||
mvn -o -q -s <settings.xml> -DskipTests clean package
|
||||
# 产物:target/aomin-gateway-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
实测:**21 秒**,`exit=0`,产物 `43,517,256 B`。
|
||||
|
||||
### 启动(**必须带 `DB_PASS`**)
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
set DB_PASS=<口令>
|
||||
# Linux / macOS
|
||||
export DB_PASS=<口令>
|
||||
|
||||
java -jar target/aomin-gateway-0.0.1-SNAPSHOT.jar --server.port=8080 --server.address=0.0.0.0
|
||||
```
|
||||
|
||||
**缺少 `DB_PASS` 会立即中止**(退出码 1),不会带着空口令去连库:
|
||||
|
||||
```
|
||||
[启动中止] 缺少必需的环境变量 DB_PASS(数据库口令)。
|
||||
SEC-Z-01:程序不再内置任何默认口令,也不会回退到包内明文。
|
||||
设置方法:Windows set DB_PASS=<口令> Linux/macOS export DB_PASS=<口令>
|
||||
```
|
||||
|
||||
### 启动后自检
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:8080/health
|
||||
```
|
||||
|
||||
本机实测返回:
|
||||
|
||||
```json
|
||||
{"code":0,"msg":"ok","data":{"app":"aomin-gateway","db":"connected","tables":87,
|
||||
"schema":"aomin_dev","redis":"connected","flyway":"1.0.28","alarmBacklog":0,
|
||||
"alarmStale":0,"alarmDeadLetter":0,"auditFailures":0,"warnings":[],"status":"UP"}}
|
||||
```
|
||||
|
||||
要点:`db: connected`、`tables: 87`、`flyway: 1.0.28`、`status: UP`。
|
||||
|
||||
---
|
||||
|
||||
## 四、入库建议(给陈工建主干时用)
|
||||
|
||||
### 4.1 `.gitignore`
|
||||
|
||||
见同目录 `gitignore_建议.txt`,核心是三条:
|
||||
|
||||
- `target/`、`*.jar` —— 构建产物不入库;
|
||||
- `.env`、`*.local.yml`、`application-local.yml` —— 本地配置可能含口令;
|
||||
- `06_统一闭环题自测证据/raw|out|screenshots/` —— 证据原始数据体积大、每轮变化,按受控目录单独交付,不进代码历史。
|
||||
|
||||
### 4.2 首次提交顺序(**顺序不能反**)
|
||||
|
||||
```
|
||||
① 确认 15 处已清、扫描 0 命中
|
||||
② git init
|
||||
③ 放入 .gitignore
|
||||
④ git add -A && git status ← 人工看一眼,确认没把 target/ 和 .env 加进来
|
||||
⑤ git commit -m "初始提交:M-Z 业务底座 V1.9 基线(SEC-Z-01 清理后)"
|
||||
⑥ git remote add origin <陈工给的地址> && git push -u origin main
|
||||
```
|
||||
|
||||
**为什么必须先清后推**:git 记录每一版。今天删掉明文、明天再提交一次,第一条提交里照样有。要彻底清只能重写全部历史(`filter-repo`),成本远高于现在清 15 处。
|
||||
|
||||
**好消息**:当前 `G:/aomin-dev/app/aomin-gateway` **不是 git 仓库**,包内也没有 `.git`,不存在历史污染,属于干净起点。
|
||||
|
||||
### 4.3 交付目录建议
|
||||
|
||||
```
|
||||
主干/
|
||||
├── src/main/java/… 业务代码(M-Z)
|
||||
├── src/main/resources/
|
||||
│ ├── application.yml 已无默认口令
|
||||
│ └── db/migration/ Flyway 12 条,最新 1.0.28
|
||||
├── pom.xml
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
证据材料(`06_…/raw`、`06_…/out`、截图)**不进主干**,走受控目录交付。
|
||||
|
||||
---
|
||||
|
||||
## 五、版本标识一致性(四项对齐)
|
||||
|
||||
| 标识 | 值 |
|
||||
|---|---|
|
||||
| 模型版本 | V1.9(已冻结,本次仅为 SEC-Z-01 最小安全清理,**未升 V1.10**) |
|
||||
| 源码树摘要 | `5E9F894B0D1071969A968F2A9B1451279ADF39D423148186886BFD064398F286` |
|
||||
| 可执行 jar | `1F38F527605F09AA45E9E54528AFB11230469E1B197FA001C06E8725FD102192`(43,517,256 B) |
|
||||
| 契约版本 | J-00 `1.8.1` |
|
||||
| 迁移版本 | Flyway `1.0.28`,12 条 |
|
||||
| 证据批次 | `R20261113-112443`,11 组 / 155 条 / 失败 0 |
|
||||
|
||||
---
|
||||
|
||||
## 六、交付包自检(打出包后实测)
|
||||
|
||||
| 项 | 结果 |
|
||||
|---|---|
|
||||
| 条目数 | 93(源码 87 + 4 份说明 + `gitignore_建议.txt` + `SHA256SUMS_源码契约迁移脚本.txt`) |
|
||||
| 解压后 `aomin-gateway/src` | 84 个文件,与包内 `01_后端源码/src` **逐文件哈希完全一致** |
|
||||
| 解压后含明文口令 | **0** |
|
||||
| 独立编译 | 解压到空目录后 `mvn -o -q -s <settings> -DskipTests compile` → **exit 0**,`GatewayApplication.class` 正常生成 |
|
||||
|
||||
> 包自身的 SHA-256 只在交付渠道给出,**不写进包内**(写进去包一改哈希就变,形成死循环)。
|
||||
|
||||
---
|
||||
|
||||
*配套材料:`01` 差异清单、`02` 扫描报告、`04` 155 条证据适用边界、`gitignore_建议.txt`。*
|
||||
@@ -0,0 +1,109 @@
|
||||
# 155 条作者证据的适用边界(Z-02 附件)
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| 依据 | AM-S1-GOV-020 §4.4「Z-02:……现有 155 条作者证据的适用边界;若作为清理后当前结果,必须真实重跑」 |
|
||||
| 处理结论 | **已真实重跑**,不是沿用清理前结果 |
|
||||
| 批次号 | `R20261113-112443` |
|
||||
| 结果 | **155 条 / 通过 155 / 未过 0**,11 组脚本 **失败 0 组** |
|
||||
|
||||
---
|
||||
|
||||
## 一、这 155 条是什么
|
||||
|
||||
| 证据文件 | 条数 | 覆盖内容 | 耗时 |
|
||||
|---|---|---|---|
|
||||
| `05_SOS链路.json` | —(非用例) | 单次闭环的原始请求/响应记录,不作计数 | 8.9s(与下一项同组) |
|
||||
| `06_命令链.json` | 23 | 命令七态、回执、幂等、状态机边界 | 58.6s |
|
||||
| `06_异常与权限.json` | 28 | 异常分支与对象级权限 | 同上组 |
|
||||
| `07_告警失败不吞事件.json` | 5 | 故障注入:规则异常 / 库异常 / 重试 / 死信 | 84.6s |
|
||||
| `08_闭环后半段.json` | 13 | 通知、家属确认、处置关闭 | 22.0s |
|
||||
| `09_数据范围.json` | 16 | 数据权限与可见范围 | 19.9s |
|
||||
| `10_摘要与状态防护.json` | 15 | rawRef 摘要、状态不可回退 | 34.0s |
|
||||
| `11_超窗与死信.json` | 15 | 时间源分流、退避、死信、审计回滚 | 286.2s |
|
||||
| `12_合并与替代.json` | 6 | 连续触发的合并与 superseded | 77.7s |
|
||||
| `13_GOV008整改.json` | 16 | GOV-008 定点整改项 | 105.8s |
|
||||
| `13_分区与一致性.json` | 8 | 分区维护、计数一致性 | 18.4s |
|
||||
| `14_命令节点闭环.json` | 10 | 领取节点、代次、租约、错节点拒收 | 42.7s |
|
||||
| **合计** | **155** | — | 约 13 分钟 |
|
||||
|
||||
---
|
||||
|
||||
## 二、为什么必须重跑(不是"为了好看")
|
||||
|
||||
清理动了三处会影响执行的东西:
|
||||
|
||||
1. **`application.yml` 的 `password`** 由「带默认值」改成「无默认值 + 缺参中止」——启动条件变了;
|
||||
2. **12 个证据脚本** 的口令来源由「环境变量或内置默认」改成「只认环境变量」——脚本启动条件变了;
|
||||
3. **`GatewayApplication`** 增加启动守卫——可执行产物变了。
|
||||
|
||||
换句话说,**清理前的 155 条是在"另一套启动条件"下跑出来的**,直接拿来当"清理后的当前结果"属于沿用旧结果。所以按 §4.4 那句"必须真实重跑"执行。
|
||||
|
||||
重跑后源码树摘要、jar 摘要、批次号全部更新,见 `03`。
|
||||
|
||||
---
|
||||
|
||||
## 三、这批证据能证明什么
|
||||
|
||||
| 能证明 | 依据 |
|
||||
|---|---|
|
||||
| 155 条在**这一棵源码树**(`5E9F894B…`)、**这一个 jar**(`1F38F527…`)、契约 `1.8.1`、迁移 `1.0.28` 上真实执行过 | 每份结果 JSON 的 `_meta` + `raw/_execution_manifest.json` |
|
||||
| 每组是哪个脚本、什么参数、几点开始几点结束、耗时多少、退出码几 | `raw/_run_logs/*.log`(11 份完整 stdout+stderr) |
|
||||
| 失败项不会被藏起来 | 清单外的结果自动标「历史结果补充索引」,**不计入通过数**;本次该数为 **0** |
|
||||
| 清理没有破坏原有功能 | 与清理前同为 155/155,无新增失败 |
|
||||
|
||||
---
|
||||
|
||||
## 四、这批证据**不能**证明什么(必须写明,否则就是夸大)
|
||||
|
||||
| 不能证明 | 说明 |
|
||||
|---|---|
|
||||
| **不是接收方复验** | 这是**作者自测**。按 §9.2 第 4 条,收到文件 ≠ 接收通过;A 类关闭要谢工、陈工签认,本件不构成关闭 |
|
||||
| **不含并发** | `v20_node_test.py` 是串行 10 条,**没有 Thread / 线程池 / 并发 PULL**。并发领取、节点与租约不匹配、重复/乱序/迟到回执,由谢工按完整矩阵补测 |
|
||||
| **不含真机** | 全部是接口级与故障注入。真实设备的上报、断连、无恢复帧场景,要等黄工真机窗口 |
|
||||
| **不代表生产性能** | 单机、本地 MySQL、单实例;没有压测、没有长稳 |
|
||||
| **不覆盖前端与小程序** | 只覆盖 M-Z 业务层与内部契约 |
|
||||
| **不是重复性统计** | 每项跑一次。偶发失败只能靠重跑发现,本批失败 0 不代表永不失败 |
|
||||
| **不覆盖 A-Z-02「停机超窗」的完整场景** | 有故障注入与死信验证,但"停服 60 分钟以上再起、事件被处理"需在共同环境由谢工/陈工复验 |
|
||||
|
||||
---
|
||||
|
||||
## 五、怎么复跑(陈工/谢工可按原样执行)
|
||||
|
||||
```bash
|
||||
# 1) 先起服务(必须带口令)
|
||||
set DB_PASS=<口令>
|
||||
java -jar aomin-gateway-0.0.1-SNAPSHOT.jar --server.port=8080 --server.address=0.0.0.0
|
||||
|
||||
# 2) 跑全部 11 组(约 13 分钟)
|
||||
cd 06_统一闭环题自测证据
|
||||
python run_all_evidence.py # 产出 raw/_execution_manifest.json + raw/_run_logs/*.log
|
||||
python stamp_evidence.py # 给每份结果写 _meta.execution
|
||||
python count_evidence.py # 对账,exit 0 = 155 条一致
|
||||
```
|
||||
|
||||
前置环境变量(缺一个都会失败或跳项):
|
||||
|
||||
| 变量 | 用途 | 缺失后果 |
|
||||
|---|---|---|
|
||||
| `DB_PASS` | 应用启动 | **启动中止**(退出码 1) |
|
||||
| `AOMIN_DB_PASS` | 12 个证据脚本 | **脚本退出**,提示设置方法 |
|
||||
| `AOMIN_MYSQL` | mysql 客户端路径 | 找不到命令,相关断言失败 |
|
||||
| `AOMIN_LOG` | 应用日志路径(`v17` 读横幅合并日志) | 误报"跳过 0 次" |
|
||||
| `NO_PROXY` | 本机回环不走代理 | 报 `10061`,与用例无关 |
|
||||
|
||||
---
|
||||
|
||||
## 六、复验入口(对应 GOV-011 / GOV-016 的 A 类)
|
||||
|
||||
| 关注点 | 脚本 | 建议核对 |
|
||||
|---|---|---|
|
||||
| A-Z-01 命令节点与代次 | `v20_node_test.py`(10 条)+ `cmd_chain_test.py`(23 条) | 领取后 `claimed_node_id` 落库、错节点 `NODE_MISMATCH`、历史空节点 `NODE_UNKNOWN`、旧节点+新代次仍被拒 |
|
||||
| A-Z-02 超窗补偿 | `v16_fix_test.py`(15 条)+ `alarm_retry_test.py`(5 条) | 无时间窗过滤、`receive_time` 库端打戳、退避与死信、人工回放 |
|
||||
| A-Z-03 审计可靠性 | `v16_fix_test.py` 的审计回滚段 | 审计写失败 → 业务整条回滚;`audit_fail_log` 可查可补录;重启后不清零 |
|
||||
|
||||
复验请填:**结论(通过/失败/未执行/不适用)+ 证据位置 + 日期**。作者不单方面宣布关闭。
|
||||
|
||||
---
|
||||
|
||||
*关联:`01` 差异清单、`02` 扫描报告、`03` 哈希与构建说明。*
|
||||
@@ -0,0 +1,51 @@
|
||||
# ─────────────────────────────────────────────
|
||||
# 代码主干 .gitignore(M-Z 业务底座)
|
||||
# 原则:源码、迁移、契约、测试脚本进仓库;
|
||||
# 构建产物、本地配置、日志、证据原始数据不进。
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
# 构建产物
|
||||
target/
|
||||
build/
|
||||
out/
|
||||
*.class
|
||||
*.jar
|
||||
*.war
|
||||
|
||||
# 本地配置(可能含口令,绝不入库)
|
||||
.env
|
||||
.env.*
|
||||
*.local.yml
|
||||
application-local.yml
|
||||
application-*-local.yml
|
||||
application-secret.yml
|
||||
|
||||
# 日志与临时
|
||||
logs/
|
||||
*.log
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
*.iml
|
||||
.vscode/
|
||||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
.pytest_cache/
|
||||
|
||||
# 证据原始数据(体积大、每轮变化;证据按受控目录单独交付,不进代码历史)
|
||||
06_统一闭环题自测证据/raw/
|
||||
06_统一闭环题自测证据/out/
|
||||
06_统一闭环题自测证据/screenshots/
|
||||
|
||||
# 系统
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Reference in new issue
Block a user