feat(ai): durcissement phase F (#79) - rate limit, redaction, OpenAPI/MCP, E2E

This commit is contained in:
2026-09-11 21:56:50 -04:00
parent 88eecd7671
commit 9dce341bc8
18 changed files with 854 additions and 27 deletions
+12 -1
View File
@@ -26,10 +26,13 @@ from backend.tools.context import (
ToolError,
ToolNotFoundError,
ToolPermissionError,
ToolRateLimitError,
ToolRisk,
ToolScope,
ToolValidationError,
)
from backend.tools.ratelimit import check_and_record
from backend.tools.redaction import redact_payload
from backend.tools.schemas import ToolResult
logger = logging.getLogger("obsigate.tools.registry")
@@ -186,6 +189,12 @@ def call_tool(
_audit(ctx, spec, arguments, ok=False, error=error.code)
raise error from e
allowed, retry_after = check_and_record(ctx.rate_limit_identity, spec.name)
if not allowed:
rate_error = ToolRateLimitError(spec.name, retry_after)
_audit(ctx, spec, arguments, ok=False, error=rate_error.code)
raise rate_error
vault = getattr(params, "vault", None)
if spec.requires_vault and vault:
try:
@@ -223,4 +232,6 @@ def call_tool(
duration_ms = round((time.perf_counter() - started) * 1000, 2)
logger.debug(f"Tool '{name}' ok in {duration_ms}ms")
_audit(ctx, spec, arguments, ok=True)
return ToolResult(ok=True, data=data)
# Never forward raw secrets to the model (defense in depth: some tools —
# diffs, search snippets — return content that was not pre-redacted).
return ToolResult(ok=True, data=redact_payload(data))