package model import "time" // User represents a row in the `users` table. // // PasswordHash is tagged `json:"-"` so it never leaks via JSON marshalling // even if a caller accidentally passes a User through response.JSON. // // EmailVerifiedAt is a pointer so JSON-encoded users carry an explicit `null` // when the user has not yet verified, instead of an omitted field — the // frontend uses this to decide whether to show the "verify your email" ribbon. type User struct { ID string `json:"id"` Email string `json:"email"` Handle string `json:"handle"` Name string `json:"name"` AvatarURL *string `json:"avatar_url"` Role string `json:"role"` Plan string `json:"plan"` // "free" | "premium" EmailVerifiedAt *time.Time `json:"email_verified_at"` PasswordHash string `json:"-"` TokenVersion int `json:"-"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // AuthToken represents a row in the `auth_tokens` table. // Used for both password reset and email verification flows. type AuthToken struct { ID string `json:"id"` UserID string `json:"user_id"` Purpose string `json:"purpose"` // "password_reset" | "email_verification" TokenHash string `json:"-"` ExpiresAt time.Time `json:"expires_at"` UsedAt *time.Time `json:"used_at,omitempty"` CreatedAt time.Time `json:"created_at"` } const ( PurposePasswordReset = "password_reset" PurposeEmailVerification = "email_verification" ) // ShortURL represents a shortened URL. type ShortURL struct { ID string `json:"id"` Slug string `json:"slug"` TargetURL string `json:"target_url"` CreatedBy *string `json:"created_by,omitempty"` ClickCount int64 `json:"click_count"` CreatedAt time.Time `json:"created_at"` ExpiresAt *time.Time `json:"expires_at,omitempty"` }