A channel with only MinTotalUnderlays set (no per-type Constraints, no DialPolicy) does not behave as a multi-underlay channel today:
isMultiUnderlayCapable() ignores MinTotalUnderlays, so AcceptUnderlay rejects additional underlays.
applyConstraints() early-returns when len(constraints) == 0, and the total-count check (countsShowValidState) lives inside that path, so MinTotalUnderlays is never enforced on its own.
Net: MinTotalUnderlays is effectively a no-op unless per-type constraints are also set. That makes it impossible to express the simple, common listener intent "accept additional underlays of any type, and close only when the last one is lost" without adding Min: 0 per-type constraints purely to flip the capability bit.
This is the v4 SetMinTotal(1) behavior that listener-side channels (e.g. OpenZiti control channels) relied on. OpenZiti currently works around it with Min: 0 constraints plus MinTotalUnderlays: 1.
Proposal
Make MinTotalUnderlays first-class:
isMultiUnderlayCapable() returns true when minTotalUnderlays > 0.
applyConstraints() proceeds (rather than early-returning) when minTotalUnderlays > 0 even with no per-type constraints, so the total-count check runs and closes the channel below the minimum.
With this, a listener can pass just MinTotalUnderlays: 1 to get "multi-underlay-capable, closes when empty, never dials," and the OpenZiti workaround constraints can be dropped.
A channel with only
MinTotalUnderlaysset (no per-typeConstraints, noDialPolicy) does not behave as a multi-underlay channel today:isMultiUnderlayCapable()ignoresMinTotalUnderlays, soAcceptUnderlayrejects additional underlays.applyConstraints()early-returns whenlen(constraints) == 0, and the total-count check (countsShowValidState) lives inside that path, soMinTotalUnderlaysis never enforced on its own.Net:
MinTotalUnderlaysis effectively a no-op unless per-type constraints are also set. That makes it impossible to express the simple, common listener intent "accept additional underlays of any type, and close only when the last one is lost" without addingMin: 0per-type constraints purely to flip the capability bit.This is the v4
SetMinTotal(1)behavior that listener-side channels (e.g. OpenZiti control channels) relied on. OpenZiti currently works around it withMin: 0constraints plusMinTotalUnderlays: 1.Proposal
Make
MinTotalUnderlaysfirst-class:isMultiUnderlayCapable()returns true whenminTotalUnderlays > 0.applyConstraints()proceeds (rather than early-returning) whenminTotalUnderlays > 0even with no per-type constraints, so the total-count check runs and closes the channel below the minimum.With this, a listener can pass just
MinTotalUnderlays: 1to get "multi-underlay-capable, closes when empty, never dials," and the OpenZiti workaround constraints can be dropped.