test(review 009): all seven coverage findings; errata on three as-filed claims

Review 009's coverage debt in full — the paths the review-008 gates
never walk. No wire or API changes.

- C-1: pin the plain-bundle install-failure arm (un-compilable
  input_schema; the as-filed duplicate-name route does not fail
  registration) — the install task ends before the dispatch loop,
  channel 0 never dispatches. ADR-051 §5 gains the loud-install
  coverage note: relay-openable + plain-bundle arms pinned,
  generic-ops + bootstrap-discovery arms documented as
  best-effort-loud (crate-internal specs compile by construction).
- C-2: the HubLegImports filter — filtered closure path + only
  partition unit-tested (errata: only was already pinned at filing);
  the empty-stash e2e gate (generic ops + discovery only, dropped
  ops resolve NOT_FOUND).
- C-3: the batch-form reserved-reply-key rejection pinned (reason
  handler_error, teardown, ledger decrement, no pump spawn).
- C-4: open_channel_with_reply's failure path pinned e2e (the typed
  error carries the channel:open_failed code + details reason/message).
- C-5: both byte-identical claims golden-pinned — the no-fields reply
  against {"channel_id": 2} and the standard-shape wire payload
  against the full 9-key literal.
- C-6: derivation edge shapes pinned — channels//sub, channels//direct,
  channels → None; the 4-segment strict superset annotated as the
  pre-amendment behavior change (errata: actual is Some("x/sub"), the
  multi-segment-ALPN rule, not the as-filed Some("alk/x/sub")).
- C-7: builder overwrite pinned last-win (single + batch) with the
  doc sentence on with_reply_field.

Verification: 682 tests pass, clippy -D warnings clean, fmt clean,
doc clean, wasm32 check clean.

File: docs/reviews/009 (resolved; errata marked per finding)
This commit is contained in:
glm-5.3-flash committed 2026-09-18 08:02:13 +00:00
1 parent 54c2a3f941
commit 9620ee7b2a
7 files changed
+594 -1

No files matched your search

+125
View File
@@ -1767,6 +1767,131 @@ mod tests {
assert!(channel_id2 > 0);
}
/// Review 009 C-4: the new pub API's failure path — a
/// `channel:open_failed` resolving through
/// `open_channel_with_reply` carries the full wire error shape
/// (`code` + typed `details` with `reason` and `message`), so the
/// caller can branch on the establishment reason through the new
/// API the same way `open_channel`'s shared parse path does.
#[tokio::test]
async fn open_channel_with_reply_resolves_typed_open_failed_end_to_end() {
use crate::channels::operations::{
ChannelCore, EstablishmentError, OpenEstablisher, OpenHandler,
};
use crate::channels::policy::NoCap;
use crate::registry::spec::ChannelOpenSpec;
let open_handler: OpenHandler =
Arc::new(|_input, _plan, _channel_conn, _auth| tokio::spawn(async {}));
let establisher: OpenEstablisher = Arc::new(|_input, _auth| {
Box::pin(async {
Err(EstablishmentError::DialFailed {
message: "target refused the connection".to_string(),
})
})
});
let establisher_for_hook = Arc::clone(&establisher);
let open_handler_for_hook = Arc::clone(&open_handler);
let install_hook: crate::channels::adapter::InstallChannelZero =
Arc::new(move |manager, channel0_conn, auth| {
let establisher = Arc::clone(&establisher_for_hook);
let open_handler = Arc::clone(&open_handler_for_hook);
tokio::spawn(async move {
let channel0_bidi = match channel0_conn.accept_bi().await {
Ok(s) => s,
Err(_) => return,
};
let (writer, reader) = split_single_stream(channel0_bidi);
let core = ChannelCore::new(manager, Arc::new(NoCap));
let registry = crate::registry::registration::OperationRegistry::new();
let spec = OperationSpec::new(
"channels/tty/sub",
OperationType::Sub,
Visibility::External,
serde_json::json!({}),
serde_json::json!({
"type": "object",
"properties": { "channel_id": { "type": "integer" } }
}),
vec![],
AccessControl::default(),
None,
)
.with_channel_open(ChannelOpenSpec::new("alk/tty"));
core.register_openable_with_establisher(
spec,
Some(establisher),
open_handler,
&registry,
auth.clone(),
None,
)
.expect("register_openable_with_establisher");
let registry = Arc::new(registry);
let provider: Arc<dyn IdentityProvider> = Arc::new(NoopIdProvider);
let call_connection = Arc::new(CallConnection::new_single_stream(
channel0_conn,
Arc::clone(&writer),
));
let dp = Dispatcher::new(registry, provider);
dp.run_loop_single_stream(call_connection, reader, writer)
.await;
})
});
let (client_end, server_end) = tokio::io::duplex(64 * 1024);
let client_conn =
Connection::from_bidi(client_end, b"alk/channels".to_vec(), Some(TEST_ADDR));
let server_conn =
Connection::from_bidi(server_end, b"alk/channels".to_vec(), Some(TEST_ADDR));
let adapter = ChannelsAdapter::new(install_hook, Arc::new(NoCap));
let auth = AuthContext::anonymous(b"alk/channels");
let _server_handle = tokio::spawn(async move {
let _ = crate::core::types::ProtocolHandler::handle(&adapter, server_conn, &auth).await;
});
let client = ChannelClient::from_connection(client_conn)
.await
.expect("channel client init");
let err = tokio::time::timeout(
std::time::Duration::from_secs(10),
client.open_channel_with_reply(
"channels/tty/sub",
serde_json::json!({ "container": "abc" }),
"alk/tty",
),
)
.await
.expect("open_channel_with_reply timed out");
let err = match err {
Err(e) => e,
Ok(_) => panic!("the establisher failure must resolve Err through the reply API"),
};
// The full reply shape is assertable by the caller: the wire
// code, the reason code, and the message inside `details`.
let call_error = err.call_error().expect("CallFailed carries the CallError");
assert_eq!(call_error.code, "channel:open_failed");
assert_eq!(err.establishment_reason(), Some("dial_failed"));
let details = call_error
.details
.as_ref()
.expect("details ride the typed error");
assert_eq!(details["reason"], serde_json::json!("dial_failed"));
assert_eq!(
details["message"],
serde_json::json!("target refused the connection"),
"the establishment-failure message survives the wire to the caller"
);
assert!(
client.manager().channel_ids().into_iter().all(|id| id == 0),
"no data channel exists for the failed open"
);
}
// --- review 004 Unit 3 acceptance gates (F-04 serving half) -----------
/// F-04 gate 1: hub→consumer call over an existing `ChannelClient`