producer: the explicit bind-policy gate + the builder-register pin (review-002 C-3, D-2, S-1, N-2)

- C-3: Socks5ProducerBuilder.bind_policy(bool) — the substrate-free
  entry's explicit BIND gate, defaulting to the accept seam's
  presence; seam presence is never the sole gate
- D-2: RegisterMode::ProducerBuilder + an integration test wiring the
  full builder through .register(...) serving all three commands
- S-1: run_datagram_stage's doc names the hot-Ok(None) residual
- N-2: wire.md §UDP ASSOCIATE carries the inline-send backpressure line

Verified: cargo test (352 green), clippy/fmt/doc clean, wasm checks clean.
This commit is contained in:
glm-5.3-flash committed 2026-09-24 18:04:55 +00:00
1 parent 53739b20cb
commit ff81f2d27b
5 files changed
+393 -17

No files matched your search

+46
View File
@@ -1011,3 +1011,49 @@ async fn readiness_contract_holds_under_concurrent_load() {
.await
.expect("fresh associate after the hot-egress load");
}
/// The spec'd assembly shape end to end (review 002 D-2): the full
/// `Socks5Producer::builder()` chain — `dial` + `egress` + `accept` —
/// through `.register(...)` (the builder's delegated registration, not
/// the free function), serving all three commands over the harness
/// topology. The one assembly path producer.md §Wiring documents is
/// the one this test pins: a signature drift or a delegation bug in
/// `register` can no longer pass the suite.
#[tokio::test]
async fn producer_builder_registers_and_serves_all_three_commands() {
let topo = wire_with(
RegisterMode::ProducerBuilder {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(echo_accept()),
bind_policy: None,
},
Some(both_scopes_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
// CONNECT over the builder's dial seam.
connect_round_trip(&topo, "builder.test".into(), "tcp".into())
.await
.expect("CONNECT serves through the builder registration");
// ASSOCIATE over the builder's egress seam.
associate_round_trip(&topo, 60, b"udp")
.await
.expect("ASSOCIATE serves through the builder registration");
// BIND over the builder's accept seam (reply#1 + reply#2 +
// pass-through — the full phase model).
bind_round_trip(&topo, "builder.test", b"bind")
.await
.expect("BIND serves through the builder registration");
// The registration is the spec'd one: the establisher rode it
// (the witness is the builder-delegated registration's probe).
assert_eq!(
topo.identity_witness.lock().await.as_deref(),
Some("consumer-both")
);
}
+42
View File
@@ -442,6 +442,17 @@ pub enum RegisterMode {
egress: Option<EgressFactory>,
accept: Option<BindAcceptFactory>,
},
/// The spec'd assembly shape (producer.md §Wiring): the
/// registration rides [`alksocks::producer::Socks5Producer::
/// builder`] + [`alksocks::producer::Socks5Producer::register`]
/// (the builder's `dial`/`egress`/`accept` setters and the
/// delegated registration — the surface D-2 guards).
ProducerBuilder {
dial: DialFn,
egress: Option<EgressFactory>,
accept: Option<BindAcceptFactory>,
bind_policy: Option<bool>,
},
/// No socks5 openable — only the generic channel ops (the
/// unknown-op / registry-gate probe's shape).
NoSocks5,
@@ -660,6 +671,37 @@ pub async fn wire_with(
)
.expect("register socks5 openable (the real producer)");
}
if let RegisterMode::ProducerBuilder {
dial,
egress,
accept,
bind_policy,
} = &mode
{
let core = ChannelCore::new(
producer_client.manager().clone(),
alkcall::channels::policy::default_policy(),
);
let mut producer = alksocks::producer::Socks5Producer::builder().dial(Arc::clone(dial));
if let Some(egress) = egress {
producer = producer.egress(egress.clone());
}
if let Some(accept) = accept {
producer = producer.accept(accept.clone());
}
if let Some(can_bind) = bind_policy {
producer = producer.bind_policy(*can_bind);
}
producer
.build()
.register(
&core,
&producer_op_registry,
AuthContext::anonymous(b"alk/socks5"),
Some(Arc::clone(&identity_witness)),
)
.expect("register socks5 openable (the spec'd builder shape)");
}
// --- consumer pieces (captured from the hook) -----------------------
let consumer_call = consumer_call_rx.recv().await.expect("consumer call conn");