/** * Smartsheet workspace — per-brand workbook connection. * * Cycle 7 schema for migration 0096. Replaces two independent Smartsheet * configs (water + time tracking) with one brand-level workbook hub. * * The encrypted API token lives here. Per-feature configs * (`water_smartsheet_config`, `time_tracking_smartsheet_config`) keep * their sheet_id, column_mapping, sync_frequency, sync_enabled, and * last_sync_* state but read the token from this table via brand_id. * * RLS: brand-scoped, same pattern as existing smartsheet tables. */ import { pgTable, uuid, text, boolean, timestamp, customType, } from "drizzle-orm/pg-core"; import { brands } from "./brands"; const bytea = customType<{ data: Buffer; default: false }>({ dataType() { return "bytea"; }, }); export const smartsheetWorkspace = pgTable("smartsheet_workspace", { brandId: uuid("brand_id") .primaryKey() .references(() => brands.id, { onDelete: "cascade" }), // AES-256-GCM encrypted API token. Same key as the old feature // configs (SMARTSHEET_TOKEN_ENC_KEY); bytes are portable. encryptedApiToken: bytea("encrypted_api_token").notNull(), tokenIv: bytea("token_iv").notNull(), tokenAuthTag: bytea("token_auth_tag").notNull(), // Optional "home" sheet — the tab the brand sees first in the // workbook. NULL is fine; the UI falls back to the first per- // feature sheet mapping. defaultSheetId: text("default_sheet_id"), // Master kill-switch. Per-feature sync_enabled still gates each // feature independently — toggling this off pauses all syncs. connectionEnabled: boolean("connection_enabled").notNull().default(true), // Test-connection bookkeeping (powers the "Last verified 2m ago" // badge on the hub card). lastTestAt: timestamp("last_test_at", { withTimezone: true }), lastTestError: text("last_test_error"), createdBy: text("created_by"), updatedBy: text("updated_by"), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }) .notNull() .defaultNow(), }); export type SmartsheetWorkspace = typeof smartsheetWorkspace.$inferSelect; export type SmartsheetWorkspaceInsert = typeof smartsheetWorkspace.$inferInsert;