From 67cf25362145a3b8f945f22e1e4b8b23e3fe3a45 Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Mon, 7 Sep 2026 17:57:36 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20alkcall=200.7.0=20adoption=20(CF-006=20?= =?UTF-8?q?identity=20alignment)=20=E2=80=94=20bump=20to=200.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BREAKING (ecosystem-coordination): alkcall bumped to 0.7.0. No type alktty touches changed shape (OpenEstablisher/OpenHandler/ Establishment/ChannelPlan identical to 0.6.0); the minor bump is for downstream lockstep, since alktty's public signatures reference alkcall types. - CF-006 alignment: the channels establisher and pump handler now take their identity from the per-call auth (alkcall 0.7 derives the dispatch-resolved opener — the same identity view the registry's ACL gate checked) instead of the captured install-time override. Behavior-identical in the per-connection-registry deployment; the ownership check and the ACL gate see the same subject in every deployment. make_tty_establisher / make_tty_open_handler drop their captured-identity parameter (both private). Verification: - cargo test: 113 passed (default), 156 passed (--all-features) - cargo clippy --all-targets -- -D warnings: clean - cargo fmt --check: clean - cargo doc --no-deps: clean - cargo check/clippy --target wasm32-unknown-unknown -D warnings: clean - cargo publish --dry-run --allow-dirty: clean --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- src/channels.rs | 39 +++++++++++++++++++-------------------- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d90dfe2..8a69f7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,35 @@ All notable changes to this crate are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this crate adheres to [Semantic Versioning](https://semver.org/). +## [0.4.0] - 2026-09-07 + +The alkcall 0.7.0 adoption (the connect-side caller-identity seam, +CF-005/006/007): a dependency bump plus one behavior-alignment change +on the channels path. The wire format, the direct-ALPN path, the +`TtyBackend` trait, and the public API surface are unchanged. + +### Changed + +- **BREAKING (ecosystem-coordination) — `alkcall` bumped to 0.7.0.** + alkcall 0.7.0 changed no type that alktty touches + (`OpenEstablisher`/`OpenHandler`/`Establishment`/`ChannelPlan` are + identical to 0.6.0; alktty never constructs `ServingConfig`), but + alktty's public signatures reference alkcall types, so downstream + crates must now unify on alkcall 0.7.0. Minor bump per the 0.x + ecosystem-coordination rule. +- **The channels establisher and pump handler take their identity + from the per-call `auth` (CF-006 alignment).** `register_openable` + no longer captures the install-time identity and overrides the + establisher/handler `auth.identity` with it — post-alkcall-0.7 the + per-call context already carries the dispatch-resolved opener (the + same identity view the registry's ACL gate checked; the end client, + not the hub, on hub-forwarded opens). Behavior-identical in the + per-connection-registry deployment (install-time identity was the + caller's); the ownership check and the ACL gate now see the same + subject in every deployment. Two factory parameters dropped + (`make_tty_establisher`/`make_tty_open_handler` are private; no + public-surface change). + ## [0.3.0] - 2026-09-07 The alkcall 0.6.0 adoption (review 007 R-01 — the `Establishment` diff --git a/Cargo.lock b/Cargo.lock index 63073d9..58dea29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,9 +27,9 @@ dependencies = [ [[package]] name = "alkcall" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44500900b82904d2a870e444051fc041a042e42ff7190803bbc5b3973f4feeb" +checksum = "5162a10144df65b03b887e30f77eb30d956ca1ca460a3f81b409128cbcae3199" dependencies = [ "async-trait", "bytes", @@ -48,7 +48,7 @@ dependencies = [ [[package]] name = "alktty" -version = "0.3.0" +version = "0.4.0" dependencies = [ "alkcall", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index fe968eb..2123178 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alktty" -version = "0.3.0" +version = "0.4.0" edition = "2021" rust-version = "1.85" license = "MIT OR Apache-2.0" @@ -25,7 +25,7 @@ default = [] local = ["dep:portable-pty", "dep:tokio-util", "tokio/process", "tokio/rt-multi-thread"] [dependencies] -alkcall = "0.6.0" +alkcall = "0.7.0" # Minimal, wasm-clean tokio features. `local` adds `process` + # `rt-multi-thread` (non-wasm). Do NOT use `features = ["full"]` — it # pulls in `signal`/`fs`/`net` which break `wasm32-unknown-unknown`. diff --git a/src/channels.rs b/src/channels.rs index 1a65d40..21dbbde 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -98,10 +98,12 @@ pub const TTY_ALPN: &str = "alk/tty"; /// the entry point (here by the registry's `AccessControl`), the /// ownership check is enforced once at the backend-selection point. /// -/// `auth` is the peer's `AuthContext`, captured at -/// `install_channel_zero` time and closed over by the wrapper so the -/// `TtyOpenHandler` receives it without the wrapper having to reach -/// into `OperationContext` for it (per the ADR-047 §4 amendment). +/// `auth` is the peer's `AuthContext`, the install-time context passed +/// through to `register_openable_with_establisher`. The establisher +/// and pump handler read their identity from the per-call context +/// alkcall derives (alkcall 0.7, CF-006 corollary) — the +/// dispatch-resolved opener, the same view the registry's ACL gate +/// checked. /// /// # Errors /// @@ -117,8 +119,8 @@ pub fn register_openable( auth: AuthContext, ) -> Result<(), String> { let spec = tty_open_spec(); - let establisher = make_tty_establisher(Arc::clone(&backends), ownership, auth.identity.clone()); - let open_handler = make_tty_open_handler(backends, auth.identity.clone()); + let establisher = make_tty_establisher(Arc::clone(&backends), ownership); + let open_handler = make_tty_open_handler(backends); core.register_openable_with_establisher( spec, Some(establisher), @@ -239,11 +241,12 @@ pub fn tty_open_spec() -> OperationSpec { /// returned. /// /// The `tty:open` scope gate is NOT checked here — the registry's -/// `AccessControl` enforced it before the establisher ran (the -/// identity view the registry checked, resolved from the connection, -/// is the authoritative one; the establisher-side identity is only -/// the ownership-check subject — the same split as the old -/// handler-side check). +/// `AccessControl` enforced it before the establisher ran. The +/// establisher's `auth` is the per-call context (alkcall 0.7, CF-006 +/// corollary): its identity is the dispatch-resolved opener — the same +/// identity view the registry's ACL gate checked — and is the +/// ownership-check subject (the same split as the old handler-side +/// check). /// /// Mapping into the ADR-049 reason vocabulary (no new codes — the /// vocabulary is alkcall's one-way wire surface): @@ -275,12 +278,11 @@ pub fn tty_open_spec() -> OperationSpec { fn make_tty_establisher( backends: Arc>>, ownership: Option>, - identity: Option, ) -> OpenEstablisher { Arc::new(move |input: Value, auth: AuthContext| { let backends = Arc::clone(&backends); let ownership = ownership.clone(); - let identity = identity.clone().or_else(|| auth.identity.clone()); + let identity = auth.identity.clone(); Box::pin(async move { let req: NegotiateRequest = match serde_json::from_value(input) { Ok(r) => r, @@ -388,17 +390,14 @@ impl AllocatedHandle { /// /// The `tty:open` scope gate is enforced by the registry's `AccessControl` /// before this handler runs — the handler does not re-check it. -fn make_tty_open_handler( - backends: Arc>>, - identity: Option, -) -> OpenHandler { +fn make_tty_open_handler(backends: Arc>>) -> OpenHandler { Arc::new( move |input: Value, plan: Option, channel_conn: Connection, auth: AuthContext| { let backends = Arc::clone(&backends); - let identity = identity.clone().or_else(|| auth.identity.clone()); + let identity = auth.identity.clone(); tokio::spawn(async move { let req: NegotiateRequest = match serde_json::from_value(input) { @@ -523,7 +522,7 @@ mod tests { let mut backends: HashMap> = HashMap::new(); backends.insert("mock".to_string(), Arc::new(MockBackend::with_exit_code(0))); - let handler = make_tty_open_handler(Arc::new(backends), None); + let handler = make_tty_open_handler(Arc::new(backends)); let task = handler( serde_json::json!({ @@ -577,7 +576,7 @@ mod tests { ownership: Option>, input: Value, ) -> Result { - let establisher = make_tty_establisher(backends, ownership, None); + let establisher = make_tty_establisher(backends, ownership); establisher(input, AuthContext::anonymous(b"test")).await }