Repository navigation
links: adopt NomadNet's RRC link grammar (rrc-room-links.md v2) - #4
Merged
Merged
Conversation
v1 of the format (2026-08-29) defined
rrc@<32hex>:/room/<percent-encoded name>
and argued that inventing an rrc:// scheme would be an invention "in an
ecosystem that already has a convention for exactly this" — meaning
NomadNet's nnn@ / lxmf@ page-link shorthands.
The reasoning was right and the fact was wrong. NomadNet 1.2.8, released
2026-07-24 and five weeks ahead of that document, ships a full RRC client
and had already claimed BOTH spellings for a different payload grammar:
the rrc:// scheme (Browser.py:277-280) and the rrc@ shorthand, whose
expand_shorthands maps to rrc.hub.session and dispatches to the same
parser (:206-214, :312-314). v1 was the parallel invention it set out to
prevent.
It does not fail cleanly. Transcribing handle_rrc_link and running a v1
link through it, the hub resolves correctly and the room name comes out
as the literal string "room/<x>" — and since this hub accepts any
non-empty UTF-8 room name, that is not an error anywhere. A NomadNet user
following a link this hub emitted creates and joins a junk room.
Percent-encoding compounds it: "#off topic" shared as "off%20topic"
joins a room literally named off%20topic.
So the hub now emits
rrc://<32hex>[:<dest_name>]/<room>
with a LITERAL room segment, and ParseRRCLink reads every spelling
upstream accepts plus v1. The v1 shim is unambiguous: such a link
presents as an EMPTY dest_name (its trailing colon) plus a room of
"room/<segment>", a shape the v2 grammar cannot otherwise produce, since
a v2 link has either no colon at all or a non-empty dest_name. On that
one shape, and only that one, the segment is percent-decoded.
Three consequences, each deliberate:
- roomLinkLocked returns "" for a room name containing whitespace. A
link in running text ends at the first space, so it would name a
shorter, different room; no link is better than a wrong one, and
this is the one thing v1 could express that v2 cannot.
- RRCLink carries DestName. A link naming another aspect names another
destination, and dropping it would silently dial rrc.hub.
- there is no /room/ path namespace any more; the whole tail is the
room name. §2.4 records that as a decision, not an oversight.
docs/rrc-room-links.md is rewritten as v2, with §5 documenting what
happened to v1 so the next reader does not re-derive it. The lesson is
narrower than "check upstream first", which v1 did do: it is that
upstream's convention for a NEIGHBOURING problem is not upstream's
convention for yours. v1 read SPEC §11.6.3, generalised the page-link
grammar to a new aspect, and never checked whether the client already
had an RRC-specific answer. It did, in a module the same package ships.
reticulum-mobile-app emits and reads v2 from the same day's cut;
reticulum-specifications PR #55 documents the grammar in §11.6.3 and
withdraws the shorthand proposal that asked to register what already
existed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pu4nRMJbPenrt4gpBp5uPV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
docs/rrc-room-links.mdv1 definedrrc@<32hex>:/room/<percent-encoded>and argued that inventing anrrc://scheme would be an invention "in an ecosystem that already has a convention for exactly this" — NomadNet'snnn@/lxmf@page-link shorthands.The reasoning was right and the fact was wrong. NomadNet 1.2.8 — released 2026-07-24, five weeks before v1 was written — ships a full RRC client and had already claimed both spellings for a different payload grammar:
rrc://scheme —Browser.py:277-280rrc@shorthand, whoseexpand_shorthandsmaps torrc.hub.sessionand dispatches to the same parser —Browser.py:206-214,:312-314Browser.py:426-461v1 was the parallel invention it set out to prevent.
It does not fail cleanly
Transcribing
handle_rrc_linkand running both grammars through it:rrc://<h>/ops<h>, roomopsrrc@<h>/ops<h>, roomopsrrc@<h>:/room/ops(v1)<h>, roomroom/opsrrc@<h><h>, no roomRow 3 raises no error anywhere — this hub accepts any non-empty UTF-8 room name — so a NomadNet user following a link this hub emitted creates and joins a junk room. Percent-encoding compounds it:
#off topicshared asoff%20topicjoins a room literally namedoff%20topic.What changed
RRCLink.String()emitsrrc://<32hex>[:<dest_name>]/<room>with a literal room segment. The percent-encoder is deleted; the decoder stays for v1.ParseRRCLinkreads every spelling upstream accepts, plus v1. The shim is unambiguous: a v1 link presents as an emptydest_name(its trailing colon) plus a room ofroom/<segment>, a shape v2's grammar cannot otherwise produce.RRCLinkcarriesDestName— a link naming another aspect names another destination, and dropping it would silently dialrrc.hub.roomLinkLockedreturns""for a room name containing whitespace. A link in running text ends at the first space; no link is better than one naming a shorter, different room. This is the one thing v1 could express that v2 cannot.docs/rrc-room-links.mdrewritten as v2, with §5 recording what happened to v1, and §2.4 recording the loss of the/room/path namespace as a decision rather than an oversight.internal/service/lxmfnotify.goinvite link, README example, three test files.Checks
go vet ./...,gofmt -l .,go test ./... -count=1, andgo test ./internal/{hub,history,peerreg,service} -race -count=1— all clean locally, i.e. the same setbuild.ymlruns.Cross-repo
reticulum-mobile-appemits and reads v2 from the same day's cut (android-v1.2.114 / ios-v1.0.105).reticulum-specifications#55 documents the grammar in §11.6.3 and withdraws the shorthand proposal that asked to register what already existed.🤖 Generated with Claude Code
https://claude.ai/code/session_01Pu4nRMJbPenrt4gpBp5uPV