*/ use HasFactory; public const SCOPE_AUDIT_VIEW = 'audit_view'; public const SCOPE_WORKSPACE_RECOVERY = 'workspace_recovery'; public const STATUS_REQUESTED = 'requested'; public const STATUS_ACTIVE = 'active'; public const STATUS_DENIED = 'denied'; public const STATUS_EXPIRED = 'expired'; public const STATUS_ENDED = 'ended'; public const APPROVAL_MODE_AUTO = 'auto'; public const APPROVAL_MODE_OWNER_REQUIRED = 'owner_required'; public const APPROVAL_MODE_OWNERLESS_WAIVER = 'ownerless_waiver'; protected $guarded = []; protected function casts(): array { return [ 'requested_at' => 'datetime', 'approved_at' => 'datetime', 'starts_at' => 'datetime', 'expires_at' => 'datetime', 'ended_at' => 'datetime', 'denied_at' => 'datetime', ]; } /** * @return BelongsTo */ public function workspace(): BelongsTo { return $this->belongsTo(Workspace::class); } /** * @return BelongsTo */ public function requester(): BelongsTo { return $this->belongsTo(PlatformUser::class, 'requested_by_platform_user_id'); } /** * @return BelongsTo */ public function approver(): BelongsTo { return $this->belongsTo(User::class, 'approved_by_user_id'); } public function scopeOpen(Builder $query): Builder { return $query->whereIn('status', [ self::STATUS_REQUESTED, self::STATUS_ACTIVE, ]); } public function isActive(): bool { return $this->status === self::STATUS_ACTIVE && $this->expires_at !== null && $this->expires_at->isFuture(); } public function isPending(): bool { return $this->status === self::STATUS_REQUESTED; } public function needsBreakGlass(): bool { return $this->scope === self::SCOPE_WORKSPACE_RECOVERY; } /** * @return array */ public static function scopeLabels(): array { return [ self::SCOPE_AUDIT_VIEW => 'Audit trail review', self::SCOPE_WORKSPACE_RECOVERY => 'Workspace recovery', ]; } public static function scopeLabel(string $scope): string { return self::scopeLabels()[$scope] ?? str($scope)->replace('_', ' ')->title()->toString(); } /** * @return array */ public static function statusLabels(): array { return [ self::STATUS_REQUESTED => 'Pending approval', self::STATUS_ACTIVE => 'Active', self::STATUS_DENIED => 'Denied', self::STATUS_EXPIRED => 'Expired', self::STATUS_ENDED => 'Ended', ]; } public static function statusLabel(string $status): string { return self::statusLabels()[$status] ?? str($status)->replace('_', ' ')->title()->toString(); } /** * @return array */ public static function approvalModeLabels(): array { return [ self::APPROVAL_MODE_AUTO => 'Auto-approved low-risk access', self::APPROVAL_MODE_OWNER_REQUIRED => 'Workspace owner approval required', self::APPROVAL_MODE_OWNERLESS_WAIVER => 'Ownerless recovery waiver', ]; } public static function approvalModeLabel(string $approvalMode): string { return self::approvalModeLabels()[$approvalMode] ?? str($approvalMode)->replace('_', ' ')->title()->toString(); } /** * @return list */ public static function scopes(): array { return [ self::SCOPE_AUDIT_VIEW, self::SCOPE_WORKSPACE_RECOVERY, ]; } /** * @return list */ public static function terminalStatuses(): array { return [ self::STATUS_DENIED, self::STATUS_EXPIRED, self::STATUS_ENDED, ]; } /** * @return list */ public static function supportAccessAuditActions(): array { return [ \App\Support\Audit\AuditActionId::SupportAccessRequested->value, \App\Support\Audit\AuditActionId::SupportAccessActivated->value, \App\Support\Audit\AuditActionId::SupportAccessApproved->value, \App\Support\Audit\AuditActionId::SupportAccessDenied->value, \App\Support\Audit\AuditActionId::SupportAccessEnded->value, \App\Support\Audit\AuditActionId::SupportAccessExpired->value, \App\Support\Audit\AuditActionId::SupportAccessOwnerlessWaiverUsed->value, ]; } }