feat(netlayer): Phase 6 — cleanup + docs (relay → location hint, netlayer guide) - #974
feat(netlayer): Phase 6 — cleanup + docs (relay → location hint, netlayer guide)#974rekmarks wants to merge 9 commits into
Conversation
…rface Rename the libp2p-flavored term "relay" to the netlayer-neutral term "location hint" across the kernel-generic surfaces where the concept is no longer libp2p-specific: the persisted hint pool, its entry type, the store methods, the kernel-level config options, and the RemoteIdentity accessor. - `store/methods/relay.ts` -> `location-hints.ts`; `getRelayMethods` -> `getLocationHintMethods`, `getRelayEntries`/`setRelayEntries`/ `getKnownRelayAddresses` -> their `LocationHint` equivalents; persisted KV key `knownRelays` -> `knownLocationHints`; drop the legacy `string[]` migration path. - `RelayEntry`/`RelayEntryStruct` -> `LocationHintEntry`/`LocationHintEntryStruct`. - `RemoteIdentity.addKnownRelays` -> `addKnownLocationHints`; `RemoteCommsOptions.maxUrlRelayHints`/`maxKnownRelays` -> `maxUrlLocationHints`/`maxKnownLocationHints` (also in the kernel-control RPC struct and the browser worker comms query string). The libp2p netlayer's own config key `config.knownRelays` is deliberately left as-is: it is the seam with `@metamask/netlayer-libp2p`'s `Libp2pNetlayerConfig`, which keeps the "relay" name. Persisted state is not migrated (breaking, per the netlayer plan's compatibility decision). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ibp2p references - Add `docs/writing-a-netlayer.md`: the `Netlayer`/`ChannelProvider` contracts, delivery semantics, incarnation handshake, identity requirements, error mapping, config/registration, testing guidance, a worked example, and an iroh next-netlayer note (issue #968). - Add a `## Networking` glossary section: netlayer, location hint, neutral peer id, loopback netlayer, hub-and-spoke, incarnation handshake, ocap URL. - Generalize `ken-protocol-assessment.md`'s FIFO/transport claims from "TCP/libp2p" to the netlayer per-connection ordering contract. - Update `usage.md` and `identity-backup-recovery.md` remote-comms examples to the `NetlayerSpecifier` shape and neutral (`z…`) peer ids. - Fix stale `packages/nodejs/` paths in `platform-specific.md` to `packages/kernel-node-runtime/`, and note netlayer injection. - Move the SES/libp2p patch guidance off the (now libp2p-free) ocap-kernel README onto `@metamask/netlayer-libp2p`; link the new guide from the netlayer package READMEs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…l stack - master.md: add the Phase 6 "Landed decisions" block (the executed rename, the `config.knownRelays` seam kept, the docs shipped, coverage) and an "Effort complete" summary of what shipped across Phases 1–4+6 and what remains (Phase 5 deferred, the endoify relocation review item, the browser getListenAddresses gap, iroh as future work). - phase-5.md: update the deferral banner to record that Phase 6 has landed and reconcile the plan against it — the relay→location-hint rename touched the kernel surface but not the `config.knownRelays` netlayer-config seam, so the plan's use of that key for `wss://` hub URLs still holds; point at the new writing-a-netlayer guide and glossary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Document the README/test-helper touches in the packages Phase 6 modified incidentally (the three netlayer package READMEs and the libp2p e2e test helper), so the changelog check passes for every changed published package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Brings in 961d968: the reworded endoify follow-up note in master.md and the new phase-6.md §1a 'Follow-ups carried from Phase 4' section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rule, libp2pComms) - Add a packaging section to the writing-a-netlayer guide documenting the load-bearing tsconfig.packages.json subpath→src mapping rule for netlayer-libp2p (§1a.4): a missing mapping makes vitest resolve to dist and initialize a second post-lockdown @libp2p/webrtc, crashing SES. - Record the libp2pComms test-helper retirement (§1a.3) as tracked future work in master.md's effort-complete summary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add the user-requested draft plan for @metamask/netlayer-iroh (proposed to supersede the deferred WebSocket phase as the second real ChannelProvider, plus a provider-conformance test kit). Reconcile it with landed Phase 6: add the kernel's config.knownRelays convention key to its config sketch, link the writing-a-netlayer guide + glossary and the guide's packaging/tsconfig section. Cross-link the draft (marked DRAFT/unscheduled) from master.md's effort-complete iroh bullet and the guide's iroh note, and add one banner sentence to phase-5.md noting the draft exists (Phase 5 remains an independent future option). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FUDCo
left a comment
There was a problem hiding this comment.
Commentary on the writing-a-netlayer document.
| - **`peerId`** — the [neutral peer id](./glossary.md#neutral-peer-id): the base58btc-multibase | ||
| encoding of the raw Ed25519 public key derived from the `keySeed` the netlayer was | ||
| constructed with. It **must** equal `deriveNeutralPeerId(fromHex(keySeed))`. |
There was a problem hiding this comment.
A peer ID is generally employed in the context of the identity that one is trying to contact. However, in this case this peerId property is the peer ID of the local kernel, the identity others should use if they wish to contact "me". This should be made clear.
| reached. These become the location hints the kernel embeds in the [ocap | ||
| URLs](./glossary.md#ocap-url) it issues. Return `[]` if the node cannot be dialed | ||
| (e.g. a browser client). | ||
| - **`stop()`** — tear everything down; after `stop`, sends reject. |
There was a problem hiding this comment.
This needs better explanation. Does it mean "terminate all currently live communications activity and throw away all the runtime state for this execution of the kernel" or does it mean "make this peer go away forever"? I.e., does it make what would happen if the process called exit() happen but without actually exiting, or is it like calling closeConnection() on every open connection or is it something more drastic and permanent? Also, what does "after stop, sends reject" mean? Sends reject to whom in response to what?
| }; | ||
|
|
||
| export type ChannelProvider = { | ||
| readonly peerId: string; |
There was a problem hiding this comment.
Once again, I think this means "my peerId", in contrast to the NetworkChannel interface where it means "their peerId". Possibly it might make sense to revise the names to be clear about this distinction.
| }); | ||
| ``` | ||
|
|
||
| The engine owns handshake-before-register, the `reuseOrReturnChannel` race, the single |
There was a problem hiding this comment.
Here (and probably elsewhere) it's somewhat unclear what entity "the engine" designates. I think it means the generic parts of the netlayer implementation as instantiated by the kernel, but I'm not 100% sure.
| - **`handleMessage(from, message)`** — deliver an inbound message to the kernel. A non-null | ||
| return value is a piggyback reply to send back on the same connection. |
There was a problem hiding this comment.
The relationship between handleMessage() here and read() in the NetworkChannel interface is unclear.
| size validation, stale-peer cleanup, and intentional-close bookkeeping. Share one | ||
| `AbortController` between the provider and the engine: `Netlayer.stop()` aborts it. | ||
|
|
||
| ## 4. Hooks (`NetlayerHooks`) |
There was a problem hiding this comment.
There probably should be an introductory sentence or two explaining what this is and what its role in the overall picture is. Actually, the Overview (section 1 above) probably should have a section that just summarizes what the various component abstractions are and their relationships to each other.
|
|
||
| ## 5. Delivery-semantics contract | ||
|
|
||
| State the guarantee precisely, because the kernel depends on exactly this and no more: |
There was a problem hiding this comment.
This is confusing. Why do I need to state the guarantee precisely? I think this document needs to state that, and I think it was the intent of this sentence to declare that that is what this section was doing, but the phrasing is unclear. This feels like this was maybe the prompt to Claude telling it to produce this section, but out of context it's weird.
| - **Best-effort, ordered per live connection.** Messages written to one live connection are | ||
| delivered in order or not at all. You **MUST NOT** reorder messages within a single | ||
| connection. |
There was a problem hiding this comment.
Implied but not stated, but worth stating, is that there is no intent to enforce any kind of ordering between concurrent connections.
Final phase of the pluggable-netlayer effort (issue #968), stacked on #973 (
rekm/netlayer-4). Phase 5 (@metamask/netlayer-websocket) is deferred by user decision — the effort goes Phase 4 → Phase 6 directly.Phase 6 is cleanup + docs. It contains no functional changes beyond a terminology rename.
Rename: relay → location hint (kernel-generic surface)
The libp2p-flavored term "relay" is renamed to the netlayer-neutral "location hint" everywhere it is the kernel's own vocabulary:
store/methods/relay.ts→location-hints.ts;getRelayMethods→getLocationHintMethods,get/setRelayEntries→get/setLocationHintEntries,getKnownRelayAddresses→getKnownLocationHintAddresses; persisted KV keyknownRelays→knownLocationHints; the legacystring[]migration path is deleted (fresh-storage only, per the effort's break-freely decision).RelayEntry/RelayEntryStruct→LocationHintEntry/LocationHintEntryStruct(theaddrfield name kept).RemoteIdentity.addKnownRelays→addKnownLocationHints;RemoteCommsOptions.maxUrlRelayHints/maxKnownRelays→maxUrlLocationHints/maxKnownLocationHints(also in the kernel-control RPC struct andkernel-browser-runtime'scomms-query-string).config.knownRelaysis deliberately NOT renamed — it is the netlayer-config seam with@metamask/netlayer-libp2p'sLibp2pNetlayerConfig.knownRelays(the one config key the kernel injects by convention), and phase-6 explicitly excludes the libp2p package. Renaming only the kernel side would break the contract.Docs
docs/writing-a-netlayer.md: theNetlayer/ChannelProvidercontracts, delivery semantics, incarnation handshake, identity requirements, error mapping, config/registration, testing guidance, a worked example, and an "iroh is the next (Node-only) netlayer" note.## Networkingglossary section (netlayer, location hint, neutral peer id, loopback netlayer, hub-and-spoke, incarnation handshake, ocap URL).ken-protocol-assessment.md(FIFO/transport → netlayer per-connection ordering),usage.md+identity-backup-recovery.md(NetlayerSpecifier shape, neutralz…peer ids),platform-specific.md(packages/nodejs/→packages/kernel-node-runtime/+ netlayer-injection note). The stale SES/@chainsafe/libp2p-yamuxpatch guidance moved off the now-libp2p-free ocap-kernel README onto@metamask/netlayer-libp2p.master.mdmarks Phase 6 done with a landed-decisions block and an effort-complete summary;phase-5.mdis re-reconciled against the final stack.Coverage
Both touched packages meet/exceed their pre-phase baselines on two clean runs:
Deleting the fully-covered migration path caused a ~0.02–0.07% arithmetic dip on ocap-kernel (no source regressed — uncovered-line count unchanged); it was closed above baseline with two behavior-asserting tests (bootstrap-hint sort order;
remoteForhint-registration failure).Left for humans
@libp2p/webrtcendoify relocation (kernel-shimsendoify-node.js) remains deferred and review-gated — a pre-lockdown import whose relocation touches ~7 packages with a silent-lockdown-failure risk. Not performed here.🤖 Generated with Claude Code