f305f8c0a5
feat: implement channels protocol + ADR-047 (openable ALPNs are operations)
...
ADR-047: the unifying decision that dissolves into
per-ALPN ops (, ) with a
marker on . Each openable ALPN registers
its own ops with their own , ,
, and the marker. The field is replaced
by (Sub/Pub). The generic ops (channel/close,
channel/control, channel/resources/subscribe) stay, keyed by
channel_id. Resolves Gaps A-G from the research findings (Gap B broker
named out-of-scope for alkcall; Gap C relay wrapper is consumer
concern; Gap D connection-owner allocates; Gap E extension trait;
Gap F boolean marker on wire; Gap G ACL/ownership complementary).
ADR-037 amended: dissolves; removed; generic
ops stay; preview dropped from resources/subscribe.
Spec docs updated: channel-operations.md (unified model, opener ledger,
ACL flow), operation-registry.md (channel_open marker, ChannelOpenSpec),
README.md (ADR-047), open-questions.md (OQ-31..38 resolved).
Source changes:
- spec.rs: ChannelOpenSpec struct, channel_open field on OperationSpec,
with_channel_open builder, 3 tests
- discovery.rs: spec_to_json emits channel_open boolean,
operation_spec_schema includes channel_open, 2 tests
- from_call.rs: rebuild_spec_for parses channel_open marker,
derive_alpn_from_op_name helper, 6 tests
Channels module (src/channels/, 10 files, ~2400 lines):
- wire.rs: 8-byte chunk header (ChunkHeader, parse/write_header,
read_header/write_chunk/write_eof async helpers), 12 tests
- reassembly.rs: MpscRecvStream (tokio::mpsc::Receiver<Bytes> →
AsyncRead), MpscSendStream (AsyncWrite → tokio::mpsc::Sender<Bytes>),
REQ-CH-01 shutdown sentinel, REQ-CH-02 sender-drop EOF, 10 tests
- mux.rs: MuxHandle (clone-able, register(channel_id)),
MuxRunner (per-channel pump tasks, exits when handles drop),
OpenerLedger (ADR-047 §7), 4 tests
- manager.rs: ChannelManager (channel map, open_channel,
install_channel_zero, route_payload, teardown_channel, clear_all),
11 tests
- source.rs: ChannelBidiStreamSource (yield-once accept_bi),
channel_source helper, 4 tests
- adapter.rs: ChannelsAdapter (ProtocolHandler for alknet/channels,
demux loop, install_channel_zero hook), 1 test
- operations.rs: ChannelOperations (registers channel/close,
channel/control, channel/resources/subscribe), ChannelCore
(check_open/on_close wrappers), 4 tests
- policy.rs: ChannelLifecyclePolicy trait, NoCap, PerIdentityChannelPolicy
(default 256, per_identity_caps override), default_policy, 8 tests
- env.rs: ChannelOperationEnv extension trait (ADR-047 §4),
ChannelsSessionEnv impl, 2 tests
- client.rs: ChannelClient (from_connection, call_open_op,
take_call_connection), 1 test
Verification: 432 tests pass (66 new channels + 10 marker + 356
existing), clippy clean, fmt clean, cargo doc generates.
Cargo.toml: +bytes dependency.
2026-08-12 12:13:53 +00:00
ea66398c88
feat: add Pub operation type, HandlerKind::Sink, call.published wire event (ADR-046)
...
The call protocol had Subscription (server→client streaming) but lacked
the directional complement: client→server streaming, where the initiator
produces a stream and the responder's handler consumes it. This gap was
inherited from the @alkdev/pubsub EventEnvelope prior art, which has
subscribe but no wire-level publish.
ADR-046 adds the Pub primitive:
- OperationType::Pub (client→server streaming)
- OperationType::Subscription renamed to Sub (wire: "subscription" → "sub")
- SinkHandler type + HandlerKind::Sink variant
- PublishStream type alias (Stream<Item = Result<Value, CallError>>)
- OperationRegistry::invoke_sink() dispatch path
- call.published wire event (sixth event type, additive)
- OperationSpec.publish_schema (Option<Value>, validates per-chunk input)
- DispatchResult::Sink + SinkDispatch (handler future + chunk channel)
- Dispatcher::pump_sink (feeds call.published chunks from wire to handler)
- CallConnection::publish() / publish_with_payload() client methods
- from_call sink forwarding handler (make_sink_forwarding_handler)
- make_sink_handler() helper
Fan-out/broker (one producer, N consumers, topic matching) is deferred to
the channels session — the call protocol is point-to-point; the broker is
a routing concern that sits above it. The Pub primitive is the
load-bearing piece the broker will compose on.
- 23 new tests (366 total, up from 343)
- clippy clean, fmt clean
Verification:
cargo test — 366 passed
cargo clippy --all-targets -- -D warnings — clean
cargo fmt --check — clean
2026-08-12 08:06:46 +00:00
cc470a363a
docs: port architecture specs + 45 ADRs from alknet, renumbered
...
Port the call + channels architecture documentation from the alknet
mono-repo into docs/architecture/, renumbered as alkcall ADR-001..045.
Renumbering map (alknet -> alkcall):
Core: 001,002,004,006,007,011,065,070,092,014,050,091 -> 001-012
Call: 005,064,012,023,015,022,024,016,049,017,028,029,030,032,066,069,067,068 -> 013-030
Shared: 003,009,013 -> 031-033
Channels: 071,093,072,073,074,075,076,094,079,080,081,089 -> 034-045
3 superseded/reversed ADRs kept for historical trail:
- ADR-013 (irpc foundation, superseded by ADR-014)
- ADR-023 (peer-scoped filtering, superseded by ADR-024)
- ADR-077 (TTY inside channels, reversed by ADR-035 — not ported, TTY-only)
Ported docs (11 spec files + README + open-questions):
- call-README.md, call-protocol.md, operation-registry.md, client-and-adapters.md
- channels-README.md, channels-overview.md, channels-wire.md, channels-connection.md, channels-adapter.md, channel-operations.md, channel-client.md
- README.md (index with doc table, ADR table grouped by category, key principles)
- open-questions.md (lean — 30 OQs, renumbered OQ-01..030; includes new OQ-22 for the pub/sub gap)
Cross-reference rewriting:
- All ADR-NNN references rewritten single-pass (no chaining bug)
- Markdown link paths fixed
- Title lines aligned with filenames
- Non-ported ADR refs (052, 082, 086, etc.) left as-is with README note
The open-questions.md includes OQ-22 (new): the call protocol pub/sub
gap — subscribe exists but pub does not, needed for channels
channel/resources/subscribe fan-out. This is the next ADR to write
(alkcall ADR-046).
2026-08-12 07:06:57 +00:00
a779dd0d0d
docs: replace alkvault scaffold with alkcall project conventions
...
- AGENTS.md: full rewrite for the call+channels RPC crate (async/tokio,
vendored core types, alktype dep, producer/consumer framing, the two
stable wire formats, no-env-vars invariant, OperationEnv trait, abort
cascade, AccessControl peer auth, ADR index for both halves)
- implementation-specialist.md: replace vault crypto conventions (OsRng,
zeroize, AES-GCM) with 15 alkcall protocol conventions matching AGENTS.md
- docs/sdd_process.md: fix alkvault -> alkcall reference
Verification: no code changed (docs-only)
commit 0a031cd..HEAD
2026-08-12 05:47:59 +00:00