From 676e29902e8761fbe5227b67dfd2e4350dfdf9eb Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 25 Mar 2026 18:04:20 -0700 Subject: [PATCH 1/2] =?UTF-8?q?feat(encryptid):=20device=20management=20?= =?UTF-8?q?=E2=80=94=20labeled=20passkey=20list=20+=20nudge=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add label column to credentials, PATCH/DELETE endpoints for rename/remove, device list UI in account modal with rename/remove actions, and clear stale nudge dismiss timestamp after device registration so multiDevice API check takes over permanently. Co-Authored-By: Claude Opus 4.6 --- shared/components/rstack-identity.ts | 123 +++++++++++++++++++++++++-- src/encryptid/db.ts | 22 ++++- src/encryptid/schema.sql | 3 + src/encryptid/server.ts | 45 ++++++++++ 4 files changed, 183 insertions(+), 10 deletions(-) diff --git a/shared/components/rstack-identity.ts b/shared/components/rstack-identity.ts index 281a2be..42f8750 100644 --- a/shared/components/rstack-identity.ts +++ b/shared/components/rstack-identity.ts @@ -1155,6 +1155,10 @@ export class RStackIdentity extends HTMLElement { let guardiansLoaded = false; let guardiansLoading = false; + let devices: { credentialId: string; label: string | null; createdAt: number; lastUsed?: number; transports?: string[] }[] = []; + let devicesLoaded = false; + let devicesLoading = false; + let addresses: { id: string; street: string; city: string; state: string; zip: string; country: string }[] = []; let addressesLoaded = false; let addressesLoading = false; @@ -1271,15 +1275,44 @@ export class RStackIdentity extends HTMLElement { const renderDeviceSection = () => { const isOpen = openSection === "device"; const done = acctStatus ? acctStatus.multiDevice : null; - const body = isOpen ? ` - ` : ""; + let body = ""; + if (isOpen) { + if (devicesLoading) { + body = ``; + } else { + const fmtDate = (ts?: number) => ts ? new Date(ts).toLocaleDateString(undefined, { month: "short", day: "numeric", year: "numeric" }) : "Never"; + const transportBadge = (t: string) => `${t}`; + + const deviceListHTML = devices.length > 0 + ? `
${devices.map(d => ` +
+
+ ๐Ÿ”‘ +
+ ${(d.label || "Unnamed device").replace(/ + Added ${fmtDate(d.createdAt)} ยท Last used ${fmtDate(d.lastUsed)} + ${d.transports?.length ? `
${d.transports.map(transportBadge).join("")}
` : ""} +
+
+
+ + +
+
+ `).join("")}
` : ""; + + body = ` + `; + } + } return `