Event::class, 'user' => User::class, 'user_profile' => UserProfile::class, 'person' => Person::class, 'company' => Company::class, 'organisation' => Organisation::class, // 'artist' added when artist module lands // Additional models used as activity-log subjects/causers 'crowd_list' => CrowdList::class, 'crowd_type' => CrowdType::class, 'email_change_request' => EmailChangeRequest::class, 'email_log' => EmailLog::class, 'festival_section' => FestivalSection::class, 'impersonation_session' => ImpersonationSession::class, 'location' => Location::class, 'mfa_backup_code' => MfaBackupCode::class, 'mfa_email_code' => MfaEmailCode::class, 'organisation_email_settings' => OrganisationEmailSettings::class, 'organisation_email_template' => OrganisationEmailTemplate::class, 'person_identity_match' => PersonIdentityMatch::class, 'person_section_preference' => PersonSectionPreference::class, 'person_tag' => PersonTag::class, 'shift' => Shift::class, 'shift_assignment' => ShiftAssignment::class, 'shift_waitlist' => ShiftWaitlist::class, 'time_slot' => TimeSlot::class, 'trusted_device' => TrustedDevice::class, 'user_invitation' => UserInvitation::class, 'user_organisation_tag' => UserOrganisationTag::class, 'volunteer_availability' => VolunteerAvailability::class, // Form-builder models — used as activity-log subjects via the // logSchemaChange / logFieldChange helpers, and (in S2+) as // polymorphic webhook payload subjects. 'form_schema' => FormSchema::class, 'form_schema_section' => FormSchemaSection::class, 'form_field' => FormField::class, 'form_field_library' => FormFieldLibrary::class, 'form_submission' => FormSubmission::class, 'form_submission_section_status' => FormSubmissionSectionStatus::class, 'form_submission_delegation' => FormSubmissionDelegation::class, 'form_value' => FormValue::class, 'form_value_option' => FormValueOption::class, 'form_template' => FormTemplate::class, 'form_schema_webhook' => FormSchemaWebhook::class, 'form_webhook_delivery' => FormWebhookDelivery::class, ]); Person::observe(PersonObserver::class); User::observe(UserObserver::class); FormValue::observe(FormValueObserver::class); // ARCH §31.10 — FORM-02 TAG_PICKER sync listener. \Illuminate\Support\Facades\Event::listen( FormSubmissionSubmitted::class, SyncTagPickerSelectionsOnSubmit::class, ); // ARCH §31.1 — identity-match trigger on event_registration. \Illuminate\Support\Facades\Event::listen( FormSubmissionSubmitted::class, TriggerPersonIdentityMatchOnFormSubmit::class, ); ResetPassword::createUrlUsing(function ($user, string $token) { return config('crewli.portal_url') . '/wachtwoord-resetten?token=' . $token . '&email=' . urlencode($user->email); }); // Tag activity log entries with impersonation context Activity::saving(function (Activity $activity) { $request = request(); $impersonator = $request->attributes->get('impersonator'); $session = $request->attributes->get('impersonation_session'); if ($impersonator && $session) { $properties = $activity->properties?->toArray() ?? []; $properties['impersonated_by'] = [ 'user_id' => $impersonator->id, 'name' => $impersonator->full_name, 'email' => $impersonator->email, ]; $properties['impersonation_session_id'] = $session->id; $activity->properties = collect($properties); } }); } }