Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.

## Unreleased

- Renamed internal module `src/app/connection.rs` to
`src/app/inbound_handler.rs` and `src/server/connection.rs` to
`src/server/connection_spawner.rs` to clarify directionality and eliminate
naming ambiguity with the public `src/connection/` module. No public API
changes.
- Deprecated `SharedState::new` (since 0.2.0); construct via `inner.into()`
instead.
- Breaking: Marked `ServerError` as `#[non_exhaustive]`. Downstream consumers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ sequenceDiagram

#### Implementation decisions (2026-02-12)

- The inbound integration seam for this ADR is `src/app/connection.rs` and
- The inbound integration seam for this ADR is `src/app/inbound_handler.rs` and
`src/app/frame_handling/`, not `src/connection/`, because inbound decode and
dispatch already occur in the app-layer connection loop.
- Message-assembly parsing, length, and continuity violations are treated as
Expand Down
6 changes: 3 additions & 3 deletions docs/adr-004-pluggable-protocol-codecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ length-delimited implementation.

Wireframe currently hardcodes `tokio_util::codec::LengthDelimitedCodec` with a
4-byte big-endian length prefix in the connection pipeline (notably in
`src/app/connection.rs` and `src/app/frame_handling.rs`). This makes framing
inflexible and prevents protocols with alternative framing rules (such as
Hotline, MySQL, and Redis Serialization Protocol (RESP) from reusing
`src/app/inbound_handler.rs` and `src/app/frame_handling.rs`). This makes
framing inflexible and prevents protocols with alternative framing rules (such
as Hotline, MySQL, and Redis Serialization Protocol (RESP)) from reusing
Wireframe's routing, middleware, and serialization infrastructure.

A pluggable framing layer is required that can:
Expand Down
12 changes: 6 additions & 6 deletions docs/execplans/8-2-1-message-assembler-hook-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ Success is observable when:
## Surprises & Discoveries

- Observation: Streaming request primitives exist (`src/request/mod.rs` and
`src/extractor.rs`), but the inbound pipeline in `src/app/connection.rs` does
not yet invoke a message-assembly hook. This plan keeps integration scoped to
8.2.1/8.2.2 and documents the limitation in the user guide until 8.2.5.
Evidence: `WireframeApp::handle_frame` decodes to `Envelope` and dispatches
directly to handlers after fragmentation reassembly.
`src/extractor.rs`), but the inbound pipeline in `src/app/inbound_handler.rs`
does not yet invoke a message-assembly hook. This plan keeps integration
scoped to 8.2.1/8.2.2 and documents the limitation in the user guide until
8.2.5. Evidence: `WireframeApp::handle_frame` decodes to `Envelope` and
dispatches directly to handlers after fragmentation reassembly.

## Decision Log

Expand All @@ -76,7 +76,7 @@ Not started yet.
## Context and Orientation

Wireframe’s inbound path decodes frames into `Envelope` values inside
`src/app/connection.rs`, then optionally applies transport fragmentation
`src/app/inbound_handler.rs`, then optionally applies transport fragmentation
reassembly via `src/app/fragmentation_state.rs` and
`frame_handling::reassemble_if_needed`. Handlers receive buffered payloads
through `ServiceRequest` and `PacketParts` in `src/middleware.rs`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ completed payloads to handlers. Unit tests (`rstest`) and behavioural tests

- Risk: The term "connection actor inbound path" is ambiguous because
`src/connection/` is outbound-focused, while inbound routing lives in
`src/app/connection.rs`. Severity: medium Likelihood: high Mitigation:
Implement in `src/app/connection.rs` and record this naming clarification in
the design docs.
`src/app/inbound_handler.rs`. Severity: medium Likelihood: high Mitigation:
Implement in `src/app/inbound_handler.rs` and record this naming
clarification in the design docs.

- Risk: Message assembly error handling may diverge from existing inbound
decode-failure policy. Severity: high Likelihood: medium Mitigation: Route
Expand All @@ -85,7 +85,7 @@ completed payloads to handlers. Unit tests (`rstest`) and behavioural tests

