Files
BlackVortexAIandClaude Fable 5.1 95ace90041 Add BV Text writing assistance, preparation caches and the 1.4.4 hardening
Features: BV Text node with management-gated writing assistance (translate,
improve, undo, prompt profiles); reuse of prepared MODEL/CLIP state for Krea 2
and Anima LLLite consumers; Regional refactoring.

Security boundaries: one wall-clock budget per Remote LLM request enforced by
a socket-closing watchdog across connect, TLS handshake, headers, chunk framing
and body; writing assistance uses the profile's configured timeout; a shared
bounded JSON reader with route-specific limits on every JSON route; endpoint
binding negative tests for the assist path.

Release and packaging: SECURITY.md; bundled-library notices and a readable
bundle header; Registry scan replica as a hard test with a pinned count; a
packaged-file-set test; publish only from a validated push to main with
provenance checks, pinned comfy-cli, an input manifest and a byte-exact
comparison of the stored archive; npm audit and a whole js/ rebuild gate in
Validate; design references, brand sources and a type declaration excluded
from the package. README and changelog for 1.4.4.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-13 16:51:38 +02:00

46 lines
1.6 KiB
Python

"""Bounded JSON request bodies for the pack's own HTTP routes.
ComfyUI applies one global upload limit to every route. The pack's routes carry
small JSON documents, so each one states its own cap and stops reading as soon as
the cap is exceeded. The body is streamed; the Content-Length header is never
trusted on its own.
"""
from __future__ import annotations
import json
from aiohttp import web
class RequestBodyError(Exception):
"""A request body that must be answered with a 4xx status before any work happens."""
def __init__(self, status: int, message: str) -> None:
super().__init__(message)
self.status = status
self.message = message
async def read_json_object(request, limit: int) -> dict:
"""Return the JSON object in the request body.
Reading stops as soon as more than ``limit`` bytes have arrived; at most one
extra 8 KiB chunk is consumed before the request is refused with 413.
"""
raw = bytearray()
async for chunk in request.content.iter_chunked(8192):
raw.extend(chunk)
if len(raw) > limit:
raise RequestBodyError(413, f"Request body exceeds {limit} bytes")
try:
value = json.loads(bytes(raw))
except (ValueError, TypeError, RecursionError):
raise RequestBodyError(400, "Request body is not valid JSON") from None
if not isinstance(value, dict):
raise RequestBodyError(400, "Request body must be a JSON object")
return value
def body_error_response(error: RequestBodyError) -> web.Response:
return web.json_response({"error": error.message}, status=error.status)