import { pgTable, serial, integer, text, timestamp, uniqueIndex } from 'drizzle-orm/pg-core'; import { users } from 'officerdb/schema'; // One row per paired browser: the salt its token is derived from, and nothing else. // // ── Why this is not `user_integrations` ── // // It was, under provider `browser-relay`. That put a plugin's data in a platform table, which is the same // coupling the extraction removes everywhere else — and it meant the platform's schema carried a row // shape whose meaning lived in code it does not own. // // Moving it is normally a breaking change, because the salt IS the pairing: lose it and every browser // re-pairs. It is free right now and only right now — the relay has been switched off since 2026-08-13 // and `user_integrations` holds zero `browser-relay` rows, checked before this table was written. Doing // it later would cost somebody their paired browsers. export const browserPairings = pgTable( 'browser_pairings', { id: serial('id').primaryKey(), userId: integer('user_id') .notNull() .references(() => users.id, { onDelete: 'cascade' }), /** Random per pairing. The token is HMAC(key, `…:${port}:${userId}:${salt}`) — see sidecar/relay-auth.ts. */ salt: text('salt').notNull(), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }, // One pairing per account. Regenerating replaces the salt rather than adding a second row, which is // what makes "regenerate" actually revoke the old token instead of leaving two valid. (table) => [uniqueIndex('uq_browser_pairings_user').on(table.userId)], );