Files
Ekklesia/docs/architecture/decisions
ekklesiaandClaude Opus 5 3d6c85b0f8 fix: observe request timeout failures
The sanitized operational line promised for a header/request timeout was
never actually emitted. Driving a real slow-header and slow-body connection
through a real socket against the pinned Node 24 runtime shows the general
server 'timeout' event never fires for headersTimeout/requestTimeout — that
event belongs to server.setTimeout()'s idle-socket timer, which this server
never arms. Both surface as 'clientError' carrying
err.code === "ERR_HTTP_REQUEST_TIMEOUT".

bindServer now observes 'clientError'. Because registering any such listener
suppresses Node's own default response entirely, the handler reproduces that
default byte-for-byte — 408 for a timeout, 431 for a header overflow, 400
otherwise — writing it only when the socket is still writable and no response
has already begun, then destroying the socket exactly as Node would. Exactly
one fixed sanitized line is logged per event, never the caught error's own
message, which for a parse failure derives from attacker-controlled input.

Proof moves to the real transport boundary: raw-socket scenarios assert the
exact response bytes, exactly one status line, socket closure, handler
non-invocation, and exactly one sanitized log for a slow-header connection, a
slow-body connection, a malformed request line, and an oversized header block.
The prior unit test, which manually emitted 'timeout', is removed as
misleading.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-07-26 15:59:33 -05:00
..
2026-07-26 12:29:24 -05:00

Architecture decision records

ADRs capture durable choices that affect more than one package or phase.

  • Filenames use a four-digit sequence followed by a short kebab-case title.
  • Status is Proposed, Accepted, Superseded, or Rejected.
  • Accepted ADRs are immutable except for status and cross-reference corrections.
  • A changed decision receives a new ADR that links to and supersedes the old one.

Index