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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user