- [x] (2026-02-12 00:00Z) Drafted ExecPlan for roadmap items 8.2.5 and 8.2.6.
- [x] Confirmed and documented the exact inbound integration seam in
`src/app/connection.rs` and `src/app/frame_handling/`.
`src/app/inbound_handler.rs` and `src/app/frame_handling/`.
- [x] Upgraded behavioural test dependencies to `rstest-bdd` v0.5.0 and
restored
green compilation.
Expand All @@ -104,14 +104,15 @@ completed payloads to handlers. Unit tests (`rstest`) and behavioural tests
## Surprises & discoveries

- Observation: `WireframeApp::with_message_assembler` is currently a stored
configuration only; inbound code in `src/app/connection.rs` does not yet call
the hook. Evidence: no `message_assembler` usage in inbound frame handling.
Impact: 8.2.5 requires runtime integration work, not only API exposure.
configuration only; inbound code in `src/app/inbound_handler.rs` does not yet
call the hook. Evidence: no `message_assembler` usage in inbound frame
handling. Impact: 8.2.5 requires runtime integration work, not only API
exposure.

- Observation: `src/connection/` is centred on outbound frame delivery and does
not own inbound decode/reassembly. Evidence: `src/connection/mod.rs` actor
loop handles push/response streams, while inbound decode happens in
`src/app/connection.rs`. Impact: roadmap wording must be interpreted as
`src/app/inbound_handler.rs`. Impact: roadmap wording must be interpreted as
inbound path in `WireframeApp` connection handling.

- Observation: the workspace currently pins `rstest-bdd = "0.4.0"` in
Expand All @@ -126,7 +127,7 @@ completed payloads to handlers. Unit tests (`rstest`) and behavioural tests

## Decision log

- Decision: Integrate message assembly in `src/app/connection.rs` using
- Decision: Integrate message assembly in `src/app/inbound_handler.rs` using
`frame_handling` helpers, immediately after `reassemble_if_needed` and before
handler lookup. Rationale: this is the existing inbound choke point and
preserves ADR 0002 layer ordering. Date/Author: 2026-02-12 / Codex.
Expand All @@ -147,7 +148,7 @@ completed payloads to handlers. Unit tests (`rstest`) and behavioural tests
Completed.

- Inbound runtime now applies message assembly after transport reassembly in
`src/app/connection.rs` via `src/app/frame_handling/assembly.rs`.
`src/app/inbound_handler.rs` via `src/app/frame_handling/assembly.rs`.
- Failure handling is unified with the existing deserialization-failure policy
for parse, continuity, and declared-length errors.
- Unit coverage includes interleaving, ordering violations, and timeout purge
Expand All @@ -164,7 +165,7 @@ Completed.

## Context and orientation

The inbound runtime pipeline in `src/app/connection.rs` is now:
The inbound runtime pipeline in `src/app/inbound_handler.rs` is now:

- `decode_envelope` converts codec frames into `Envelope` values.
- `frame_handling::reassemble_if_needed` applies transport-level fragment
Expand Down Expand Up @@ -207,7 +208,7 @@ or a completed envelope for dispatch. Keep this helper small and explicitly
route failures through existing deserialization failure accounting.

Stage C integrates the helper into connection processing. Extend connection
state in `src/app/connection.rs` to hold optional message assembly runtime
state in `src/app/inbound_handler.rs` to hold optional message assembly runtime
state, invoke the new helper after transport reassembly, and purge expired
assemblies on idle read timeouts alongside existing fragmentation purging.
Go/no-go: if composition order or failure policy differs from ADR 0002, stop
Expand Down Expand Up @@ -249,7 +250,7 @@ mark roadmap entries 8.2.5 and 8.2.6 as done only after all gates pass.

3. Wire runtime state in connection handling.

