Add node location access RPCs and operator visibility

This commit is contained in:
William Valentin
2026-02-16 12:30:55 -08:00
parent 1d16cd54e6
commit fe8674e108
19 changed files with 693 additions and 15 deletions
+45 -3
View File
@@ -97,6 +97,7 @@ export interface GatewayServerConfig {
enabled: boolean;
allowedRoles: string[];
featureGates: Record<string, boolean>;
locationEnabled?: boolean;
};
/** Optional pairing manager for DM pairing code management via gateway. */
pairingManager?: PairingManager;
@@ -185,6 +186,36 @@ export class GatewayServer {
getPresence: channelRegistry
? (opts) => channelRegistry.getPresence(opts)
: undefined,
getNodeLocations: ({ role, nodeId, limit } = {}) => {
const entries: Array<{
nodeId: string;
role: string;
connectionId: string;
location: NonNullable<NodeConnectionState['location']>;
}> = [];
for (const [connectionId, state] of this.connectionStateMap.entries()) {
if (!state.node || !state.location) {
continue;
}
if (role && state.node.role !== role) {
continue;
}
if (nodeId && state.node.nodeId !== nodeId) {
continue;
}
entries.push({
nodeId: state.node.nodeId,
role: state.node.role,
connectionId,
location: state.location,
});
}
const sorted = entries.sort((a, b) => b.location.receivedAt - a.location.receivedAt);
if (typeof limit === 'number' && Number.isFinite(limit) && limit > 0) {
return sorted.slice(0, Math.floor(limit));
}
return sorted;
},
getUsage: () => ({
totalSessions: this.config.sessionManager.listSessions().length,
activeConnections: this.sessionBridge.connectionCount,
@@ -279,6 +310,7 @@ export class GatewayServer {
const nodeHandlers = createNodeHandlers({
enabled: this.config.nodes?.enabled ?? false,
locationEnabled: this.config.nodes?.locationEnabled ?? false,
allowedRoles: this.config.nodes?.allowedRoles ?? [],
featureGates: this.config.nodes?.featureGates ?? {},
getConnectionState: (connectionId) => this.connectionStateMap.get(connectionId),
@@ -292,6 +324,16 @@ export class GatewayServer {
node: registration,
});
},
setNodeLocation: (connectionId, location) => {
const existing = this.connectionStateMap.get(connectionId);
if (!existing) {
return;
}
this.connectionStateMap.set(connectionId, {
...existing,
location,
});
},
});
// Config handlers (only if config object is provided)
@@ -635,9 +677,9 @@ export class GatewayServer {
nodeRole: this.connectionStateMap.get(connectionId)?.node?.role,
allowedRoles: this.config.nodes?.allowedRoles ?? [],
roleScopes: {
companion: ['node.capabilities.get'],
observer: ['node.capabilities.get'],
automation: ['node.capabilities.get'],
companion: ['node.capabilities.get', 'node.location.set', 'node.location.get'],
observer: ['node.capabilities.get', 'node.location.get'],
automation: ['node.capabilities.get', 'node.location.get'],
},
});
if (!nodeAuth.authenticated) {