feat: T-02 审计中间件——http_access 全量访问审计(auth 注入 request.state, 排障路径跳过, 写库失败降级) + 独立 request_id(X-Request-Id 白名单透传贯通, B7 复审 P3-4) + 422/404/405/500 统一错误体(500 由 trace 中间件兜底生成并回写 trace 头, B7 复审 P2-2) + input_guard_log 双写(deps 401/403 留痕, platform 网关跳过 ENUM 口径, 挂账⑧收口) + repo.insert_input_guard_log + tests/test_audit_middleware 12 例, 240 绿

This commit is contained in:
2026-09-07 02:32:03 +08:00
parent 36f476f450
commit 3cec034026
9 changed files with 446 additions and 25 deletions
+29
View File
@@ -8,10 +8,17 @@
from __future__ import annotations
import re
from contextvars import ContextVar, Token
from uuid import uuid4
# 透传外部 X-Trace-Id / X-Request-Id 的格式白名单(防响应头注入;不合规一律新生成)
_HEADER_ID_PATTERN = re.compile(r"^[A-Za-z0-9._-]{1,64}$")
_trace_id: ContextVar[str] = ContextVar("trace_id", default="")
# 独立请求级 ID(T-02 · B7 复审 P3-4):trace_id 贯通链路,request_id 标识单次
# HTTP 请求(幂等/重试对账,手册 §4.6),两者不再互用。
_request_id: ContextVar[str] = ContextVar("request_id", default="")
def new_trace(trace_id: str | None = None) -> str:
@@ -40,3 +47,25 @@ def ensure_trace() -> None:
"""无上下文时兜底归因(脚本/引擎入口),有值时保留(中间件场景不重新 set)。"""
if not current_trace():
new_trace()
def new_request_id() -> str:
"""生成并绑定 request_id(中间件入口每请求一次)。"""
rid = f"req-{uuid4().hex[:16]}"
_request_id.set(rid)
return rid
def bind_request_id(request_id: str | None) -> tuple[str, Token]:
"""绑定请求 request_id(合法透传否则生成);返回 (id, token) 供中间件复位。"""
rid = request_id if _HEADER_ID_PATTERN.fullmatch(request_id or "") else f"req-{uuid4().hex[:16]}"
return rid, _request_id.set(rid)
def reset_request_id(token: Token) -> None:
_request_id.reset(token)
def current_request_id() -> str:
"""读取当前请求 request_id;未初始化返回空串(错误体兜底生成)。"""
return _request_id.get()