Add iOS node push-token registration foundation

This commit is contained in:
William Valentin
2026-02-16 12:47:34 -08:00
parent bea4c54f3b
commit 58c4b0b9bb
19 changed files with 448 additions and 7 deletions
+36 -1
View File
@@ -100,6 +100,7 @@ export interface GatewayServerConfig {
allowedRoles: string[];
featureGates: Record<string, boolean>;
locationEnabled?: boolean;
pushEnabled?: boolean;
};
/** Optional pairing manager for DM pairing code management via gateway. */
pairingManager?: PairingManager;
@@ -231,6 +232,13 @@ export class GatewayServer {
registeredAt: number;
location?: NodeConnectionState['location'];
status?: NodeConnectionState['status'];
push?: {
provider: NonNullable<NodeConnectionState['pushToken']>['provider'];
tokenPreview: string;
topic?: string;
environment: NonNullable<NodeConnectionState['pushToken']>['environment'];
registeredAt: number;
};
}> = [];
for (const [connectionId, state] of this.connectionStateMap.entries()) {
@@ -253,6 +261,15 @@ export class GatewayServer {
registeredAt: state.node.registeredAt,
location: state.location,
status: state.status,
push: state.pushToken
? {
provider: state.pushToken.provider,
tokenPreview: maskToken(state.pushToken.token),
topic: state.pushToken.topic,
environment: state.pushToken.environment,
registeredAt: state.pushToken.registeredAt,
}
: undefined,
});
}
@@ -361,6 +378,7 @@ export class GatewayServer {
const nodeHandlers = createNodeHandlers({
enabled: this.config.nodes?.enabled ?? false,
locationEnabled: this.config.nodes?.locationEnabled ?? false,
pushEnabled: this.config.nodes?.pushEnabled ?? false,
allowedRoles: this.config.nodes?.allowedRoles ?? [],
featureGates: this.config.nodes?.featureGates ?? {},
getConnectionState: (connectionId) => this.connectionStateMap.get(connectionId),
@@ -394,6 +412,16 @@ export class GatewayServer {
status,
});
},
setNodePushToken: (connectionId, pushToken) => {
const existing = this.connectionStateMap.get(connectionId);
if (!existing) {
return;
}
this.connectionStateMap.set(connectionId, {
...existing,
pushToken,
});
},
});
// Config handlers (only if config object is provided)
@@ -740,7 +768,7 @@ export class GatewayServer {
nodeRole: this.connectionStateMap.get(connectionId)?.node?.role,
allowedRoles: this.config.nodes?.allowedRoles ?? [],
roleScopes: {
companion: ['node.capabilities.get', 'node.location.set', 'node.location.get', 'node.status.set'],
companion: ['node.capabilities.get', 'node.location.set', 'node.location.get', 'node.status.set', 'node.push_token.set'],
observer: ['node.capabilities.get', 'node.location.get'],
automation: ['node.capabilities.get', 'node.location.get'],
},
@@ -849,3 +877,10 @@ export class GatewayServer {
return readRequestBody(req, { maxBytes });
}
}
function maskToken(token: string): string {
if (token.length <= 8) {
return '****';
}
return `***${token.slice(-8)}`;
}