feat(review 008 Unit 2): flavor-form open-op ids in discovery (U-1, ADR-047 amendment 3)
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.
This commit is contained in:
1 parent
82ddddf986
commit
620180d615
4 files changed
+442
-25
No files matched your search
@@ -11,7 +11,94 @@ base registry installed as the session's dispatch registry**, not the
|
||||
connection overlay — see "Amendment (§4 mechanism, 2026-09-03)" below;
|
||||
§6 amended 2026-09-06 — the static half of discovery gains an additive
|
||||
per-op `description` on the listing, the dynamic half stays deferred
|
||||
— see "Amendment (§6 listing enrichment, 2026-09-06)" below)
|
||||
— see "Amendment (§6 listing enrichment, 2026-09-06)" below;
|
||||
amendment 3 (2026-09-16, review 008 U-1) — the op-name convention
|
||||
extends to the flavor form and discovery carries an explicit
|
||||
`channel_open_alpn` for non-derivable names — see "Amendment 3" below)
|
||||
|
||||
## Amendment 3 (flavor-form open-op ids + explicit `channel_open_alpn`, 2026-09-16 — review 008 U-1)
|
||||
|
||||
alktunnels' graduation (ADR-002 Amendment 1 at
|
||||
`/workspace/@alkdev/alktunnels/docs/architecture/decisions/002-alpn-strategy.md`)
|
||||
pins two NEW `Sub`-typed open ops on the existing `alk/tunnel` ALPN
|
||||
with flavor-form op ids (`channels/tunnel/direct`,
|
||||
`channels/tunnel/forwarded`) — the ssh
|
||||
`direct-tcpip`/`forwarded-tcpip` shape: one ALPN, several channel
|
||||
flavors, one open op per flavor. §1 pinned the open-op naming to
|
||||
exactly two shapes per ALPN (`channels/<alpn>/sub`,
|
||||
`channels/<alpn>/pub`), and Gap F's marker reconstruction derived the
|
||||
ALPN by stripping exactly those two suffixes — so a flavor-form op id
|
||||
failed the derivation and a hub consuming through discovery rebuilt
|
||||
the spec WITHOUT the marker (the silent plain-forwarding-stub failure,
|
||||
the worst mode for a relay). Runtime was never blocked (registration
|
||||
sets the ALPN explicitly; `open_channel` takes it as an argument);
|
||||
discovery + hub relay are the re-produce path that must survive.
|
||||
|
||||
**The convention sentence (mirroring alktunnels ADR-002 Amendment 1):**
|
||||
`channels/<alpn>/<flavor>` is a valid open-op name where `<flavor>`
|
||||
is a bare path segment (no `/`), `Sub`-typed, served through the same
|
||||
establishment wrapper and relay path as `…/sub`. New flavors are new
|
||||
op ids — additive; the `…/sub` op is never reused for a different
|
||||
meaning. `OperationType` (`Sub`/`Pub`) continues to carry the
|
||||
direction; the flavor is the channel-type discriminator the producing
|
||||
crate owns (per-ALPN params semantics, per alktunnels ADR-001
|
||||
Amendment 1).
|
||||
|
||||
**The wire shape (Gap F refinement):** the boolean marker's
|
||||
round-trip is derivable only for the standard shapes. The rule:
|
||||
|
||||
- `spec_to_json_pub` keeps emitting `"channel_open": true` for every
|
||||
marked op (unchanged). When the op name is NOT the standard
|
||||
`channels/<segment>/(sub|pub)` shape, it ALSO emits
|
||||
`"channel_open_alpn": "<alpn>"` — the explicit string rides beside
|
||||
the boolean. Standard shapes stay byte-identical to the
|
||||
pre-amendment payload (no new key).
|
||||
- `rebuild_spec_for` prefers the explicit string when present; else
|
||||
(the boolean alone — the deployment-skew case of an old producer)
|
||||
the derivation generalizes from "strip `/sub`|`/pub`" to "strip the
|
||||
LAST path segment." The boolean marker remains the gate: the
|
||||
derivation is consulted only for marked ops, so a plain op named
|
||||
`channels/tty/query` is unaffected, and a `channel_open_alpn`
|
||||
string without the boolean never marks an op.
|
||||
- `services/schema`'s advertised `operation_spec_schema` documents
|
||||
`channel_open_alpn` as an optional `["string", "null"]` property
|
||||
(schema-type widening, additive — old consumers ignore unknown
|
||||
properties).
|
||||
- Both wire consumers of the shape — the `from_call` import and the
|
||||
`op/register` announced-spec path — parse through the same
|
||||
`rebuild_spec_for`, so one parser change covers both.
|
||||
|
||||
**Residual ambiguity, pinned:** an op name whose ALPN segment itself
|
||||
ends in a flavor-like name (`channels/x/direct` where the intended
|
||||
ALPN is `alk/x/direct`-shaped) is undecidable from the name alone —
|
||||
strip-last reads `alk/x`, and the true ALPN is unknowable from the
|
||||
name. The explicit `channel_open_alpn` string is the disambiguator:
|
||||
producing crates with non-`alk/*`-derivable names set it; the
|
||||
derivation is the fallback for derivable shapes. Old producers
|
||||
(alkcall ≤ 0.7.1) cannot serve flavor-form marked ops discoverably
|
||||
until upgraded — the review's one-way-door timing note.
|
||||
|
||||
Door type: the flavor-form names and the additive
|
||||
`channel_open_alpn` key are wire-stable from the first consumer
|
||||
(alksocks composes against them); the boolean's meaning for
|
||||
standard-shape ops is unchanged (the pre-amendment byte-stability is
|
||||
pinned by test). The `op_name_is_standard_channel_open_shape` helper
|
||||
and the strip-last derivation are two-way-door implementation details
|
||||
within the one-way wire shape.
|
||||
|
||||
Implemented surface (alkcall 0.7.2): the generalized
|
||||
`derive_alpn_from_op_name` (strip-last), the explicit-field emission
|
||||
(`spec_to_json_pub` + the advertised schema property), and the
|
||||
preference order in `rebuild_spec_for`. Verification gates landed as
|
||||
tests: `channels/tunnel/direct` reconstructs WITH
|
||||
`channel_open = alk/tunnel` (gate 1, both the explicit-string and the
|
||||
skew-case paths); standard boolean ops (`channels/tty/sub`,
|
||||
multi-segment `channels/custom/proto/sub`) round-trip byte-stable
|
||||
(gate 3); the explicit string overrides a colliding derivation; a
|
||||
string without the boolean never marks; `op/register` announced
|
||||
flavor-form specs round-trip with the marker. Gate 2 (the hub-relay
|
||||
round trip) lands with the in-tree relay component (review 008
|
||||
remediation plan Unit 3, amending ADR-042).
|
||||
|
||||
## Amendment (§6 listing enrichment, 2026-09-06)
|
||||
|
||||
|
||||
Reference in new issue
Block a user