- Update `src/app/connection.rs` to:
- Update `src/app/inbound_handler.rs` to:
- hold optional inbound message assembly state per connection;
- call assembly helper after `reassemble_if_needed` and before route
lookup;
Expand All @@ -259,7 +260,7 @@ mark roadmap entries 8.2.5 and 8.2.6 as done only after all gates pass.
4. Add or extend unit tests with `rstest`.

- Add targeted tests in `src/app/frame_handling/tests.rs` and/or
`src/app/connection/tests.rs`:
`src/app/inbound_handler/tests.rs`:
- interleaved keyed assembly dispatches only completed messages;
- out-of-order continuation is rejected and does not dispatch;
- timeout purge evicts stale partial state and later continuation fails as
Expand Down Expand Up @@ -342,7 +343,7 @@ specific files introduced by this feature branch.

Expected deliverables:

- inbound message assembly integration in `src/app/connection.rs` and
- inbound message assembly integration in `src/app/inbound_handler.rs` and
`src/app/frame_handling/`;
- `rstest` unit tests for inbound interleaving, ordering violation, timeout;
- `rstest-bdd` v0.5.0 behavioural scenarios for the same behaviours;
Expand Down
12 changes: 6 additions & 6 deletions docs/execplans/9-1-1-instance-aware-payload-wrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ The codec abstraction lives in `src/codec.rs` with the `FrameCodec` trait and
`LengthDelimitedFrameCodec` default. The outbound send path uses
`FrameCodec::wrap_payload` in two places:

- `src/app/connection.rs` in `WireframeApp::send_response` and
- `src/app/inbound_handler.rs` in `WireframeApp::send_response` and
`WireframeApp::send_response_framed_with_codec`.
- `src/app/frame_handling.rs` in `send_response_payload`, which feeds the
`Framed` stream used by `handle_connection_result`.

Inbound decoding uses `FrameCodec::frame_payload` in
`WireframeApp::decode_envelope` (`src/app/connection.rs`). Connection framing
uses `CombinedCodec` in `src/app/combined_codec.rs` to pair a codec decoder and
encoder into a `Framed` stream.
`WireframeApp::decode_envelope` (`src/app/inbound_handler.rs`). Connection
framing uses `CombinedCodec` in `src/app/combined_codec.rs` to pair a codec
decoder and encoder into a `Framed` stream.

Tests and examples that implement `FrameCodec` live in:

Expand Down Expand Up @@ -113,7 +113,7 @@ roadmap item 9.1.1 as done, then run the required Makefile gates.
## Concrete Steps

1. Inspect the existing trait and send paths to catalogue `wrap_payload` usage:
`src/codec.rs`, `src/app/connection.rs`, `src/app/frame_handling.rs`,
`src/codec.rs`, `src/app/inbound_handler.rs`, `src/app/frame_handling.rs`,
`tests/frame_codec.rs`, `tests/example_codecs.rs`, and the codec examples.

2. Update the trait signature in `src/codec.rs`:
Expand All @@ -131,7 +131,7 @@ roadmap item 9.1.1 as done, then run the required Makefile gates.
- Extend `ResponseContext` (and any related context structs) to carry a
`&F` so `send_response_payload` can use the per-connection codec
instance.
- In `WireframeApp::process_stream` (`src/app/connection.rs`), create a
- In `WireframeApp::process_stream` (`src/app/inbound_handler.rs`), create a
per-connection codec value (for example
`let mut codec = self.codec.clone();`)
and use it both to build the `CombinedCodec` and to populate the response
Expand Down
10 changes: 5 additions & 5 deletions docs/execplans/9-1-2-introduce-a-codec-error-taxonomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ integration, and behavioural tests.
- [x] (2026-01-07) Update `LengthDelimitedDecoder` to produce structured EOF
errors.
- [ ] Integrate `CodecErrorContext` population in connection processing.
- [ ] Add recovery policy evaluation in `src/app/connection.rs`.
- [ ] Add recovery policy evaluation in `src/app/inbound_handler.rs`.
- [ ] Add structured logging with codec error fields.
- [ ] Add `on_eof` hook to `ProtocolHooks`.
- [x] (2026-01-07) Add codec error metrics.
Expand Down Expand Up @@ -102,7 +102,7 @@ Codec implementation:

