fix(mesh): route ordering shadowed /api/mesh/register; initiator side never got a self-entry
Two real bugs found while live-testing the new GET /api/mesh/self
endpoint with two actual jump-host containers (mesh-joined for real,
not mocked):
1. routes/api.js mounted `/` (routes/jump.js, admin-session-gated)
before `/mesh`. Since router.use('/', ...) matches every /api/*
path, EVERY /api/mesh/* request -- including /register, which is
authenticated by a bearer mesh join token, not an admin session --
hit that admin gate first and 401'd before routes/mesh.js ever ran.
Confirmed live: a real gateway-to-gateway /join call failed with a
checkApiToken/LoginFailed error instead of ever reaching /register.
Reordered so /mesh is mounted first.
2. POST /register (the receiving side of a join) persists a `(self)`
registry entry via ensureOwnMeshIndex(), but POST /join (the
initiating side) never did -- so GET /api/mesh/self and the mesh
UI's own-entry handling silently saw nothing on whichever gateway
called /join. Fixed by registering a self-entry there too, using
the exact meshIndex the remote assigned (models/mesh_gateway.js's
register() now accepts an explicit meshIndex instead of always
auto-picking one from the local registry, which has no reason to
agree with what's actually configured on the live wg0 interface).
Verified with two real containers joined over a live network: both
sides now report their own correct mesh IP via GET /api/mesh/self,
and both appear correctly in GET /api/mesh/gateways.
This commit is contained in:
@@ -62,7 +62,16 @@ function nextFreeMeshIndex(existing) {
|
||||
// Re-registering the same public key updates its endpoint/siteSlug but
|
||||
// reuses its existing mesh index -- a gateway that re-registers after a
|
||||
// restart must not get bumped to a new mesh subnet.
|
||||
async function register({ publicKey, endpoint, siteSlug }) {
|
||||
//
|
||||
// meshIndex is normally auto-assigned (the next free local index) -- correct
|
||||
// when THIS gateway is the one handing out indices (POST /register, for both
|
||||
// the caller and itself via ensureOwnMeshIndex). But the INITIATING side of
|
||||
// a join (POST /join) doesn't get to pick its own index -- the remote
|
||||
// already assigned it and returned it in the response -- so an explicit
|
||||
// meshIndex is accepted to record that exact value instead of whatever this
|
||||
// gateway's own local registry would have auto-picked (which has no reason
|
||||
// to agree with the value actually configured on the live wg0 interface).
|
||||
async function register({ publicKey, endpoint, siteSlug, meshIndex: explicitMeshIndex }) {
|
||||
const redis = await getRedis();
|
||||
const existing = await list();
|
||||
const already = existing.find((g) => g.publicKey === publicKey);
|
||||
@@ -75,7 +84,7 @@ async function register({ publicKey, endpoint, siteSlug }) {
|
||||
}
|
||||
|
||||
const id = crypto.randomBytes(8).toString('hex');
|
||||
const meshIndex = nextFreeMeshIndex(existing);
|
||||
const meshIndex = explicitMeshIndex || nextFreeMeshIndex(existing);
|
||||
const gateway = { id, publicKey, endpoint, siteSlug: siteSlug || '', meshIndex, createdAt: now, lastSeenAt: now };
|
||||
await redis.hSet(gatewayKey(id), serialize(gateway));
|
||||
await redis.zAdd(idxKey(), { score: now, value: id });
|
||||
|
||||
Reference in New Issue
Block a user