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

@@ -39,6 +39,8 @@ type PendingDevice = {
deviceId: string;
displayName?: string;
role?: string;
roles?: string[];
scopes?: string[];
remoteIp?: string;
isRepair?: boolean;
ts?: number;
@@ -197,6 +199,30 @@ function formatTokenSummary(tokens: DeviceTokenSummary[] | undefined) {
return parts.join(", ");
}
function formatPendingRoles(request: PendingDevice): string {
const role = typeof request.role === "string" ? request.role.trim() : "";
if (role) {
return role;
}
const roles = Array.isArray(request.roles)
? request.roles.map((item) => item.trim()).filter((item) => item.length > 0)
: [];
if (roles.length === 0) {
return "";
}
return roles.join(", ");
}
function formatPendingScopes(request: PendingDevice): string {
const scopes = Array.isArray(request.scopes)
? request.scopes.map((item) => item.trim()).filter((item) => item.length > 0)
: [];
if (scopes.length === 0) {
return "";
}
return scopes.join(", ");
}
function resolveRequiredDeviceRole(
opts: DevicesRpcOpts,
): { deviceId: string; role: string } | null {
@@ -235,6 +261,7 @@ export function registerDevicesCli(program: Command) {
{ key: "Request", header: "Request", minWidth: 10 },
{ key: "Device", header: "Device", minWidth: 16, flex: true },
{ key: "Role", header: "Role", minWidth: 8 },
{ key: "Scopes", header: "Scopes", minWidth: 14, flex: true },
{ key: "IP", header: "IP", minWidth: 12 },
{ key: "Age", header: "Age", minWidth: 8 },
{ key: "Flags", header: "Flags", minWidth: 8 },
@@ -242,7 +269,8 @@ export function registerDevicesCli(program: Command) {
rows: list.pending.map((req) => ({
Request: req.requestId,
Device: req.displayName || req.deviceId,
Role: req.role ?? "",
Role: formatPendingRoles(req),
Scopes: formatPendingScopes(req),
IP: req.remoteIp ?? "",
Age: typeof req.ts === "number" ? formatTimeAgo(Date.now() - req.ts) : "",
Flags: req.isRepair ? "repair" : "",