Draft the `/tipc` multiaddr protocol

Propose a fixed-width service endpoint carrying the TIPC type,
instance and publication scope, with one canonical structured value
that generic multiaddr parsers can compose normally.

Retain the kernel-standard `tipc` name while using “Cluster Domain
Sockets” as explanatory terminology. Document the binary and text
encodings, WireGuard composition, deployment-management boundary,
upstream sequence, test vector and open maintainer questions.

Prompt-IO: ai/prompt-io/opencode/20260819T003328Z_53516b09_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
wkt/tipc_backend_378
Gud Boi 2026-08-19 15:03:00 -04:00
parent ff2b20b7d1
commit be108ccc32
4 changed files with 256 additions and 0 deletions

View File

@ -0,0 +1,37 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: a998acff-af66-4969-a65e-f77cbf5ef8dd
timestamp: 2026-08-19T00:33:28Z
git_ref: wkt/tipc_backend_378
scope: docs
substantive: true
raw_file: 20260819T003328Z_53516b09_prompt_io.raw.md
---
## Prompt
Draft an upstream `/tipc` multiaddr issue modeled on the prior `wg`
proposal.
## Response summary
Added a reviewable upstream issue draft with a concrete binary and
text encoding, composition examples, rollout plan and open design
questions. Retained the ecosystem-standard `tipc` name while using
“Cluster Domain Sockets” as explanatory terminology, and separated
the future `pyroute2` management track from address encoding.
## Files changed
- `ai/tpt-backends/04_tipc_multiaddr_upstream.md` - candidate
`multiformats/multiaddr` issue body.
- `ai/tpt-backends/README.md` - roster the upstream proposal.
## Human edits
The human chose to track the draft under `ai/tpt-backends/` instead
of leaving it in the ignored gish cache, and explicitly requested a
Prompt-IO record for this docs-only commit. The human proposed the
`cds` alternative and unifying TIPC/WireGuard management through
`pyroute2`.

View File

@ -0,0 +1,26 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-08-19T00:33:28Z
git_ref: wkt/tipc_backend_378
diff_cmd: git diff HEAD~1..HEAD
---
## Prompt
The user asked to begin drafting an upstream `/tipc` multiaddr issue
similar to the existing WireGuard proposal, then chose to track the
draft as an AI planning document.
## Response
The generated proposal is intended for `multiformats/multiaddr`:
> `git diff HEAD~1..HEAD -- ai/tpt-backends/04_tipc_multiaddr_upstream.md ai/tpt-backends/README.md`
It proposes a code allocated upstream, a fixed 72-bit value holding
the service type, instance and scope, and the canonical text form
`/tipc/<type>:<instance>:<scope>`. It includes WireGuard composition,
security boundaries, the `tipc` versus `cds` naming decision,
deployment-management separation, implementation phases, test data
and open questions for maintainers.

View File