Error handling paths:

- `src/app/connection.rs` - Connection processing and error handling
- `src/app/inbound_handler.rs` - Connection processing and error handling
- `src/app/frame_handling.rs` - Frame deserialization and response forwarding
- `src/hooks.rs` - Protocol hooks including error callbacks

Expand Down Expand Up @@ -182,7 +182,7 @@ Update `LengthDelimitedDecoder` to produce structured EOF errors:
Integrate the error taxonomy into connection processing:

1. Populate `CodecErrorContext` from connection state in
`src/app/connection.rs`
`src/app/inbound_handler.rs`
2. Evaluate recovery policies when codec errors occur
3. Apply recovery actions (drop frame, quarantine, disconnect)
4. Track consecutive drop count and escalate to disconnect if exceeded
Expand Down Expand Up @@ -286,7 +286,7 @@ Update documentation:
- Return appropriate `CodecError::Eof` variant
- Convert to `io::Error` for trait compatibility

7. Update `src/app/connection.rs`:
7. Update `src/app/inbound_handler.rs`:
- Add `CodecErrorContext` population from connection state
- Add recovery policy evaluation on decode errors
- Track consecutive drop count
Expand Down Expand Up @@ -438,7 +438,7 @@ Record key evidence here once available:
| `src/codec.rs` | Modify: Re-export error types |
| `src/app/error.rs` | Modify: Add Codec variant |
| `src/response.rs` | Modify: Add Codec variant |
| `src/app/connection.rs` | Modify: Integrate error handling |
| `src/app/inbound_handler.rs` | Modify: Integrate error handling |
| `src/hooks.rs` | Modify: Add on_eof hook |
| `src/metrics.rs` | Modify: Add codec error metrics |
| `src/lib.rs` | Modify: Re-export types |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ The `HotlineFrameCodec::wrap_payload()` method copies:

### Primary Usage Site

The connection handling code in `src/app/connection.rs` calls
The connection handling code in `src/app/inbound_handler.rs` calls
`F::frame_payload(frame)` to extract payload bytes for envelope parsing. This
works with `&[u8]` and would also work with `Bytes` via `as_ref()`.

Expand Down
6 changes: 3 additions & 3 deletions docs/execplans/9-1-3-fragment-adapter-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ Current app integration points are:

- `src/app/builder/core.rs` and `src/app/builder/codec.rs`, where
`default_fragmentation(...)` currently auto-enables fragmentation.
- `src/app/connection.rs`, which instantiates optional fragmentation state and
calls purge on read-timeout ticks.
- `src/app/inbound_handler.rs`, which instantiates optional fragmentation state
and calls purge on read-timeout ticks.
- `src/app/frame_handling/response.rs` and
`src/app/frame_handling/reassembly.rs`, which apply fragmentation and
reassembly around handler processing.
Expand Down Expand Up @@ -278,7 +278,7 @@ Go/no-go:
2. Refactor connection-facing adapter implementation:
`src/app/fragmentation_state.rs`, `src/app/frame_handling/core.rs`,
`src/app/frame_handling/reassembly.rs`,
`src/app/frame_handling/response.rs`, `src/app/connection.rs`.
`src/app/frame_handling/response.rs`, `src/app/inbound_handler.rs`.

3. Enforce opt-in builder behaviour:
`src/app/builder_defaults.rs`, `src/app/builder/core.rs`,
Expand Down
21 changes: 11 additions & 10 deletions docs/execplans/9-3-1-fragment-adapter-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ After this work:

- App-level request and response handling is routed through the actor codec
path so protocol hooks apply consistently.
- Duplicate codec construction in `src/app/connection.rs` is removed; the
- Duplicate codec construction in `src/app/inbound_handler.rs` is removed; the
actor path owns framing.
- Integration tests cover streaming responses and push traffic through the
unified path.
Expand Down Expand Up @@ -284,7 +284,7 @@ crate under `wireframe_testing/`.

