'integer', 'expires_at' => 'datetime', 'used_at' => 'datetime', ]; // ── Relationships ── public function user() { return $this->belongsTo(User::class); } // ── Scopes ── public function scopeValid($query) { return $query->where('expires_at', '>', now()) ->whereNull('used_at'); } public function scopeForPurpose($query, string $purpose) { return $query->where('purpose', $purpose); } public function scopeForUser($query, int $userId) { return $query->where('user_id', $userId); } // ── Helpers ── public function isExpired(): bool { return $this->expires_at->isPast(); } public function isUsed(): bool { return !is_null($this->used_at); } public function hasAttemptsLeft(int $max): bool { return $this->attempts < $max; } public function incrementAttempts(): bool { return $this->increment('attempts'); } public function markUsed(): bool { return $this->update(['used_at' => now()]); } }