envelope.py python
50 lines 1.6 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 4 days ago
1 """JSON response envelope for ``api/*`` routes (§Q0.10.2)."""
2
3 from __future__ import annotations
4
5 import json
6 from dataclasses import dataclass
7 from typing import Any
8
9
10 @dataclass(frozen=True)
11 class ApiEnvelope:
12 """Standard API response wrapper."""
13
14 ok: bool
15 exit_code: int | None
16 error: str | None
17 result: Any
18 http_status: int = 200
19
20 def to_dict(self) -> dict[str, Any]:
21 payload: dict[str, Any] = {
22 "ok": self.ok,
23 "exit_code": self.exit_code,
24 "error": self.error,
25 "result": self.result,
26 }
27 return payload
28
29 def to_json_bytes(self) -> bytes:
30 return json.dumps(self.to_dict(), indent=2, sort_keys=True).encode("utf-8")
31
32
33 def auth_refusal(*, http_status: int, error: str) -> ApiEnvelope:
34 """Build an adapter refusal envelope without a CLI exit code."""
35 return ApiEnvelope(ok=False, exit_code=None, error=error, result=None, http_status=http_status)
36
37
38 def engine_success(result: Any, *, exit_code: int = 0) -> ApiEnvelope:
39 """Build a successful engine response."""
40 return ApiEnvelope(ok=exit_code == 0, exit_code=exit_code, error=None, result=result, http_status=200)
41
42
43 def engine_failure(*, exit_code: int, error: str | None, result: Any = None) -> ApiEnvelope:
44 """Build a failed engine response with CLI parity exit code."""
45 return ApiEnvelope(ok=False, exit_code=exit_code, error=error, result=result, http_status=200)
46
47
48 def bad_request(error: str = "bad_request") -> ApiEnvelope:
49 """Reject malformed API input before invoking the engine."""
50 return ApiEnvelope(ok=False, exit_code=None, error=error, result=None, http_status=400)
File History 1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 4 days ago