Two outbound frame-processing paths exist today:

**Path 1 — App router** (`src/app/connection.rs`,
**Path 1 — App router** (`src/app/inbound_handler.rs`,
`src/app/frame_handling/response.rs`):

- `WireframeApp::process_stream()` creates a `Framed<W, ConnectionCodec<F>>`
Expand Down Expand Up @@ -315,15 +315,16 @@ Two outbound frame-processing paths exist today:
- Used by standalone tests, client code, and custom protocol harnesses.
**Not used by the server runtime.**

**Server runtime** (`src/server/connection.rs`, `src/server/runtime/accept.rs`):
**Server runtime** (`src/server/connection_spawner.rs`,
`src/server/runtime/accept.rs`):

- `spawn_connection_task()` spawns a Tokio task per TCP connection.
- The task calls `app.handle_connection_result(stream)`, which enters
path 1 directly. No `ConnectionActor` is created.

### Key files

- `src/app/connection.rs` — app router's `process_stream()` and
- `src/app/inbound_handler.rs` — app router's `process_stream()` and
`handle_frame()`.
- `src/app/frame_handling/response.rs` — `forward_response()`,
`fragment_responses()`, `send_response_payload()`.
Expand All @@ -338,7 +339,7 @@ Two outbound frame-processing paths exist today:
- `src/hooks.rs` — `WireframeProtocol` trait and `ProtocolHooks` struct.
- `src/response.rs` — `Response` enum, `FrameStream`, `WireframeError`.
- `src/codec.rs` — `FrameCodec` trait and `LengthDelimitedFrameCodec`.
- `src/server/connection.rs` — `spawn_connection_task()`.
- `src/server/connection_spawner.rs` — `spawn_connection_task()`.
- `src/app/builder/core.rs` — `WireframeApp` builder.
- `src/app/builder/codec.rs` — codec configuration methods.
- `src/app/builder/protocol.rs` — `with_protocol()` method.
Expand Down Expand Up @@ -560,7 +561,7 @@ All commands must exit 0. If Mermaid diagrams are edited, also run:

### Inbound/outbound split

In `src/app/connection.rs`, the current `process_stream()` method (lines
In `src/app/inbound_handler.rs`, the current `process_stream()` method (lines
235-284) performs both decode and response send in a single loop. The unified
design splits this:

Expand Down Expand Up @@ -612,7 +613,7 @@ Acceptance is complete when all of the following are true:
`process_frame_with_hooks_and_metrics()` before reaching the wire.
- `WireframeProtocol::before_send` fires for every outbound frame on
server connections.
- Duplicate codec construction in `src/app/connection.rs` is removed.
- Duplicate codec construction in `src/app/inbound_handler.rs` is removed.
- Integration tests exercise streaming responses, push traffic,
multi-packet channels, and back-pressure through the unified path.
- BDD scenarios covering hook consistency, streaming, push interleaving,
Expand Down Expand Up @@ -695,14 +696,14 @@ Sketch of the driver's public surface:

### Modified files (expected)

- `src/app/connection.rs` — refactor `process_stream()` to use
- `src/app/inbound_handler.rs` — refactor `process_stream()` to use
`CodecDriver`.
- `src/app/frame_handling/response.rs` — simplify `forward_response()` to
produce response values rather than writing directly.
- `src/app/frame_handling/core.rs` — remove or simplify `ResponseContext`.
- `src/app/combined_codec.rs` — no changes expected; driver reuses it.
- `src/server/connection.rs` — may need minor adjustment if the connection
task setup changes.
- `src/server/connection_spawner.rs` — may need minor adjustment if the
connection task setup changes.
- `src/app/builder/protocol.rs` — wire `ProtocolHooks` into the connection
driver.
- `docs/asynchronous-outbound-messaging-design.md`
Expand Down
Loading
Loading