feat: alkcall 0.7.0 adoption (CF-006 identity alignment) — bump to 0.4.0
- 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
This commit is contained in:
1 parent
bc4a9b6024
commit
67cf253621
4 files changed
+53
-25
No files matched your search
@@ -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
|
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
||||||
this crate adheres to [Semantic Versioning](https://semver.org/).
|
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
|
## [0.3.0] - 2026-09-07
|
||||||
|
|
||||||
The alkcall 0.6.0 adoption (review 007 R-01 — the `Establishment`
|
The alkcall 0.6.0 adoption (review 007 R-01 — the `Establishment`
|
||||||
|
|||||||
Generated
+3
-3
@@ -27,9 +27,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkcall"
|
name = "alkcall"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a44500900b82904d2a870e444051fc041a042e42ff7190803bbc5b3973f4feeb"
|
checksum = "5162a10144df65b03b887e30f77eb30d956ca1ca460a3f81b409128cbcae3199"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -48,7 +48,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alktty"
|
name = "alktty"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alkcall",
|
"alkcall",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "alktty"
|
name = "alktty"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@@ -25,7 +25,7 @@ default = []
|
|||||||
local = ["dep:portable-pty", "dep:tokio-util", "tokio/process", "tokio/rt-multi-thread"]
|
local = ["dep:portable-pty", "dep:tokio-util", "tokio/process", "tokio/rt-multi-thread"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
alkcall = "0.6.0"
|
alkcall = "0.7.0"
|
||||||
# Minimal, wasm-clean tokio features. `local` adds `process` +
|
# Minimal, wasm-clean tokio features. `local` adds `process` +
|
||||||
# `rt-multi-thread` (non-wasm). Do NOT use `features = ["full"]` — it
|
# `rt-multi-thread` (non-wasm). Do NOT use `features = ["full"]` — it
|
||||||
# pulls in `signal`/`fs`/`net` which break `wasm32-unknown-unknown`.
|
# pulls in `signal`/`fs`/`net` which break `wasm32-unknown-unknown`.
|
||||||
|
|||||||
+19
-20
@@ -98,10 +98,12 @@ pub const TTY_ALPN: &str = "alk/tty";
|
|||||||
/// the entry point (here by the registry's `AccessControl`), the
|
/// the entry point (here by the registry's `AccessControl`), the
|
||||||
/// ownership check is enforced once at the backend-selection point.
|
/// ownership check is enforced once at the backend-selection point.
|
||||||
///
|
///
|
||||||
/// `auth` is the peer's `AuthContext`, captured at
|
/// `auth` is the peer's `AuthContext`, the install-time context passed
|
||||||
/// `install_channel_zero` time and closed over by the wrapper so the
|
/// through to `register_openable_with_establisher`. The establisher
|
||||||
/// `TtyOpenHandler` receives it without the wrapper having to reach
|
/// and pump handler read their identity from the per-call context
|
||||||
/// into `OperationContext` for it (per the ADR-047 §4 amendment).
|
/// alkcall derives (alkcall 0.7, CF-006 corollary) — the
|
||||||
|
/// dispatch-resolved opener, the same view the registry's ACL gate
|
||||||
|
/// checked.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
@@ -117,8 +119,8 @@ pub fn register_openable(
|
|||||||
auth: AuthContext,
|
auth: AuthContext,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let spec = tty_open_spec();
|
let spec = tty_open_spec();
|
||||||
let establisher = make_tty_establisher(Arc::clone(&backends), ownership, auth.identity.clone());
|
let establisher = make_tty_establisher(Arc::clone(&backends), ownership);
|
||||||
let open_handler = make_tty_open_handler(backends, auth.identity.clone());
|
let open_handler = make_tty_open_handler(backends);
|
||||||
core.register_openable_with_establisher(
|
core.register_openable_with_establisher(
|
||||||
spec,
|
spec,
|
||||||
Some(establisher),
|
Some(establisher),
|
||||||
@@ -239,11 +241,12 @@ pub fn tty_open_spec() -> OperationSpec {
|
|||||||
/// returned.
|
/// returned.
|
||||||
///
|
///
|
||||||
/// The `tty:open` scope gate is NOT checked here — the registry's
|
/// The `tty:open` scope gate is NOT checked here — the registry's
|
||||||
/// `AccessControl` enforced it before the establisher ran (the
|
/// `AccessControl` enforced it before the establisher ran. The
|
||||||
/// identity view the registry checked, resolved from the connection,
|
/// establisher's `auth` is the per-call context (alkcall 0.7, CF-006
|
||||||
/// is the authoritative one; the establisher-side identity is only
|
/// corollary): its identity is the dispatch-resolved opener — the same
|
||||||
/// the ownership-check subject — the same split as the old
|
/// identity view the registry's ACL gate checked — and is the
|
||||||
/// handler-side check).
|
/// ownership-check subject (the same split as the old handler-side
|
||||||
|
/// check).
|
||||||
///
|
///
|
||||||
/// Mapping into the ADR-049 reason vocabulary (no new codes — the
|
/// Mapping into the ADR-049 reason vocabulary (no new codes — the
|
||||||
/// vocabulary is alkcall's one-way wire surface):
|
/// vocabulary is alkcall's one-way wire surface):
|
||||||
@@ -275,12 +278,11 @@ pub fn tty_open_spec() -> OperationSpec {
|
|||||||
fn make_tty_establisher(
|
fn make_tty_establisher(
|
||||||
backends: Arc<HashMap<String, Arc<dyn TtyBackend>>>,
|
backends: Arc<HashMap<String, Arc<dyn TtyBackend>>>,
|
||||||
ownership: Option<Arc<dyn OwnershipProvider>>,
|
ownership: Option<Arc<dyn OwnershipProvider>>,
|
||||||
identity: Option<alkcall::core::auth::Identity>,
|
|
||||||
) -> OpenEstablisher {
|
) -> OpenEstablisher {
|
||||||
Arc::new(move |input: Value, auth: AuthContext| {
|
Arc::new(move |input: Value, auth: AuthContext| {
|
||||||
let backends = Arc::clone(&backends);
|
let backends = Arc::clone(&backends);
|
||||||
let ownership = ownership.clone();
|
let ownership = ownership.clone();
|
||||||
let identity = identity.clone().or_else(|| auth.identity.clone());
|
let identity = auth.identity.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let req: NegotiateRequest = match serde_json::from_value(input) {
|
let req: NegotiateRequest = match serde_json::from_value(input) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
@@ -388,17 +390,14 @@ impl AllocatedHandle {
|
|||||||
///
|
///
|
||||||
/// The `tty:open` scope gate is enforced by the registry's `AccessControl`
|
/// The `tty:open` scope gate is enforced by the registry's `AccessControl`
|
||||||
/// before this handler runs — the handler does not re-check it.
|
/// before this handler runs — the handler does not re-check it.
|
||||||
fn make_tty_open_handler(
|
fn make_tty_open_handler(backends: Arc<HashMap<String, Arc<dyn TtyBackend>>>) -> OpenHandler {
|
||||||
backends: Arc<HashMap<String, Arc<dyn TtyBackend>>>,
|
|
||||||
identity: Option<alkcall::core::auth::Identity>,
|
|
||||||
) -> OpenHandler {
|
|
||||||
Arc::new(
|
Arc::new(
|
||||||
move |input: Value,
|
move |input: Value,
|
||||||
plan: Option<ChannelPlan>,
|
plan: Option<ChannelPlan>,
|
||||||
channel_conn: Connection,
|
channel_conn: Connection,
|
||||||
auth: AuthContext| {
|
auth: AuthContext| {
|
||||||
let backends = Arc::clone(&backends);
|
let backends = Arc::clone(&backends);
|
||||||
let identity = identity.clone().or_else(|| auth.identity.clone());
|
let identity = auth.identity.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let req: NegotiateRequest = match serde_json::from_value(input) {
|
let req: NegotiateRequest = match serde_json::from_value(input) {
|
||||||
@@ -523,7 +522,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut backends: HashMap<String, Arc<dyn TtyBackend>> = HashMap::new();
|
let mut backends: HashMap<String, Arc<dyn TtyBackend>> = HashMap::new();
|
||||||
backends.insert("mock".to_string(), Arc::new(MockBackend::with_exit_code(0)));
|
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(
|
let task = handler(
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
@@ -577,7 +576,7 @@ mod tests {
|
|||||||
ownership: Option<Arc<dyn OwnershipProvider>>,
|
ownership: Option<Arc<dyn OwnershipProvider>>,
|
||||||
input: Value,
|
input: Value,
|
||||||
) -> Result<Establishment, EstablishmentError> {
|
) -> Result<Establishment, EstablishmentError> {
|
||||||
let establisher = make_tty_establisher(backends, ownership, None);
|
let establisher = make_tty_establisher(backends, ownership);
|
||||||
establisher(input, AuthContext::anonymous(b"test")).await
|
establisher(input, AuthContext::anonymous(b"test")).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user