Commit Graph
3 Commits
Author SHA1 Message Date
glm-5.2 502488cc72 fix: Unit 1 — make publish() work end-to-end (P-01, P-02, P-05, P-08, P-09, P-12 #1)
Fixes the Pub operation's client→responder path so a publish() actually
works on any transport. Previously the wire was broken in three
compounding ways and the unit tests couldn't see it.

P-01 [critical] — publish chunks were written to a *fresh* open_bi
stream (stream B) while the responder read chunks from the stream that
carried call.requested (stream A). Stream B's frames were silently
discarded by the dispatch loop's "ignoring non-requested event" branch.
On single-stream transports (TCP+TLS, SSH) the second open_bi returns
StreamClosed outright, so every publish failed. Fix: pump call.requested
+ call.published + call.completed on the *same* write half via the new
pump_publish_to_wire free function; the read half is pumped concurrently
for the single call.responded.

P-02 [major] — publish() / publish_with_payload() now take
Pin<Box<dyn Stream<Item = Value> + Send>> per ADR-046 §8, not Vec<Value>.
The Vec shape buffered the entire publish in memory and made the ADR's
flagship use cases (telemetry ingest, live upload, drag-drop file
streaming) impossible. The wire format is unchanged; this corrects API
drift (no deployments exist).

P-05 [major] — publish now registers with timeout: None (like
subscribe), not DEFAULT_CALL_TIMEOUT (30s). A publish whose stream took
>30s wall-clock got a spurious client-side TIMEOUT while the responder
kept consuming. PendingEntry::Call.timeout is now Option<Instant> so the
sweeper never evicts unbounded calls; all register_call callers updated
(Some(...) for call(), None for publish()).

P-08 [major] — the dispatch Pub branch re-implemented invoke_sink's
not-found / visibility / ACL / handler-kind checks inline; invoke_sink
was only ever called from its own tests. Any future fix in invoke_sink
(e.g. the missing publish_schema validation, P-03) wouldn't reach the
wire path. Fix: extract OperationRegistry::resolve_sink_handler
(pub(crate)) as the single source of truth for the sink dispatch checks;
both invoke_sink and Dispatcher::dispatch (Pub branch) call it. The two
paths can no longer diverge.

P-09 [major, side-effect] — make_sink_forwarding_handler in from_call.rs
was store-and-forward (collect into Vec) and silently discarded Err
items (filter_map(|item| item.ok())), contradicting the SinkHandler
contract that an Err terminates the stream. Now that
publish_with_payload takes a Stream, the forwarding handler passes the
stream through directly (streamed, not buffered) and uses
take_while(Ok) + filter_map to terminate on Err. P-09 was listed in
Unit 6 but depends on P-01/P-02, so it falls out naturally here.

P-12 #1 [acceptance gate] — adds the end-to-end publish test that the
review identifies as the gate for this unit:
publish_end_to_end_delivers_chunks_and_returns_response wires
CallConnection::publish ↔ Dispatcher::run_loop over a real
tokio::io::duplex pair (new duplex_connection_pair test helper +
SingleStreamSource BidiStreamSource impl), publishes 3 chunks, and
asserts the responder saw all 3 and returned the right result. A second
test covers the unknown-op → NOT_FOUND path. These tests would have
caught P-01 immediately.

Verification:
- cargo test --lib         → 434 passed, 0 failed (was 432; +2 e2e tests)
- cargo clippy --all-targets -- -D warnings → clean
- cargo fmt --check        → clean
- cargo doc --no-deps      → 4 warnings (pre-existing C-09, unchanged)
2026-08-12 13:29:58 +00:00
glm-5.2 1ceb9b785d docs: rename pass — update crate refs from alknet-* to alkcall
Update doc comments referencing the old alknet-* crate names and
spec paths to reflect the alkcall home. ALPN strings (alknet/call,
alknet/test) are wire-stable and unchanged. Sibling crate refs
(alknet-http, alknet-core historical context) kept as-is — those are
accurate references to crates that still exist or will be reworked
later.

Also fixes the pre-existing broken intra-doc link [`CallAdapter`] in
dispatch.rs (now [`super::adapter::CallAdapter`]) — the only doc
warning carried over from the extraction.

Verification:
- cargo test: 343 passed (0 failed)
- cargo clippy --all-targets -- -D warnings: clean
- cargo fmt --check: clean
- cargo doc --no-deps: clean (0 warnings, was 1)
2026-08-12 05:58:59 +00:00
glm-5.2 4bc7a19695 feat: extract alknet-call into alkcall, vendor core types
Phase 1 of the alknet-call + alknet-channels unification. The call crate
is extracted verbatim from /workspace/@alkdev/alknet/crates/alknet-call
and the needed alknet-core types are vendored into src/core/ — alkcall is
the home for these types going forward (no separate alkcore crate).

Vendored core types (src/core/):
- auth.rs: Identity, AuthToken, AuthContext, IdentityProvider
- ownership.rs: OwnershipProvider, OwnershipStore, InMemoryOwnershipStore,
  OwnershipError
- types.rs: ProtocolHandler, Connection, BiStream, BidiStreamSource,
  SendStream, RecvStream, HandlerError, StreamError, Capabilities, Secret,
  IdentityAlreadySet
- Stripped: quinn/iroh/rustls deps, Connection::from_quinn/from_iroh
  (the dial lives in the consumer per ADR-089), config/credentials/
  fingerprint/store modules, ConfigIdentityProvider/IdentityStore

Call crate (src/client, src/protocol, src/registry/):
- Copied verbatim from alknet-call; alknet_core::{auth,types,ownership}
  rebound to crate::core::{auth,types,ownership}
- ALPN strings unchanged (alknet/call — wire-stable per ADR-006)
- No behavioral changes

Verification:
- cargo test: 343 passed (0 failed)
- cargo clippy --all-targets -- -D warnings: clean
- cargo fmt --check: clean
- cargo doc --no-deps: 1 pre-existing broken intra-doc link
  (CallAdapter in dispatch.rs — Phase 2 cleanup)

Next: Phase 2 — channels greenfield implementation + ALPN rename +
architecture doc porting.
2026-08-12 05:52:18 +00:00