All files / web/src/db/schema family-events.ts

100% Statements 44/44
100% Branches 2/2
100% Functions 2/2
100% Lines 44/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 452x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x  
import { createId } from '@paralleldrive/cuid2'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
import { players } from './players'
import { users } from './users'
 
/**
 * Family events audit log
 *
 * Tracks family-related actions for abuse prevention and visibility:
 * - Parent linked/unlinked
 * - Family code regenerated
 */
export const familyEvents = sqliteTable('family_events', {
  /** Unique event ID */
  id: text('id')
    .primaryKey()
    .$defaultFn(() => createId()),
 
  /** The child this event relates to */
  childPlayerId: text('child_player_id')
    .notNull()
    .references(() => players.id, { onDelete: 'cascade' }),
 
  /** Type of event */
  eventType: text('event_type', {
    enum: ['parent_linked', 'parent_unlinked', 'code_regenerated'],
  }).notNull(),
 
  /** Who performed the action */
  actorUserId: text('actor_user_id')
    .notNull()
    .references(() => users.id, { onDelete: 'cascade' }),
 
  /** The parent being linked/unlinked (null for code_regenerated) */
  targetUserId: text('target_user_id'),
 
  /** When this event occurred */
  createdAt: integer('created_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date()),
})
 
export type FamilyEvent = typeof familyEvents.$inferSelect
export type NewFamilyEvent = typeof familyEvents.$inferInsert