docs(arch): fix inbound worker hook — callback inside handle(), not post-hoc

- Replace on_worker_connected() post-hoc call with WorkerConnectedCallback
  that fires inside CallAdapter::handle(). handle() blocks until disconnect
  — there is no 'after handle accepts' point for the assembly layer to
  hook into. The callback carries both on_connected (from_call + attach_peer)
  and on_disconnected (detach_peer + drop channels).

- Add CallAdapter::with_worker_connected_callback(callback) builder method.

- Consolidate duplicate WorkerConnectedCallback struct definitions.

- Fix channel role: 'channel proxying' → 'channel management'. The hub
  tracks channels; it does not proxy streams. What the caller does with
  the resulting channel is the assembly layer's business.

- Resolve OQ-54: callback is the committed design. Update OQ file and
  open-questions.md table.
This commit is contained in:
deepseek-v4-pro committed 2026-07-11 07:46:00 +00:00
1 parent b38b1d28a7
commit 5d56bae1ba
3 files changed
+135 -89

No files matched your search

@@ -1,26 +1,21 @@
# OQ-54: Inbound Worker on_worker_connected Hook Placement
- **Origin**: [crates/hub/README.md](crates/hub/README.md)
- **Status**: open
- **Status**: resolved (2026-07-09)
- **Door type**: Two-way
- **Priority**: low
- **Resolution**: Not yet decided.
- **Resolution**: The hook is a **callback** (`WorkerConnectedCallback`) that
fires inside `CallAdapter::handle()` between identity resolution and
dispatch start. `handle()` blocks until disconnect — there is no "after
handle accepts" point for the assembly layer to hook into. The callback
carries both `on_connected` (runs `from_call`, registers bundles, attaches
peer to aggregated env) and `on_disconnected` (detaches peer, drops channel
tracking on `run_loop` exit). The callback is wired via
`CallAdapter::with_worker_connected_callback(callback)`.
When a worker connects inbound (via `CallAdapter::handle`), the hub needs to
call `from_call`, register the bundles, and `attach_peer`. Two options:
- **(a) Explicit**: The assembly layer calls `hub.on_worker_connected()` after
`CallAdapter::handle` accepts the connection. The hub provides the method;
the assembly layer wires it.
- **(b) Wrapper**: The hub provides a `HubCallAdapter` wrapper that calls the
hook automatically inside `handle()`. The assembly layer uses the wrapper
instead of the raw `CallAdapter`.
Option (a) is simpler and more flexible — the assembly layer controls when
the hook fires and can add its own logic (authorization checks, logging)
before discovery. Option (b) is more convenient but hides the hook from the
assembly layer.
The explicit approach is the committed interim. A wrapper is additive.
The earlier "explicit post-hoc call" design (option a) was based on the
incorrect assumption that `CallAdapter::handle` returns after accepting
the connection. It doesn't — it runs the dispatch loop internally and
returns only on disconnect. The callback approach is the correct design.
- **Cross-references**: ADR-067, ADR-068, [crates/hub/README.md](crates/hub/README.md)