pmc 7a9e511132 test(03-02): Phase 3 端到端验收报告 (CRED-05 + CRED-06)
- 9 truth × 32 项独立断言全 PASS, FAIL = 0
- T1-T5: 客户端 GET 5 项 (user/admin token + 401 + swagger schema)
- T6: filter 4 种正则形态 (JSON/Pyrepr/Query/Fallback)
- T7: 不误伤 Authorization / Bearer 字段
- T8: admin PUT roundtrip + admin GET 脱敏 + client GET 明文
- T9: 端到端 logger.info 真打印 console 输出脱敏
- T_FINAL: DB 探针态还原 (probe_app/probe_secret_xxxx)
- 临时脚本均已删除 (_phase3_01_verify / _phase3_02_unit_test / _phase3_02_verify / _phase3_02_settings_check)
2026-05-08 10:28:26 +08:00

4.4 KiB
Raw Blame History

Phase 3 端到端验收报告CRED-05 + CRED-06

执行时间2026-05-08 执行命令python manage.py shell -c "exec(open('_phase3_02_verify.py', encoding='utf-8').read())" 结果ALL PASS — 32 项独立断言全部通过FAIL 数 = 0 临时验收脚本:跑完即删(_phase3_01_verify.py / _phase3_02_unit_test.py / _phase3_02_verify.py / _phase3_02_settings_check.py


9 条 Truth × 32 项独立断言

T1: client GET 携 user token → 200 + 明文

[PASS] T1.user_token_200: sc=200
[PASS] T1.success_true
[PASS] T1.app_id
[PASS] T1.access_token_plain: should be plaintext
[PASS] T1.no_mask_in_response

T2: client GET 携 admin token → 200 + 明文(不区分 admin / user token

[PASS] T2.admin_token_200
[PASS] T2.access_token_plain

T3: client GET 无 token → 401 + 标准壳层 success=false

[PASS] T3.no_token_401
[PASS] T3.success_false

T4: client GET 伪造 token → 401Redis 中无该 key

[PASS] T4.fake_token_401

T5: /swagger.json/ 含 /credential-slot/ 路径 + GET 方法

[PASS] T5.swagger_200
[PASS] T5.path_in_schema: keys_sample=['/achievement/achievements/', '/achievement/achievements/{id}/', '/achievement/achievements/{id}/check_achievement/', '/achievement/user-achievements/', '/achievement/user-achievements/check_and_grant/']
[PASS] T5.has_get

T6: AccessTokenMaskFilter 4 种序列化形态全脱敏

[PASS] T6.JSON.no_plain: out='{"access_token": "********1234"}'
[PASS] T6.JSON.has_tail
[PASS] T6.Pyrepr.no_plain: out="{'access_token': '********1234'}"
[PASS] T6.Pyrepr.has_tail
[PASS] T6.Query.no_plain: out='GET /x?access_token=********1234&u=1'
[PASS] T6.Query.has_tail
[PASS] T6.Fallback.no_plain: out='access_token: ********1234'
[PASS] T6.Fallback.has_tail

T7: AccessTokenMaskFilter 不误伤 Authorization header / Bearer 字段

[PASS] T7.unmodified_Authorization h: out='Authorization header: bearer_user_token_xxxxxxx'
[PASS] T7.unmodified_Bearer raw_toke: out='Bearer raw_token_zzz'

T8: 端到端 admin PUT roundtrip → client GET 一致明文 + admin GET 脱敏

[PASS] T8.put_200: sc=200
[PASS] T8.admin_get_masked: admin GET should mask got='**********RT99'
[PASS] T8.admin_get_tail_RT99
[PASS] T8.client_get_plain: client GET should be plain got='rt_secret_RT99'
[PASS] T8.client_app_id

T9: 端到端 logger.info 真打印 → console 输出脱敏(防御性兜底真实生效)

[PASS] T9.logger_info_no_plain: out='defensive_test access_token=*****************DEFC'
[PASS] T9.logger_info_tail

T_FINAL: DB 探针态主动还原(给后续 phase 留稳定起点)

[PASS] T_FINAL.db_restored.app_id
[PASS] T_FINAL.db_restored.access_token

关键观察

  • 明文走客户端 / 脱敏走管理端T8 同时验证了 /api/credential-slot/(客户端)返回 'rt_secret_RT99' 明文,与 /api/v1/admin/credential-slot/(管理端)返回 '**********RT99' 末 4 位脱敏view 层差异化语义正确
  • Filter 兜底真实生效T9 端到端调 logger.info('access_token=defensive_secret_DEFC')console handler 实际输出 ***...DEFC17 个 * + 末 4 位 DEFC),证明 settings.LOGGING.handlers.console.filters 注册路径打通
  • Filter 4 种正则形态全部覆盖T6JSON / Python dict repr / URL query / 等号或冒号兜底,每种形态 mask 后保留末 4 位明文(1234
  • 不误伤其它敏感字段T7filter 只识别 access_token 字段名前缀锚点;Authorization header: bearer_user_token_xxxxxxx / Bearer raw_token_zzz 经过 filter 后字符级一致

偏差记录auto-fixed

详见 03-02-SUMMARY.md 的 "Deviations from Plan" 段。本阶段共 fixed 2 处:

  1. [Rule 1 - Bug] 4 个 regex 正则交叉吃掉末 4 位Pattern 4 兜底正则把 Pattern 3 已脱敏的 ********1234&u=1 当 value 整段二次 mask1234 吃成 &u=1)— Pattern 4 终止符 [^\s,;)\]\}"\']+ 增加 & / = 排除字符
  2. [Rule 1 - Bug] tuple 形态 args 误吃 %s 占位符filter 先扫 record.msgaccess_token=%s 中的 %s 当 value mask 成 **Formatter 阶段 'access_token=**' % ('abcdefgh1234',) 报 TypeError— 改为tuple args 形态先 record.getMessage() 拼成最终字符串再整体脱敏args 清空避免 Formatter 二次拼接

Phase: 03-client-and-log-mask Verification completed: 2026-05-08