@ -0,0 +1,191 @@
# `/tipc` multiaddr protocol: upstream issue draft
Candidate issue for `multiformats/multiaddr`, to be submitted after
the encoding questions below have been reviewed locally.
## Context
Linux TIPC (Transparent Inter-Process Communication) addresses a
service by a location-independent `(service type, instance)` name.
A server publishes that name into the kernel-maintained cluster name
table and a client connects by the same name; no host or transport
port forms part of the service identity.
TIPC is also known as **Cluster Domain Sockets**, a useful description
of its relationship to Unix-domain sockets. The registered protocol
name should nevertheless remain `tipc`: it matches Linux's
`AF_TIPC`, socket constants, kernel module and iproute2 frontend.
Registering `cds` would create an ecosystem-specific alias that is
harder to map back to the normative kernel API.
We would like to register a `tipc` multiaddr component so these
service endpoints can be represented directly and composed with a
bearer or tunnel description:
```text
/tipc/1953628160:1616:2
/ip4/192.168.1.50/udp/51820/wg/u<key>/tipc/1953628160:1616:2
\____________ WireGuard bearer ____________/\____ TIPC service ____/
```
In the composed form, the components through `/wg/<key>` identify
the routed bearer and tunnel peer. The `/tipc/...` component is pure
service identity, resolved to a current publisher by the TIPC kernel
name table. Unlike a TCP endpoint, it deliberately has no inner IP
address or port.
This proposal does not imply that parsing the multiaddr configures a
TIPC bearer. In particular, TIPC over a WireGuard interface requires
a separately configured TIPC UDP bearer; WireGuard interfaces are L3
devices and cannot carry TIPC Ethernet media directly.
Today that bearer is configured through iproute2's `tipc` frontend,
which speaks the kernel's `TIPCv2` generic-netlink family. `pyroute2`
already provides WireGuard support and generic-netlink primitives but
has no TIPC codec/module; adding one is a complementary deployment
automation track, not part of this address-format proposal.
## Proposed protocol
- Name: `tipc`
- Code: TBD, allocated in `multiformats/multicodec` under the
`multiaddr` tag before implementations stabilize one
- Size: 72 bits
- Value: service type, service instance and publication scope
### Binary form
Exactly nine bytes with no value-length prefix:
| Offset | Size | Field | Encoding |
| ---: | ---: | --- | --- |
| 0 | 4 bytes | service type | unsigned 32-bit big-endian |
| 4 | 4 bytes | service instance | unsigned 32-bit big-endian |
| 8 | 1 byte | publication scope | unsigned enum byte |
```text
tipc-value = uint32be(type) || uint32be(instance) || uint8(scope)
```
For type `1953628160` (`0x74720000`), instance `1616` and
cluster scope `2`, the payload is:
```text
74 72 00 00 00 00 06 50 02
```
### String form
Use one multiaddr value segment containing three canonical decimal
integers:
```text
/tipc/<type>:<instance>:<scope>
```
Canonical values have no sign, whitespace, alternate radix or
leading zeroes, except that zero itself is `0`. `type` and `instance`
must fit unsigned 32-bit fields. Scope is one of:
- `2`: `TIPC_CLUSTER_SCOPE`
- `3`: `TIPC_NODE_SCOPE`
The existing experimental spelling
`/tipc/<type>/<instance>/<scope>` cannot be registered as one normal
multiaddr protocol: generic parsing treats each slash-delimited name
as another protocol component. A single structured value preserves
TIPC's atomic service-address semantics without registering three
artificial protocols.
## Why scope is included
TIPC scope controls where a bound service publication is visible.
The same address representation is used for listener configuration
and dialing, so retaining scope lets a multiaddr round-trip the full
socket address rather than silently turning a node-local bind into a
cluster publication.
Modern Linux UAPI defines cluster and node scopes. The deprecated
zone spelling should not receive a new wire value; implementations
may normalize legacy input to cluster scope before encoding.
## Composition
Standalone service:
```text
/tipc/1953628160:1616:2
```
TIPC service reached through a WireGuard bearer:
```text
/ip4/192.168.1.50/udp/51820/wg/u<key>/tipc/1953628160:1616:2
```
This differs intentionally from TCP over WireGuard:
```text
/ip4/192.168.1.50/udp/51820/wg/u<key>/ip4/10.0.11.1/tcp/1616
```
TCP repeats an inner locative address. TIPC does not: its service
name is resolved and load-balanced in-kernel across current
publishers.
## Semantics and security
- A TIPC service name identifies a service, not a unique process.
Multiple publishers may bind the same name and connections can be
distributed among them.
- Publication scope is reachability metadata, not authentication.
- A composed `/wg` key authenticates the tunnel peer, not the TIPC
service publisher.
- TIPC's optional native AES-GCM link encryption is independent of
this address codec and of WireGuard.
- Codec implementations should validate field widths and canonical
text only; cluster membership and publisher authorization remain
deployment concerns.
## Implementation plan
1. Reserve a `multiaddr`-tagged code in
`multiformats/multicodec`.
2. Add the fixed-size protocol row and normative encoding text to
`multiformats/multiaddr`.
3. Add codecs and cross-language test vectors, beginning with
`multiformats/py-multiaddr`.
4. Verify standalone and composed `wg` + `tipc` string/binary
round-trips.
## Open questions
1. Is a fixed 72-bit value preferred over a self-describing or
variable-width tuple for this kernel-defined address?
2. Should node scope be representable in a generally shareable
multiaddr, or should the registered form be cluster-only?
3. Does multiaddr have an existing convention for structured numeric
values that should replace the colon-separated text form?
4. Should the specification describe TIPC service *ranges*, or keep
this protocol limited to singleton service names used for
connection endpoints?
## References
- Linux TIPC documentation:
https://docs.kernel.org/networking/tipc.html
- Cluster Domain Sockets terminology:
https://en.wikipedia.org/wiki/Transparent_Inter-process_Communication
- Linux socket UAPI:
https://github.com/torvalds/linux/blob/master/include/uapi/linux/tipc.h
- Linux TIPC generic-netlink UAPI:
https://github.com/torvalds/linux/blob/master/include/uapi/linux/tipc_netlink.h
- pyroute2 WireGuard and generic-netlink APIs:
https://docs.pyroute2.org/wireguard.html
- WireGuard multiaddr implementation discussion:
https://github.com/multiformats/py-multiaddr/issues/107
- WireGuard codec implementation:
https://github.com/multiformats/py-multiaddr/pull/108
- Downstream tracking and prototype:
https://github.com/goodboy/tractor/issues/498

View File

@ -16,6 +16,7 @@ document only their own deltas.
| [01 — TIPC](./01_tipc_backend.md) | [#378] | **none** (stdlib) | small | **landed**, PR [#493] — see the [handoff](./01_tipc_HANDOFF.md) |
| [02 — QUIC/`iroh`](./02_quic_iroh_backend.md) | [#353] | `iroh` (uniffi FFI) | large | needs a prep PR |
| [03 — `wg` bindspace](./03_wg_tunnel_bindspace.md) | [#482], [#443] | `pyroute2` | medium, 3 layers | layer A now |
| [04 — `/tipc` multiaddr](./04_tipc_multiaddr_upstream.md) | [#498] | upstream `multiformats` | issue draft | local review |
Headline conclusions:
@ -52,5 +53,6 @@ lands first ships it.
[#353]: https://github.com/goodboy/tractor/issues/353
[#482]: https://github.com/goodboy/tractor/issues/482
[#443]: https://github.com/goodboy/tractor/issues/443
[#498]: https://github.com/goodboy/tractor/issues/498
[#493]: https://github.com/goodboy/tractor/pull/493