id(); $table->foreignId('person_id')->constrained('person')->cascadeOnDelete(); // The email address $table->string('value', 255); // Optional label like "work", "home", etc. $table->string('label', 50)->nullable(); // Mark a preferred email for the person (enforce at most one in app logic) $table->boolean('is_primary')->default(false); // Whether this email is considered currently active/usable $table->boolean('is_active')->default(true); // Whether validation checks passed (syntax/deliverability) $table->boolean('valid')->default(true); // When the email was verified (e.g., via confirmation link) $table->timestamp('verified_at')->nullable(); // JSON columns for notification preferences and arbitrary metadata $table->json('preferences')->nullable(); $table->json('meta')->nullable(); // Soft delete support $table->softDeletes(); // Avoid duplicate emails per person among non-deleted records $table->unique(['person_id', 'value', 'deleted_at'], 'emails_person_value_unique'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('emails'); } };