Flavor-form open op ids (channels/tunnel/direct, channels/tunnel/
forwarded — alktunnels ADR-007/008) now survive discovery + the
op/register announce path: the marker reconstructs, so a hub consuming
through discovery wraps the op with relay machinery instead of the
silent plain-forwarding-stub failure.
Per the review-008 plan's combined (b)+(c) shape:
- derive_alpn_from_op_name generalizes from strip-/sub|/pub to
strip-last-segment (rsplit_once) — a strict superset: standard
two-suffix shapes derive identically, multi-segment ALPNs survive
the same way, and the flavor form derives. The boolean marker
remains the gate (consulted only for marked ops in
rebuild_spec_for) — a plain op named channels/tty/query is
unaffected.
- spec_to_json_pub emits channel_open_alpn (the explicit string)
beside the boolean when the op name is not the standard
channels/<seg>/(sub|pub) shape; standard shapes stay byte-identical
to the pre-amendment payload. The advertised operation_spec_schema
documents the optional ["string","null"] property.
- rebuild_spec_for prefers the explicit string, else boolean →
generalized derivation. Both wire consumers (from_call import,
op/register announce) parse through the same parser, so one change
covers both. A channel_open_alpn without the boolean never marks an
op (the boolean is the dispatch hint).
Residual ambiguity pinned in the ADR: an ALPN segment colliding with
a flavor name (channels/x/direct → alk/x vs alk/x/direct) is
undecidable from the name alone; the explicit string is the
disambiguator.
Tests (review gates 1 + 3; gate 2 lands with the Unit 3 relay):
- channels/tunnel/direct reconstructs WITH channel_open = alk/tunnel,
both via the explicit string and via the boolean alone (the
deployment-skew case: old producer, new consumer)
- standard shapes (channels/tty/sub, multi-segment
channels/custom/proto/sub) round-trip byte-stable — no new key
- explicit string overrides a colliding derivation; string without
boolean is ignored
- op/register announced flavor-form spec round-trips with the marker
- derivation unit tests: flavor form, non-op-type suffix not
special-cased, prior shapes unchanged
Docs: ADR-047 amendment 3 — the convention sentence (mirroring
alktunnels ADR-002 Amendment 1: flavors are new op ids, additive, the
.../sub op is never reused), the wire shape, the preference order,
the residual-ambiguity note, one-way-door timing.
Verification: cargo test 649 passed (12 new); clippy -D warnings
clean; cargo fmt --check clean; cargo doc --no-deps clean.