feat(sdk): add auto-verify handshake after gateway registration
Embed transparent verification logic in GatewayClient that automatically sends an RPC "verify" request to the Hub after REGISTERED event. Adds hubId, token, and verifyTimeout options. Upper-layer callers see no change — "registered" state means both gateway registration and Hub verification are complete. Failures surface via onError callback. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e9ed53b615
commit
0eac2b2a23
4 changed files with 60 additions and 3 deletions
|
|
@ -25,6 +25,8 @@ export {
|
|||
type DeleteAgentResult,
|
||||
type UpdateGatewayParams,
|
||||
type UpdateGatewayResult,
|
||||
type VerifyParams,
|
||||
type VerifyResult,
|
||||
} from "./rpc";
|
||||
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -145,3 +145,14 @@ export interface UpdateGatewayResult {
|
|||
url: string;
|
||||
connectionState: string;
|
||||
}
|
||||
|
||||
/** verify - request params */
|
||||
export interface VerifyParams {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
/** verify - response payload */
|
||||
export interface VerifyResult {
|
||||
hubId: string;
|
||||
agentId: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ interface ResolvedOptions {
|
|||
deviceType: DeviceType;
|
||||
autoReconnect: boolean;
|
||||
reconnectDelay: number;
|
||||
hubId: string | undefined;
|
||||
token: string | undefined;
|
||||
verifyTimeout: number;
|
||||
}
|
||||
|
||||
export class GatewayClient {
|
||||
|
|
@ -55,6 +58,9 @@ export class GatewayClient {
|
|||
deviceType: options.deviceType,
|
||||
autoReconnect: options.autoReconnect ?? true,
|
||||
reconnectDelay: options.reconnectDelay ?? 1000,
|
||||
hubId: options.hubId,
|
||||
token: options.token,
|
||||
verifyTimeout: options.verifyTimeout ?? 30_000,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +233,12 @@ export class GatewayClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Hub 验证成功回调 */
|
||||
onVerified(callback: (result: { hubId: string; agentId: string }) => void): this {
|
||||
this.callbacks.onVerified = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 注册消息回调 */
|
||||
onMessage(callback: (message: RoutedMessage) => void): this {
|
||||
this.callbacks.onMessage = callback;
|
||||
|
|
@ -291,11 +303,36 @@ export class GatewayClient {
|
|||
this.socket.on(
|
||||
GatewayEvents.REGISTERED,
|
||||
(response: RegisteredResponse) => {
|
||||
if (response.success) {
|
||||
if (!response.success) {
|
||||
this.callbacks.onError?.(new Error(response.error ?? "Registration failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
// If hubId is configured, auto-verify before exposing "registered" to upper layer
|
||||
if (this.options.hubId) {
|
||||
// Set internal state to allow send/request during verify
|
||||
this._state = "registered";
|
||||
this.request<{ hubId: string; agentId: string }>(
|
||||
this.options.hubId,
|
||||
"verify",
|
||||
{ token: this.options.token },
|
||||
this.options.verifyTimeout,
|
||||
)
|
||||
.then((result) => {
|
||||
// Verify succeeded — now expose "registered" to upper layer
|
||||
this.callbacks.onVerified?.(result);
|
||||
this.callbacks.onRegistered?.(response.deviceId);
|
||||
this.callbacks.onStateChange?.("registered");
|
||||
})
|
||||
.catch((err) => {
|
||||
// Verify failed (UNAUTHORIZED, REJECTED, or timeout)
|
||||
this.callbacks.onError?.(err instanceof Error ? err : new Error(String(err)));
|
||||
this.disconnect();
|
||||
});
|
||||
} else {
|
||||
// No hubId — original behavior
|
||||
this.setState("registered");
|
||||
this.callbacks.onRegistered?.(response.deviceId);
|
||||
} else {
|
||||
this.callbacks.onError?.(new Error(response.error ?? "Registration failed"));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ export interface GatewayClientOptions {
|
|||
autoReconnect?: boolean | undefined;
|
||||
/** Reconnect delay (milliseconds), defaults to 1000 */
|
||||
reconnectDelay?: number | undefined;
|
||||
/** Hub device ID for verification (optional, enables auto-verify after gateway registration) */
|
||||
hubId?: string | undefined;
|
||||
/** Token for first-time verification (optional, omit for reconnection via device whitelist) */
|
||||
token?: string | undefined;
|
||||
/** Verify timeout in ms (default: 30_000, longer because user confirmation may be needed) */
|
||||
verifyTimeout?: number | undefined;
|
||||
}
|
||||
|
||||
/** Connection state */
|
||||
|
|
@ -103,6 +109,7 @@ export interface GatewayClientCallbacks {
|
|||
onConnect?: (socketId: string) => void;
|
||||
onDisconnect?: (reason: string) => void;
|
||||
onRegistered?: (deviceId: string) => void;
|
||||
onVerified?: (result: { hubId: string; agentId: string }) => void;
|
||||
onMessage?: (message: RoutedMessage) => void;
|
||||
onSendError?: (error: SendErrorResponse) => void;
|
||||
onPong?: (data: string) => void;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue