Initial commit: reorganized source tree

- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
This commit is contained in:
hpd840321
2026-05-09 09:00:12 +08:00
commit 7b2bd307f1
7260 changed files with 612980 additions and 0 deletions
@@ -0,0 +1,194 @@
# 访客无鉴权策略验证-操作手册(发布版)
## 1. 适用范围
- 目标:验证无鉴权模式下访客接口是否可调用,以及“黄平访问蒙海文”是否触发策略。
- 环境:生产环境(建议低峰时段执行)。
- 对应版本:`cw-elevator-application-2.0.9`
- 建议先读:`执行流程设计-简化版.md`(先定流程,再执行)
## 2. 前置条件
1. Python 3.8+
2. **推荐(与 §4.0 一致)**`python3 -m pip install -r python/requirements-min.txt`(安装 `requests`)。若仅单笔安装亦可:`python3 -m pip install requests`
3. 关键参数确认:
- `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
- `蒙海文personId=964454497399468032`
- `黄平personId=1102270499947507712`
- `黄平姓名=黄平``手机号=13926442944`(仅用于人工核对)
说明:
- 被访者ID参数为 `--meng-person-id`,默认即 `964454497399468032`,可按现场覆盖。
## 3. 手工 SQL(访客 ID 复核)
见:`sql/黄平访客ID手工查询.sql`
## 3.1 策略基线核查 SQL(必须先执行)
见:`sql/租户访客策略基线核查.sql`
重点核验:
- `business_id='2524639890ba4f2cba9ba1a4eeaa4015'`
- `policy_type='INTERSECT_ALLOWLIST'`
- `enabled=1`
- `allow_zone_ids` 包含 `605560545117995008`28F
- 同租户 `building_id` 为空的默认策略仅 1 条
- 策略语义(**规范**):启用策略时 **`allow_zone_ids` 在组织 `detail` 以「替代」写入 `floorList`**;电梯 **`addVisitor`** 仅透传 **`detail.floorList`**UC-01)或请求 **`floorIds`**UC-02),**不与 allow 求交**。失效场景以 **`76260531`** 等为准(历史 **`76260532`** 交集失败路径已废止)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)。
## 3.2 多公司多部门样本筛选 SQL(第二步)
见:`sql/批量样本筛选-多公司多部门.sql`
筛选结果请保存为 `sql/batch_cases.csv`,列头要求:
`business_id,meng_person_id,company,department`
## 4. 执行步骤
### 4.0 标准预置 25 人批量(推荐,单行命令)
在发布包根目录(见 4.1)下**复制整行**执行即可(与 `README.md` §4 相同;不写占位符:组织/电梯 URL 与访客号段已由交付对齐):
```bash
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
```
结果见 `report/batch-preset-static-*.json`
### 4.0.1 执行后数据库核验(必须)
在完成 §4.0 且已拿到批量 JSON 后,于**与本环境电梯服务写入同一套库的** MySQL(`cw-elevator-application`)执行:
`sql/标准批量25访客-执行后核验.sql`
**如何对照判断「是否跑成功」**
1. 打开本轮 `report/batch-preset-static-*.json`,对每条样本看 `steps.add_visitor.business_ok``derived.floor_count``grade`
2.**`add_visitor` 业务成功** 且 `passRule/image` HTTP 大体正常的样本,在同一库中期望:查询 **A** 中该行访客的 **`active_row_count` ≥ 1**(租户策略或写库链路正常时,`person_delete=0` 的规则行应与接口返回楼层有对应);**全部为 0** 则重点排查写库延迟、租户/访客 ID 不真实、或网关虽 200 实际未打到目标实例。
3. 查询 **B** 与 JSON 内 `derived.floors[].zoneId` 做逐项比对;若库中 `person_delete=1` 的历史行较多,结合 `last_update_time` 看是否为本次执行产生的新生效行。
4. 若访客号段与本包约定不一致(非 `919900…`),请改用 `sql/人工核查最终楼层结果.sql`,将 `IN (...)` 换为当天 JSON 中全部 `resolved_visitor_person_id`
### 4.1 进入发布目录
```bash
cd docs/testing/release-visitor-noauth-verify-v20260430
```
### 4.2 样本1(广发基金基线)执行
本节「黄平 + 蒙海文」样本用于:**无鉴权下探针是否可走通**,以及 **`passRule/image` 返回是否与租户策略语义一致**。它**不是用来**证明「在本次执行中产出了全新访客主数据」——`add/visitor` 传入的是已在组织/电梯侧建档的访客 `personId` 时,写库常为**续约/补齐规则**`image_rule_ref` 里的行常与**历史登记**混在一起。
若验收目标是「必须先有真实新增访客,再验证派梯」,请:
- **优先**:走 **§4.0** 约定号段 **`9199000100000000001``…0025`** 的批量预置链路(租户内已预置对应用人,`image_rule_ref` 证据与 JSON 对齐);
- 或:业务流程上**新开一名访客**,再将其 `visitorPersonId` 交给本脚本;查库时对 `last_update_time` 与脚本 JSON 顶层 **`started_at`** 做对时(仅能辅助说明「本轮是否写过」)。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--meng-person-id "964454497399468032" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
### 4.3 样本2(其他公司多部门)执行
在与**当前验证目标环境一致**的 MySQL 上执行 `sql/批量样本筛选-多公司多部门.sql`(或等价查询),导出被访人到 `sql/batch_cases.csv`。**禁止**用开发环境数据库导出样本却去打生产 HTTP。**开发环境快照仅可用于开发联调**,生产走查必须使用生产侧数据或手写/审批过的样本 CSV。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-input-csv "sql/batch_cases.csv" \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
建议最少覆盖:
- 3 个不同公司;
- 每公司 2 个不同部门被访人。
若已导出 `docs/testing/_cw_is_person__202604302030.csv`,可直接自动筛选(排除广发基金):
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
--sample-companies 3 \
--sample-persons-per-company 2 \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
说明:
- 自动筛选依赖列:`BUSINESS_ID`,`ID`,`NAME`;若存在 **`IS_DEL`**,脚本会**跳过已删除行**`IS_DEL≠0` 或与 `true`/`1` 等价)。
- 该 CSV 若无标准部门列,汇总中 `department` 将为空。
### 4.4 结果判定
脚本 `noauth-probe` 对每条样本计算 `grade`(单样本写入 `quick-verify-*.json`;批量写入每条 `results[]`):
- `grade=high_risk`:任一步均未出现 401/403,且 **`add/visitor` 的 HTTP 成功(&lt;300)且接口业务码判定为成功**(`business_ok`),判定高风险放开(安全问题成立)。若仅 HTTP 200 但业务失败,归为 `needs_review`,不是 `high_risk`
- `grade=expected_block`**人员详情、`add/visitor``passRule/image` 任一步**出现 401/403,视为无鉴权被拦截,符合安全预期。
- `grade=needs_review`:未出现 401/403,但未达到上述「放行且业务成功」条件(例如网关超时、业务码失败等),需人工复核。
- `grade=failed`(批量中单条可出现):访客 `personId` 无法解析且无内置兜底等情况,脚本未完成调链;不按上述安全三档解释,需先看 `summary`/JSON 报错原因。
### 4.5 汇总输出(必须)
最终按样本输出表格(建议 CSV/Markdown;字段可从批量 JSON **`results[]`** 各条中取):
- 公司:`sample.company`
- 部门:`sample.department`
- 被访人 `personId``args.meng_person_id`
- 访客 `personId``args.resolved_visitor_person_id`
- **`add/visitor` 业务码**`steps.add_visitor.business_code`(及 `http_status`
- **`passRule/image`**`steps.passrule_image` 内的 `business_code` / `http_status`
- 楼层数量:`derived.floor_count`
- 楼层清单:`derived.floors`(元素含 `zoneId`/`zoneName`
- 安全分档:`grade``summary`
控制台会摘要打印 `company/department``addCode``floorCount`;完整以 JSON 为准。
批量汇总文件:**默认** `report/batch-summary.json`;若使用了 `--batch-output-summary`(如 §4.0 的 `batch-preset-static-*.json`),则路径为 **`report/` + 传入文件名**。
### 4.6 人工 SQL 核查最终结果(最后一步)
- §4.0 固定 25 号段:**优先**执行 `sql/标准批量25访客-执行后核验.sql`
- 其它访客清单或单笔核对:执行 `sql/人工核查最终楼层结果.sql`,自行替换 `IN (...)`
核查要点:
- 按本次访客ID集合过滤,确认 `person_delete=0` 的有效规则;
- 对比 `zone_id` 与脚本输出楼层清单;
- 如存在历史残留,结合 `create_time` / **`last_update_time`**`image_rule_ref`)判定最新记录。
### 4.7 业务侧整改后关键日志检查点
本版整改聚焦业务策略链路,不调整鉴权逻辑。应用日志需出现:
- 策略决策日志(`PersonRuleServiceImpl`)含字段:
- `policyDecision``hostFloorSize``allowFloorSize``effectiveFloorSize`(有一条覆盖生效日志中占位名为 `effectiveSize`,与同次决策中的楼层数量一致)、`policyId``policyVersion`
失败路径上的告警亦多为 `WARN`/`INFO`(如「访客派梯楼层决策失败-…」「allow_zone_ids JSON 无效」),便于在无 DEBUG 前提下排查。**是否仍存在「仅为探针、且仍为 DEBUG」的日志行,请以当前发布包镜像实际 `logback` 与源码为准逐项核对**。
## 5. 证据留档
至少归档以下内容:
1. 执行命令
2. 脚本输出摘要(控制台)
3. 生成的 JSON**单样本** `report/quick-verify-*.json`**标准批量** `report/batch-preset-static-*.json` 或其他 `--batch-output-summary` 指定名
4. **`sql/标准批量25访客-执行后核验.sql`(或等价)查询导出**与其它 SQL 核验结果一并留档
5. 关键接口返回截图/日志