Hardening: refresh stale device pairing requests and pending metadata (#50695)

* Docs: clarify device pairing supersede behavior

* Device pairing: supersede pending requests on auth changes
This commit is contained in:
Josh Avant
2026-03-19 18:26:06 -05:00
committed by GitHub
parent 9486f6e379
commit 8e132aed6e
19 changed files with 452 additions and 41 deletions

View File

@@ -25,10 +25,33 @@ export type PendingPairingRequest = {
deviceId: string;
displayName?: string;
platform?: string;
role?: string;
roles?: string[];
scopes?: string[];
remoteIp?: string;
ts?: number;
};
function formatStringList(values?: readonly string[]): string {
if (!Array.isArray(values) || values.length === 0) {
return "none";
}
const normalized = values.map((value) => value.trim()).filter((value) => value.length > 0);
return normalized.length > 0 ? normalized.join(", ") : "none";
}
function formatRoleList(request: PendingPairingRequest): string {
const role = request.role?.trim();
if (role) {
return role;
}
return formatStringList(request.roles);
}
function formatScopeList(request: PendingPairingRequest): string {
return formatStringList(request.scopes);
}
export function formatPendingRequests(pending: PendingPairingRequest[]): string {
if (pending.length === 0) {
return "No pending device pairing requests.";
@@ -42,6 +65,8 @@ export function formatPendingRequests(pending: PendingPairingRequest[]): string
`- ${req.requestId}`,
label ? `name=${label}` : null,
platform ? `platform=${platform}` : null,
`role=${formatRoleList(req)}`,
`scopes=${formatScopeList(req)}`,
ip ? `ip=${ip}` : null,
].filter(Boolean);
lines.push(parts.join(" · "));
@@ -182,11 +207,15 @@ function buildPairingRequestNotificationText(request: PendingPairingRequest): st
const label = request.displayName?.trim() || request.deviceId;
const platform = request.platform?.trim();
const ip = request.remoteIp?.trim();
const role = formatRoleList(request);
const scopes = formatScopeList(request);
const lines = [
"📲 New device pairing request",
`ID: ${request.requestId}`,
`Name: ${label}`,
...(platform ? [`Platform: ${platform}`] : []),
`Role: ${role}`,
`Scopes: ${scopes}`,
...(ip ? [`IP: ${ip}`] : []),
"",
`Approve: /pair approve ${request.requestId}`,