The HubN Registry now has a proper workflow for requesting, configuring and tracking a peering session. The actual network is older than that workflow.
Several BGP sessions were already running. They had working transport, real route exchange and visibility in the Looking Glass, but no corresponding Registry session. Recreating them through the new request path would mean pretending the connection did not exist, exchanging tunnel details which were already configured and potentially replacing working transport for the sake of making a database tidy.
I added a second path instead: find adjacencies which the route collector can see, compare them with the Registry and import the ones which are already carrying routes.
Starting With Observation
The Looking Glass builds an AS-level graph from the routes received by its collector. That graph is operational evidence rather than a declaration. If two ASNs appear as an edge, the collector has seen paths which connect them.

This is the peering test-lab topology, not the real HubN network. It is useful here because the view came from routes observed by the collector rather than the Registry’s peering table.
The discovery job fetches that graph, the active ASN records and the existing peering sessions at the same time. It ignores edges involving unknown or inactive ASNs, collapses duplicate directions and checks whether an active or configuring session already represents the pair.
What remains is a list of observed-but-untracked adjacencies. Each candidate includes the two ASNs, their tiers, how many paths contributed to the edge and any session which already claims the pair.
I store the observation time and path count as evidence when a session is imported. This isn’t intended as permanent proof that the BGP session will always be up. It records why the Registry started tracking a relationship which did not go through a request.
Observation Doesn’t Explain the Relationship
A BGP path can show that two autonomous systems are adjacent. It cannot, by itself, say what the two operators agreed to do.
HubN’s tier rules make some cases unambiguous enough to infer. Two T1 systems or two T3 systems can be bilateral peers. Between different tiers, the lower-numbered tier is the transit provider. T2 to T2 is deliberately left unresolved because it may be bilateral peering or transit in either direction.
The portal asks for an explicit choice in that case. I would rather leave one field for a person than turn an observed edge into a confidently wrong commercial relationship.
The same caution applies to ordinary peering requests. Every ASN now has a peering profile, but the default policy is closed. Adding discovery for an ASN should not silently opt its owner into receiving requests from everybody else.
Existing Transport Is a Different Setup Mode
An imported session is marked as externally transported. That tells the rest of the workflow that connectivity already exists and is managed somewhere else.
HubN does not ask the two parties for WireGuard endpoints, IPsec identities or a PSK. It does not generate a tunnel which competes with the running one. The session page still shows the relationship, BGP guidance, Looking Glass state, activity and the policy which applies to the session.
This ended up being a useful separation for new sessions too. Transport and routing relationship are connected, but they are not the same lifecycle. Two ASNs can change from bilateral peering to transit without replacing a physical cross-connect. They can move from WireGuard to a direct link without changing who provides transit.
The Registry now stores those changes separately. A relationship change is a proposal which the other side must accept. The proposer can’t accept their own change, and either side can reject it. Once accepted, the new role feeds the generated policy and AS-SET guidance without making the existing transport go through setup again.
The Labels Were Wrong Once
The first version exposed an irritating role bug. The underlying relationship was stored correctly, but parts of the session page described the requester as the provider when the other ASN was actually upstream. The AS-SET prompt inherited the same assumption.
This is exactly the sort of bug which looks cosmetic until somebody copies the configuration beneath it. “Your role” has to be derived from the local ASN and the accepted upstream ASN, not from which side happened to send the original request.
I moved that calculation into one shared utility and added tests for both directions. The API, headings, policy badge and AS-SET actions now use the same result. It is a small fix, but one I am glad the peering lab had made difficult to dismiss as merely a label.
Closing the Two Views
HubN now has two useful accounts of its peerings.
The Registry contains the agreed relationship, transport ownership and configuration intent. The Looking Glass contains what the collector currently observes. Discovery compares them, but neither one is allowed to overwrite the meaning of the other.
An observed adjacency can create an externally transported session when the relationship is clear or a person supplies it. A Registry session which is not yet observed remains pending rather than disappearing. Collector state for a session which has been removed is pruned. If a tracked session later drops, the Registry still remembers what should exist while the Looking Glass shows that it currently does not.
That is the model I have gradually ended up using throughout HubN: keep the declared state, keep the operational state, and spend the automation effort on explaining and repairing the difference between them.
Previously: Testing the HubN Peering Workflow.