* SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * See the LICENSE file in the project root for the full license text. */ declare(strict_types=1); namespace App\Domain; final class User { /** * Public label used in the UI when a user is tombstoned (R01-N23). Audit * rows keep the historical email verbatim; this constant only feeds the * live display layer (Users page, anywhere that surfaces a user object). */ public const TOMBSTONE_LABEL = '(former user)'; public function __construct( public readonly int $id, public readonly string $entraOid, public readonly string $email, public readonly string $displayName, public readonly bool $isAdmin, public readonly string $createdAt, public readonly ?string $lastLoginAt, public readonly ?string $tombstonedAt = null, ) { } public function isTombstoned(): bool { return $this->tombstonedAt !== null; } /** Email to display in the live UI — redacted while tombstoned. */ public function publicEmail(): string { return $this->isTombstoned() ? self::TOMBSTONE_LABEL : $this->email; } /** Display name for the live UI — redacted while tombstoned. */ public function publicDisplayName(): string { return $this->isTombstoned() ? self::TOMBSTONE_LABEL : $this->displayName; } /** Stable row snapshot for audit JSON. */ public function toAuditSnapshot(): array { return [ 'id' => $this->id, 'entra_oid' => $this->entraOid, 'email' => $this->email, 'display_name' => $this->displayName, 'is_admin' => $this->isAdmin ? 1 : 0, 'created_at' => $this->createdAt, 'last_login_at' => $this->lastLoginAt, 'tombstoned_at' => $this->tombstonedAt, ]; } }