feat: QR code phone pairing for Decky plugin + MangoHud guide revision + SteamOS version fix

- Add plugin_pairings table + migration (0028) for short-lived pairing sessions
- Add pairing API: POST /api/plugin/pair/initiate, GET /status/:token, POST /confirm
- Add /pair web page: user scans QR on phone, confirms, API key auto-created
- Plugin: 'Pair with Phone' button renders QR code (qrcode.react), polls for status, saves API key
- Plugin: new initiate_pair + check_pair_status Python RPCs
- Revise MangoHud Setup Guide into clean numbered steps
- Fix SteamOS version detection: read VERSION_ID + BUILD_ID (was just 'SteamOS')
This commit is contained in:
2026-06-28 22:09:39 +08:00
parent b637b55011
commit 1de08ed4ec
12 changed files with 3588 additions and 18 deletions
+27
View File
@@ -178,3 +178,30 @@ export const apikeyRelations = relations(apikey, ({ one }) => ({
references: [user.id],
}),
}))
// ── Decky plugin pairing ────────────────────────────────────
// Short-lived pairing sessions that let a Steam Deck link to a
// user account by scanning a QR code on a logged-in phone.
export const pluginPairing = pgTable(
"plugin_pairings",
{
token: text("token").primaryKey(),
userId: text("user_id"),
apiKeyId: text("api_key_id"),
// Plaintext API key, only present between confirm and the plugin
// retrieving it. Cleared once the plugin has fetched it.
apiKey: text("api_key"),
status: text("status").default("pending").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
confirmedAt: timestamp("confirmed_at"),
expiresAt: timestamp("expires_at").notNull(),
},
(table) => [index("plugin_pairings_userId_idx").on(table.userId)],
)
export const pluginPairingRelations = relations(pluginPairing, ({ one }) => ({
user: one(user, {
fields: [pluginPairing.userId],
references: [user.id],
}),
}))