/** * GDPR client-data export tracking. * * Each row is one export request. The actual bundle (a ZIP holding * `client.json` + `client.html` and a copy of every attached file) * lives in MinIO; we keep the storage key here plus the lifecycle * markers needed for audit + the "download history" UI. */ import { pgTable, text, timestamp, integer, index } from 'drizzle-orm/pg-core'; import { ports } from './ports'; import { clients } from './clients'; import { user } from './users'; export const gdprExports = pgTable( 'gdpr_exports', { id: text('id') .primaryKey() .$defaultFn(() => crypto.randomUUID()), portId: text('port_id') .notNull() .references(() => ports.id, { onDelete: 'cascade' }), clientId: text('client_id') .notNull() .references(() => clients.id, { onDelete: 'cascade' }), /** Staff member who requested the export. */ requestedBy: text('requested_by') .notNull() .references(() => user.id, { onDelete: 'restrict' }), /** 'pending' | 'building' | 'ready' | 'sent' | 'failed' */ status: text('status').notNull().default('pending'), /** MinIO path under the configured bucket - null until the worker uploads. */ storageKey: text('storage_key'), sizeBytes: integer('size_bytes'), /** When status='failed', the truncated error message. */ error: text('error'), /** Email recipient if the bundle was emailed (typically the client's primary). */ sentTo: text('sent_to'), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), readyAt: timestamp('ready_at', { withTimezone: true }), sentAt: timestamp('sent_at', { withTimezone: true }), /** Cleanup target - bundles are removed from MinIO after this. */ expiresAt: timestamp('expires_at', { withTimezone: true }), }, (table) => [ index('idx_gdpr_exports_client').on(table.clientId), index('idx_gdpr_exports_port_created').on(table.portId, table.createdAt), ], ); export type GdprExport = typeof gdprExports.$inferSelect; export type NewGdprExport = typeof gdprExports.$inferInsert; export type GdprExportStatus = 'pending' | 'building' | 'ready' | 'sent' | 'failed';