Full Code of Relaticle/relaticle for AI

main 6ab18e87f8da cached
911 files
7.3 MB
2.0M tokens
10898 symbols
1 requests
Download .txt
Showing preview only (7,832K chars total). Download the full file or copy to clipboard to get everything.
Repository: Relaticle/relaticle
Branch: main
Commit: 6ab18e87f8da
Files: 911
Total size: 7.3 MB

Directory structure:
gitextract_xr43z_zf/

├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .githooks/
│   └── pre-commit
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug_report.yml
│   │   └── config.yml
│   ├── copilot-instructions.md
│   └── workflows/
│       ├── docker-publish.yml
│       ├── filament-view-monitor-simple.yml
│       └── tests.yml
├── .gitignore
├── CLAUDE.md
├── Dockerfile
├── LICENSE
├── README.md
├── TODOS.md
├── app/
│   ├── Actions/
│   │   ├── Company/
│   │   │   ├── CreateCompany.php
│   │   │   ├── DeleteCompany.php
│   │   │   ├── ListCompanies.php
│   │   │   └── UpdateCompany.php
│   │   ├── Fortify/
│   │   │   ├── CreateNewSocialUser.php
│   │   │   ├── PasswordValidationRules.php
│   │   │   ├── ResetUserPassword.php
│   │   │   ├── UpdateUserPassword.php
│   │   │   └── UpdateUserProfileInformation.php
│   │   ├── Jetstream/
│   │   │   ├── AddTeamMember.php
│   │   │   ├── CreateTeam.php
│   │   │   ├── DeleteTeam.php
│   │   │   ├── DeleteUser.php
│   │   │   ├── InviteTeamMember.php
│   │   │   ├── RemoveTeamMember.php
│   │   │   └── UpdateTeamName.php
│   │   ├── Note/
│   │   │   ├── CreateNote.php
│   │   │   ├── DeleteNote.php
│   │   │   ├── ListNotes.php
│   │   │   └── UpdateNote.php
│   │   ├── Opportunity/
│   │   │   ├── CreateOpportunity.php
│   │   │   ├── DeleteOpportunity.php
│   │   │   ├── ListOpportunities.php
│   │   │   └── UpdateOpportunity.php
│   │   ├── People/
│   │   │   ├── CreatePeople.php
│   │   │   ├── DeletePeople.php
│   │   │   ├── ListPeople.php
│   │   │   └── UpdatePeople.php
│   │   └── Task/
│   │       ├── CreateTask.php
│   │       ├── DeleteTask.php
│   │       ├── ListTasks.php
│   │       ├── NotifyTaskAssignees.php
│   │       └── UpdateTask.php
│   ├── Concerns/
│   │   └── DetectsTeamInvitation.php
│   ├── Console/
│   │   └── Commands/
│   │       ├── BackfillCustomFieldColorsCommand.php
│   │       ├── CleanupExpiredInvitationsCommand.php
│   │       ├── CreateSystemAdminCommand.php
│   │       ├── GenerateSitemapCommand.php
│   │       └── InstallCommand.php
│   ├── Contracts/
│   │   └── User/
│   │       └── CreatesNewSocialUsers.php
│   ├── Data/
│   │   └── SubscriberData.php
│   ├── Enums/
│   │   ├── CreationSource.php
│   │   ├── CustomFieldType.php
│   │   ├── CustomFields/
│   │   │   ├── CompanyField.php
│   │   │   ├── CustomFieldTrait.php
│   │   │   ├── NoteField.php
│   │   │   ├── OpportunityField.php
│   │   │   ├── PeopleField.php
│   │   │   └── TaskField.php
│   │   ├── SocialiteProvider.php
│   │   └── SubscriberTagEnum.php
│   ├── Filament/
│   │   ├── Actions/
│   │   │   └── GenerateRecordSummaryAction.php
│   │   ├── Components/
│   │   │   └── Infolists/
│   │   │       └── AvatarName.php
│   │   ├── Exports/
│   │   │   ├── BaseExporter.php
│   │   │   ├── CompanyExporter.php
│   │   │   ├── NoteExporter.php
│   │   │   ├── OpportunityExporter.php
│   │   │   ├── PeopleExporter.php
│   │   │   └── TaskExporter.php
│   │   ├── Pages/
│   │   │   ├── AccessTokens.php
│   │   │   ├── Auth/
│   │   │   │   ├── Login.php
│   │   │   │   └── Register.php
│   │   │   ├── CreateTeam.php
│   │   │   ├── EditProfile.php
│   │   │   ├── EditTeam.php
│   │   │   ├── OpportunitiesBoard.php
│   │   │   └── TasksBoard.php
│   │   └── Resources/
│   │       ├── CompanyResource/
│   │       │   ├── Pages/
│   │       │   │   ├── ListCompanies.php
│   │       │   │   └── ViewCompany.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       ├── PeopleRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── CompanyResource.php
│   │       ├── NoteResource/
│   │       │   ├── Forms/
│   │       │   │   └── NoteForm.php
│   │       │   └── Pages/
│   │       │       └── ManageNotes.php
│   │       ├── NoteResource.php
│   │       ├── OpportunityResource/
│   │       │   ├── Forms/
│   │       │   │   └── OpportunityForm.php
│   │       │   ├── Pages/
│   │       │   │   ├── ListOpportunities.php
│   │       │   │   └── ViewOpportunity.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── OpportunityResource.php
│   │       ├── PeopleResource/
│   │       │   ├── Pages/
│   │       │   │   ├── ListPeople.php
│   │       │   │   └── ViewPeople.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── PeopleResource.php
│   │       ├── TaskResource/
│   │       │   ├── Forms/
│   │       │   │   └── TaskForm.php
│   │       │   └── Pages/
│   │       │       └── ManageTasks.php
│   │       └── TaskResource.php
│   ├── Health/
│   │   └── AnthropicModelCheck.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── AcceptTeamInvitationController.php
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── CompaniesController.php
│   │   │   │       ├── CustomFieldsController.php
│   │   │   │       ├── NotesController.php
│   │   │   │       ├── OpportunitiesController.php
│   │   │   │       ├── PeopleController.php
│   │   │   │       └── TasksController.php
│   │   │   ├── Auth/
│   │   │   │   ├── CallbackController.php
│   │   │   │   └── RedirectController.php
│   │   │   ├── ContactController.php
│   │   │   ├── HomeController.php
│   │   │   ├── PrivacyPolicyController.php
│   │   │   └── TermsOfServiceController.php
│   │   ├── Middleware/
│   │   │   ├── ApplyTenantScopes.php
│   │   │   ├── EnsureTokenHasAbility.php
│   │   │   ├── ForceJsonResponse.php
│   │   │   ├── SetApiTeamContext.php
│   │   │   ├── SubdomainRootResponse.php
│   │   │   └── ValidateSignature.php
│   │   ├── Requests/
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── IndexCustomFieldsRequest.php
│   │   │   │       ├── IndexRequest.php
│   │   │   │       ├── StoreCompanyRequest.php
│   │   │   │       ├── StoreNoteRequest.php
│   │   │   │       ├── StoreOpportunityRequest.php
│   │   │   │       ├── StorePeopleRequest.php
│   │   │   │       ├── StoreTaskRequest.php
│   │   │   │       ├── UpdateCompanyRequest.php
│   │   │   │       ├── UpdateNoteRequest.php
│   │   │   │       ├── UpdateOpportunityRequest.php
│   │   │   │       ├── UpdatePeopleRequest.php
│   │   │   │       └── UpdateTaskRequest.php
│   │   │   └── ContactRequest.php
│   │   ├── Resources/
│   │   │   └── V1/
│   │   │       ├── CompanyResource.php
│   │   │       ├── Concerns/
│   │   │       │   └── FormatsCustomFields.php
│   │   │       ├── CustomFieldResource.php
│   │   │       ├── NoteResource.php
│   │   │       ├── OpportunityResource.php
│   │   │       ├── PeopleResource.php
│   │   │       ├── TaskResource.php
│   │   │       └── UserResource.php
│   │   └── Responses/
│   │       └── LoginResponse.php
│   ├── Jobs/
│   │   ├── Email/
│   │   │   ├── CreateSubscriberJob.php
│   │   │   └── UpdateSubscriberJob.php
│   │   └── FetchFaviconForCompany.php
│   ├── Listeners/
│   │   ├── CreateTeamCustomFields.php
│   │   ├── Email/
│   │   │   └── NewSubscriberListener.php
│   │   └── SwitchTeam.php
│   ├── Livewire/
│   │   ├── App/
│   │   │   ├── AccessTokens/
│   │   │   │   ├── CreateAccessToken.php
│   │   │   │   └── ManageAccessTokens.php
│   │   │   ├── Profile/
│   │   │   │   ├── DeleteAccount.php
│   │   │   │   ├── LogoutOtherBrowserSessions.php
│   │   │   │   ├── UpdatePassword.php
│   │   │   │   └── UpdateProfileInformation.php
│   │   │   └── Teams/
│   │   │       ├── AddTeamMember.php
│   │   │       ├── DeleteTeam.php
│   │   │       ├── PendingTeamInvitations.php
│   │   │       ├── TeamMembers.php
│   │   │       └── UpdateTeamName.php
│   │   ├── BaseLivewireComponent.php
│   │   └── UpdateProfileInformationForm.php
│   ├── Mail/
│   │   └── NewContactSubmissionMail.php
│   ├── Mcp/
│   │   ├── Filters/
│   │   │   ├── CustomFieldFilter.php
│   │   │   └── CustomFieldSort.php
│   │   ├── Prompts/
│   │   │   └── CrmOverviewPrompt.php
│   │   ├── Resources/
│   │   │   ├── CompanySchemaResource.php
│   │   │   ├── Concerns/
│   │   │   │   └── ResolvesEntitySchema.php
│   │   │   ├── CrmSummaryResource.php
│   │   │   ├── NoteSchemaResource.php
│   │   │   ├── OpportunitySchemaResource.php
│   │   │   ├── PeopleSchemaResource.php
│   │   │   └── TaskSchemaResource.php
│   │   ├── Schema/
│   │   │   └── CustomFieldFilterSchema.php
│   │   ├── Servers/
│   │   │   └── RelaticleServer.php
│   │   └── Tools/
│   │       ├── BaseAttachTool.php
│   │       ├── BaseCreateTool.php
│   │       ├── BaseDeleteTool.php
│   │       ├── BaseDetachTool.php
│   │       ├── BaseListTool.php
│   │       ├── BaseShowTool.php
│   │       ├── BaseUpdateTool.php
│   │       ├── Company/
│   │       │   ├── CreateCompanyTool.php
│   │       │   ├── DeleteCompanyTool.php
│   │       │   ├── GetCompanyTool.php
│   │       │   ├── ListCompaniesTool.php
│   │       │   └── UpdateCompanyTool.php
│   │       ├── Concerns/
│   │       │   ├── BuildsRelationshipResponse.php
│   │       │   ├── ChecksTokenAbility.php
│   │       │   └── SerializesRelatedModels.php
│   │       ├── Note/
│   │       │   ├── AttachNoteToEntitiesTool.php
│   │       │   ├── CreateNoteTool.php
│   │       │   ├── DeleteNoteTool.php
│   │       │   ├── DetachNoteFromEntitiesTool.php
│   │       │   ├── GetNoteTool.php
│   │       │   ├── ListNotesTool.php
│   │       │   └── UpdateNoteTool.php
│   │       ├── Opportunity/
│   │       │   ├── CreateOpportunityTool.php
│   │       │   ├── DeleteOpportunityTool.php
│   │       │   ├── GetOpportunityTool.php
│   │       │   ├── ListOpportunitiesTool.php
│   │       │   └── UpdateOpportunityTool.php
│   │       ├── People/
│   │       │   ├── CreatePeopleTool.php
│   │       │   ├── DeletePeopleTool.php
│   │       │   ├── GetPeopleTool.php
│   │       │   ├── ListPeopleTool.php
│   │       │   └── UpdatePeopleTool.php
│   │       ├── Task/
│   │       │   ├── AttachTaskToEntitiesTool.php
│   │       │   ├── CreateTaskTool.php
│   │       │   ├── DeleteTaskTool.php
│   │       │   ├── DetachTaskFromEntitiesTool.php
│   │       │   ├── GetTaskTool.php
│   │       │   ├── ListTasksTool.php
│   │       │   └── UpdateTaskTool.php
│   │       └── WhoAmiTool.php
│   ├── Models/
│   │   ├── AiSummary.php
│   │   ├── Company.php
│   │   ├── Concerns/
│   │   │   ├── BelongsToTeamCreator.php
│   │   │   ├── HasAiSummary.php
│   │   │   ├── HasCreator.php
│   │   │   ├── HasNotes.php
│   │   │   ├── HasProfilePhoto.php
│   │   │   ├── HasTeam.php
│   │   │   └── InvalidatesRelatedAiSummaries.php
│   │   ├── CustomField.php
│   │   ├── CustomFieldOption.php
│   │   ├── CustomFieldSection.php
│   │   ├── CustomFieldValue.php
│   │   ├── Export.php
│   │   ├── Membership.php
│   │   ├── Note.php
│   │   ├── Opportunity.php
│   │   ├── People.php
│   │   ├── PersonalAccessToken.php
│   │   ├── Scopes/
│   │   │   └── TeamScope.php
│   │   ├── Task.php
│   │   ├── Team.php
│   │   ├── TeamInvitation.php
│   │   ├── User.php
│   │   └── UserSocialAccount.php
│   ├── Observers/
│   │   ├── CompanyObserver.php
│   │   ├── NoteObserver.php
│   │   ├── OpportunityObserver.php
│   │   ├── PeopleObserver.php
│   │   └── TaskObserver.php
│   ├── Policies/
│   │   ├── CompanyPolicy.php
│   │   ├── NotePolicy.php
│   │   ├── OpportunityPolicy.php
│   │   ├── PeoplePolicy.php
│   │   ├── TaskPolicy.php
│   │   └── TeamPolicy.php
│   ├── Providers/
│   │   ├── AppServiceProvider.php
│   │   ├── FaviconServiceProvider.php
│   │   ├── Filament/
│   │   │   └── AppPanelProvider.php
│   │   ├── FortifyServiceProvider.php
│   │   ├── HealthServiceProvider.php
│   │   ├── HorizonServiceProvider.php
│   │   ├── JetstreamServiceProvider.php
│   │   └── MacroServiceProvider.php
│   ├── Rules/
│   │   ├── ValidCustomFields.php
│   │   └── ValidTeamSlug.php
│   ├── Scribe/
│   │   └── Strategies/
│   │       └── GetFromSpatieQueryBuilder.php
│   ├── Services/
│   │   ├── AI/
│   │   │   ├── RecordContextBuilder.php
│   │   │   └── RecordSummaryService.php
│   │   ├── AvatarService.php
│   │   ├── Favicon/
│   │   │   └── Drivers/
│   │   │       ├── GoogleHighResDriver.php
│   │   │       └── HighQualityDriver.php
│   │   └── GitHubService.php
│   ├── Support/
│   │   └── CustomFieldMerger.php
│   └── View/
│       └── Components/
│           └── GuestLayout.php
├── artisan
├── bootstrap/
│   ├── app.php
│   ├── cache/
│   │   └── .gitignore
│   └── providers.php
├── compose.dev.yml
├── compose.yml
├── composer.json
├── config/
│   ├── app.php
│   ├── auth.php
│   ├── avatar.php
│   ├── blade-icons.php
│   ├── cache.php
│   ├── custom-fields.php
│   ├── data.php
│   ├── database.php
│   ├── eloquent-sortable.php
│   ├── favicon-fetcher.php
│   ├── filament.php
│   ├── filesystems.php
│   ├── fortify.php
│   ├── health.php
│   ├── horizon-watcher.php
│   ├── horizon.php
│   ├── jetstream.php
│   ├── logging.php
│   ├── login-link.php
│   ├── mail.php
│   ├── mailcoach-sdk.php
│   ├── markdown-response.php
│   ├── markdown.php
│   ├── media-library.php
│   ├── prism.php
│   ├── queue.php
│   ├── relaticle.php
│   ├── sanctum.php
│   ├── scribe.php
│   ├── sentry.php
│   ├── services.php
│   ├── session.php
│   └── sitemap.php
├── database/
│   ├── .gitignore
│   ├── factories/
│   │   ├── CompanyFactory.php
│   │   ├── CustomFieldFactory.php
│   │   ├── NoteFactory.php
│   │   ├── OpportunityFactory.php
│   │   ├── PeopleFactory.php
│   │   ├── SystemAdministratorFactory.php
│   │   ├── TaskFactory.php
│   │   ├── TeamFactory.php
│   │   ├── TeamInvitationFactory.php
│   │   ├── UserFactory.php
│   │   └── UserSocialAccountFactory.php
│   ├── migrations/
│   │   ├── 0001_01_01_000000_create_users_table.php
│   │   ├── 0001_01_01_000001_create_cache_table.php
│   │   ├── 0001_01_01_000002_create_jobs_table.php
│   │   ├── 2024_08_23_110718_create_teams_table.php
│   │   ├── 2024_08_23_110719_create_team_user_table.php
│   │   ├── 2024_08_23_110720_create_team_invitations_table.php
│   │   ├── 2024_08_24_133803_create_companies_table.php
│   │   ├── 2024_09_11_114549_create_tasks_table.php
│   │   ├── 2024_09_22_084119_create_notes_table.php
│   │   ├── 2024_09_22_091034_create_people_table.php
│   │   ├── 2024_09_22_092300_create_task_user_table.php
│   │   ├── 2024_09_22_110651_add_two_factor_columns_to_users_table.php
│   │   ├── 2024_09_22_110718_create_personal_access_tokens_table.php
│   │   ├── 2024_09_22_114735_create_opportunities_table.php
│   │   ├── 2024_09_26_160649_create_user_social_accounts_table.php
│   │   ├── 2024_09_26_170133_create_notifications_table.php
│   │   ├── 2025_02_07_192236_create_custom_fields_table.php
│   │   ├── 2025_03_15_180559_create_taskables_table.php
│   │   ├── 2025_03_15_192334_create_notables_table.php
│   │   ├── 2025_03_17_180206_create_media_table.php
│   │   ├── 2025_04_30_143551_add_creation_source_to_entity_tables.php
│   │   ├── 2025_05_08_112613_create_imports_table.php
│   │   ├── 2025_05_08_112614_create_exports_table.php
│   │   ├── 2025_05_08_112615_create_failed_import_rows_table.php
│   │   ├── 2025_07_05_093310_update_opportunity_amount_field_type_to_currency.php
│   │   ├── 2025_08_12_202409_add_settings_to_custom_field_options_table.php
│   │   ├── 2025_08_25_173222_update_order_column_to_flowforge_position_for_tasks_and_opportunities.php
│   │   ├── 2025_08_26_124042_create_system_administrators_table.php
│   │   ├── 2025_11_30_202612_create_ai_summaries_table.php
│   │   ├── 2025_12_10_191207_update_people_emails_field_type_to_email.php
│   │   ├── 2025_12_11_000001_update_company_domain_name_settings.php
│   │   ├── 2025_12_20_000000_migrate_to_ulid.php
│   │   ├── 2025_12_27_122241_convert_order_column_to_decimal_and_regenerate_positions.php
│   │   ├── 2026_01_02_152157_update_phone_number_custom_fields_type.php
│   │   ├── 2026_01_12_225824_upgrade_custom_fields_to_v3.php
│   │   ├── 2026_02_11_232804_add_slug_to_teams_table.php
│   │   ├── 2026_02_12_222910_expand_imports_table.php
│   │   ├── 2026_02_13_002721_cleanup_imports_table.php
│   │   ├── 2026_02_15_214730_drop_sessions_user_id_foreign_key.php
│   │   ├── 2026_02_20_212853_add_team_id_to_personal_access_tokens_table.php
│   │   ├── 2026_02_25_124942_add_team_id_indexes_to_entity_tables.php
│   │   ├── 2026_03_15_201741_add_custom_field_value_filtering_indexes.php
│   │   └── 2026_03_18_202956_add_expires_at_to_team_invitations_table.php
│   └── seeders/
│       ├── DatabaseSeeder.php
│       ├── LocalSeeder.php
│       └── SystemAdministratorSeeder.php
├── lang/
│   └── en/
│       ├── access-tokens.php
│       ├── profile.php
│       └── teams.php
├── package.json
├── packages/
│   ├── Documentation/
│   │   ├── README.md
│   │   ├── config/
│   │   │   └── documentation.php
│   │   ├── resources/
│   │   │   ├── css/
│   │   │   │   └── documentation.css
│   │   │   ├── js/
│   │   │   │   └── documentation.js
│   │   │   ├── markdown/
│   │   │   │   ├── developer-guide.md
│   │   │   │   ├── getting-started.md
│   │   │   │   ├── import-guide.md
│   │   │   │   ├── mcp-guide.md
│   │   │   │   └── self-hosting-guide.md
│   │   │   └── views/
│   │   │       ├── components/
│   │   │       │   ├── card.blade.php
│   │   │       │   ├── layout.blade.php
│   │   │       │   └── search-form.blade.php
│   │   │       ├── index.blade.php
│   │   │       ├── search.blade.php
│   │   │       └── show.blade.php
│   │   ├── routes/
│   │   │   └── web.php
│   │   └── src/
│   │       ├── Components/
│   │       │   └── Card.php
│   │       ├── Data/
│   │       │   ├── DocumentData.php
│   │       │   ├── DocumentSearchRequest.php
│   │       │   └── DocumentSearchResultData.php
│   │       ├── DocumentationServiceProvider.php
│   │       ├── Http/
│   │       │   └── Controllers/
│   │       │       └── DocumentationController.php
│   │       └── Services/
│   │           └── DocumentationService.php
│   ├── ImportWizard/
│   │   ├── config/
│   │   │   └── import-wizard.php
│   │   ├── resources/
│   │   │   ├── lang/
│   │   │   │   └── en/
│   │   │   │       └── validation.php
│   │   │   └── views/
│   │   │       ├── components/
│   │   │       │   ├── field-select.blade.php
│   │   │       │   ├── multi-value-input.blade.php
│   │   │       │   ├── select-menu.blade.php
│   │   │       │   └── value-row-actions.blade.php
│   │   │       ├── filament/
│   │   │       │   └── pages/
│   │   │       │       ├── import-history.blade.php
│   │   │       │       └── import-page.blade.php
│   │   │       └── livewire/
│   │   │           ├── import-wizard.blade.php
│   │   │           ├── partials/
│   │   │           │   └── step-indicator.blade.php
│   │   │           └── steps/
│   │   │               ├── mapping-step.blade.php
│   │   │               ├── partials/
│   │   │               │   ├── value-row-choice.blade.php
│   │   │               │   ├── value-row-date.blade.php
│   │   │               │   ├── value-row-multi-value.blade.php
│   │   │               │   ├── value-row-number.blade.php
│   │   │               │   ├── value-row-skipped.blade.php
│   │   │               │   └── value-row-text.blade.php
│   │   │               ├── preview-step.blade.php
│   │   │               ├── review-step.blade.php
│   │   │               └── upload-step.blade.php
│   │   ├── routes/
│   │   │   └── web.php
│   │   └── src/
│   │       ├── Commands/
│   │       │   └── CleanupImportsCommand.php
│   │       ├── Data/
│   │       │   ├── ColumnData.php
│   │       │   ├── EntityLink.php
│   │       │   ├── ImportField.php
│   │       │   ├── ImportFieldCollection.php
│   │       │   ├── InferenceResult.php
│   │       │   ├── MatchableField.php
│   │       │   └── RelationshipMatch.php
│   │       ├── Enums/
│   │       │   ├── DateFormat.php
│   │       │   ├── EntityLinkSource.php
│   │       │   ├── EntityLinkStorage.php
│   │       │   ├── ImportEntityType.php
│   │       │   ├── ImportStatus.php
│   │       │   ├── MatchBehavior.php
│   │       │   ├── NumberFormat.php
│   │       │   ├── ReviewFilter.php
│   │       │   ├── RowMatchAction.php
│   │       │   ├── SortDirection.php
│   │       │   └── SortField.php
│   │       ├── Filament/
│   │       │   └── Pages/
│   │       │       ├── ImportCompanies.php
│   │       │       ├── ImportHistory.php
│   │       │       ├── ImportNotes.php
│   │       │       ├── ImportOpportunities.php
│   │       │       ├── ImportPage.php
│   │       │       ├── ImportPeople.php
│   │       │       └── ImportTasks.php
│   │       ├── Http/
│   │       │   └── Controllers/
│   │       │       └── DownloadFailedRowsController.php
│   │       ├── ImportWizardNewServiceProvider.php
│   │       ├── Importers/
│   │       │   ├── BaseImporter.php
│   │       │   ├── CompanyImporter.php
│   │       │   ├── Contracts/
│   │       │   │   └── ImporterContract.php
│   │       │   ├── NoteImporter.php
│   │       │   ├── OpportunityImporter.php
│   │       │   ├── PeopleImporter.php
│   │       │   └── TaskImporter.php
│   │       ├── Jobs/
│   │       │   ├── ExecuteImportJob.php
│   │       │   ├── ResolveMatchesJob.php
│   │       │   └── ValidateColumnJob.php
│   │       ├── Livewire/
│   │       │   ├── Concerns/
│   │       │   │   └── WithImportStore.php
│   │       │   ├── ImportWizard.php
│   │       │   └── Steps/
│   │       │       ├── MappingStep.php
│   │       │       ├── PreviewStep.php
│   │       │       ├── ReviewStep.php
│   │       │       └── UploadStep.php
│   │       ├── Models/
│   │       │   ├── FailedImportRow.php
│   │       │   └── Import.php
│   │       ├── Rules/
│   │       │   ├── ImportChoiceRule.php
│   │       │   ├── ImportDateRule.php
│   │       │   └── ImportNumberRule.php
│   │       ├── Store/
│   │       │   ├── ImportRow.php
│   │       │   └── ImportStore.php
│   │       └── Support/
│   │           ├── DataTypeInferencer.php
│   │           ├── EntityLinkResolver.php
│   │           ├── EntityLinkStorage/
│   │           │   ├── CustomFieldValueStorage.php
│   │           │   ├── EntityLinkStorageInterface.php
│   │           │   ├── ForeignKeyStorage.php
│   │           │   └── MorphToManyStorage.php
│   │           ├── EntityLinkValidator.php
│   │           ├── MatchResolver.php
│   │           └── Validation/
│   │               ├── ColumnValidator.php
│   │               └── ValidationError.php
│   ├── OnboardSeed/
│   │   ├── README.md
│   │   ├── resources/
│   │   │   ├── fixtures/
│   │   │   │   ├── companies/
│   │   │   │   │   ├── airbnb.yaml
│   │   │   │   │   ├── apple.yaml
│   │   │   │   │   ├── figma.yaml
│   │   │   │   │   └── notion.yaml
│   │   │   │   ├── notes/
│   │   │   │   │   ├── airbnb_note.yaml
│   │   │   │   │   ├── apple_note.yaml
│   │   │   │   │   ├── dylan_note.yaml
│   │   │   │   │   ├── figma_note.yaml
│   │   │   │   │   └── notion_note.yaml
│   │   │   │   ├── opportunities/
│   │   │   │   │   ├── airbnb_analytics.yaml
│   │   │   │   │   ├── apple_partnership.yaml
│   │   │   │   │   ├── figma_enterprise.yaml
│   │   │   │   │   └── notion_integration.yaml
│   │   │   │   ├── people/
│   │   │   │   │   ├── brian.yaml
│   │   │   │   │   ├── dylan.yaml
│   │   │   │   │   ├── ivan.yaml
│   │   │   │   │   └── tim.yaml
│   │   │   │   └── tasks/
│   │   │   │       ├── brian_call.yaml
│   │   │   │       ├── dylan_followup.yaml
│   │   │   │       ├── ivan_meeting.yaml
│   │   │   │       └── tim_proposal.yaml
│   │   │   └── templates/
│   │   │       └── entity_template.yaml
│   │   └── src/
│   │       ├── Contracts/
│   │       │   └── ModelSeederInterface.php
│   │       ├── ModelSeeders/
│   │       │   ├── CompanySeeder.php
│   │       │   ├── NoteSeeder.php
│   │       │   ├── OpportunitySeeder.php
│   │       │   ├── PeopleSeeder.php
│   │       │   └── TaskSeeder.php
│   │       ├── OnboardSeedManager.php
│   │       ├── OnboardSeeder.php
│   │       └── Support/
│   │           ├── BaseModelSeeder.php
│   │           ├── BulkCustomFieldValueWriter.php
│   │           ├── FixtureLoader.php
│   │           └── FixtureRegistry.php
│   └── SystemAdmin/
│       └── src/
│           ├── Enums/
│           │   └── SystemAdministratorRole.php
│           ├── Filament/
│           │   ├── Exports/
│           │   │   └── CompanyExporter.php
│           │   ├── Pages/
│           │   │   ├── Dashboard.php
│           │   │   └── EngagementDashboard.php
│           │   ├── Resources/
│           │   │   ├── CompanyResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateCompany.php
│           │   │   │       ├── EditCompany.php
│           │   │   │       ├── ListCompanies.php
│           │   │   │       └── ViewCompany.php
│           │   │   ├── CompanyResource.php
│           │   │   ├── ImportResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── ListImports.php
│           │   │   │   │   └── ViewImport.php
│           │   │   │   └── RelationManagers/
│           │   │   │       └── FailedRowsRelationManager.php
│           │   │   ├── ImportResource.php
│           │   │   ├── NoteResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateNote.php
│           │   │   │       ├── EditNote.php
│           │   │   │       ├── ListNotes.php
│           │   │   │       └── ViewNote.php
│           │   │   ├── NoteResource.php
│           │   │   ├── OpportunityResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateOpportunity.php
│           │   │   │       ├── EditOpportunity.php
│           │   │   │       ├── ListOpportunities.php
│           │   │   │       └── ViewOpportunity.php
│           │   │   ├── OpportunityResource.php
│           │   │   ├── PeopleResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreatePeople.php
│           │   │   │       ├── EditPeople.php
│           │   │   │       ├── ListPeople.php
│           │   │   │       └── ViewPeople.php
│           │   │   ├── PeopleResource.php
│           │   │   ├── SystemAdministrators/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateSystemAdministrator.php
│           │   │   │   │   ├── EditSystemAdministrator.php
│           │   │   │   │   ├── ListSystemAdministrators.php
│           │   │   │   │   └── ViewSystemAdministrator.php
│           │   │   │   ├── Schemas/
│           │   │   │   │   ├── SystemAdministratorForm.php
│           │   │   │   │   └── SystemAdministratorInfolist.php
│           │   │   │   ├── SystemAdministratorResource.php
│           │   │   │   └── Tables/
│           │   │   │       └── SystemAdministratorsTable.php
│           │   │   ├── TaskResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateTask.php
│           │   │   │       ├── EditTask.php
│           │   │   │       ├── ListTasks.php
│           │   │   │       └── ViewTask.php
│           │   │   ├── TaskResource.php
│           │   │   ├── TeamResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateTeam.php
│           │   │   │   │   ├── EditTeam.php
│           │   │   │   │   ├── ListTeams.php
│           │   │   │   │   └── ViewTeam.php
│           │   │   │   └── RelationManagers/
│           │   │   │       ├── CompaniesRelationManager.php
│           │   │   │       ├── MembersRelationManager.php
│           │   │   │       ├── NotesRelationManager.php
│           │   │   │       ├── OpportunitiesRelationManager.php
│           │   │   │       ├── PeopleRelationManager.php
│           │   │   │       └── TasksRelationManager.php
│           │   │   ├── TeamResource.php
│           │   │   ├── UserResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateUser.php
│           │   │   │   │   ├── EditUser.php
│           │   │   │   │   ├── ListUsers.php
│           │   │   │   │   └── ViewUser.php
│           │   │   │   └── RelationManagers/
│           │   │   │       ├── OwnedTeamsRelationManager.php
│           │   │   │       └── TeamsRelationManager.php
│           │   │   └── UserResource.php
│           │   └── Widgets/
│           │       ├── ActivationRateWidget.php
│           │       ├── Concerns/
│           │       │   └── HasPeriodComparison.php
│           │       ├── PlatformGrowthStatsWidget.php
│           │       ├── RecordDistributionChartWidget.php
│           │       ├── SignupTrendChartWidget.php
│           │       ├── TopTeamsTableWidget.php
│           │       └── UserRetentionChartWidget.php
│           ├── Models/
│           │   └── SystemAdministrator.php
│           ├── Policies/
│           │   ├── CompanyPolicy.php
│           │   ├── FailedImportRowPolicy.php
│           │   ├── ImportPolicy.php
│           │   ├── NotePolicy.php
│           │   ├── OpportunityPolicy.php
│           │   ├── PeoplePolicy.php
│           │   ├── SystemAdministratorPolicy.php
│           │   ├── TaskPolicy.php
│           │   ├── TeamPolicy.php
│           │   └── UserPolicy.php
│           └── SystemAdminPanelProvider.php
├── phpstan.neon
├── phpunit.ci.xml
├── phpunit.xml
├── pint.json
├── public/
│   ├── .htaccess
│   ├── css/
│   │   ├── asmit/
│   │   │   └── resized-column/
│   │   │       └── resized-column.css
│   │   ├── filament/
│   │   │   ├── filament/
│   │   │   │   └── app.css
│   │   │   ├── forms/
│   │   │   │   └── forms.css
│   │   │   └── support/
│   │   │       └── support.css
│   │   └── relaticle/
│   │       ├── custom-fields/
│   │       │   └── custom-fields.css
│   │       └── flowforge/
│   │           └── flowforge.css
│   ├── fonts/
│   │   └── filament/
│   │       └── filament/
│   │           └── inter/
│   │               └── index.css
│   ├── index.php
│   ├── js/
│   │   ├── asmit/
│   │   │   └── resized-column/
│   │   │       └── resized-column.js
│   │   ├── filament/
│   │   │   ├── actions/
│   │   │   │   └── actions.js
│   │   │   ├── filament/
│   │   │   │   ├── app.js
│   │   │   │   └── echo.js
│   │   │   ├── forms/
│   │   │   │   └── components/
│   │   │   │       ├── checkbox-list.js
│   │   │   │       ├── code-editor.js
│   │   │   │       ├── color-picker.js
│   │   │   │       ├── date-time-picker.js
│   │   │   │       ├── file-upload.js
│   │   │   │       ├── key-value.js
│   │   │   │       ├── markdown-editor.js
│   │   │   │       ├── rich-editor.js
│   │   │   │       ├── select.js
│   │   │   │       ├── slider.js
│   │   │   │       ├── tags-input.js
│   │   │   │       └── textarea.js
│   │   │   ├── notifications/
│   │   │   │   └── notifications.js
│   │   │   ├── schemas/
│   │   │   │   ├── components/
│   │   │   │   │   ├── actions.js
│   │   │   │   │   ├── tabs.js
│   │   │   │   │   └── wizard.js
│   │   │   │   └── schemas.js
│   │   │   ├── support/
│   │   │   │   ├── async-alpine.js
│   │   │   │   └── support.js
│   │   │   ├── tables/
│   │   │   │   ├── components/
│   │   │   │   │   ├── columns/
│   │   │   │   │   │   ├── checkbox.js
│   │   │   │   │   │   ├── select.js
│   │   │   │   │   │   ├── text-input.js
│   │   │   │   │   │   └── toggle.js
│   │   │   │   │   └── table.js
│   │   │   │   └── tables.js
│   │   │   └── widgets/
│   │   │       └── components/
│   │   │           ├── chart.js
│   │   │           └── stats-overview/
│   │   │               └── stat/
│   │   │                   └── chart.js
│   │   └── relaticle/
│   │       └── flowforge/
│   │           ├── components/
│   │           │   └── flowforge.js
│   │           └── flowforge.js
│   ├── manifest.webmanifest
│   ├── robots.txt
│   └── site.webmanifest
├── rector.php
├── resources/
│   ├── css/
│   │   ├── app.css
│   │   ├── filament/
│   │   │   ├── admin/
│   │   │   │   └── theme.css
│   │   │   └── app/
│   │   │       └── theme.css
│   │   ├── fonts.css
│   │   └── theme.css
│   ├── js/
│   │   ├── app.js
│   │   └── motion.js
│   ├── markdown/
│   │   ├── brand-assets.md
│   │   ├── font-sources.md
│   │   ├── policy.md
│   │   └── terms.md
│   └── views/
│       ├── api/
│       │   └── api-token-manager.blade.php
│       ├── components/
│       │   ├── action-message.blade.php
│       │   ├── action-section.blade.php
│       │   ├── application-logo.blade.php
│       │   ├── application-mark.blade.php
│       │   ├── authentication-card-logo.blade.php
│       │   ├── authentication-card.blade.php
│       │   ├── banner.blade.php
│       │   ├── brand/
│       │   │   ├── logo-lockup.blade.php
│       │   │   ├── logomark.blade.php
│       │   │   └── wordmark.blade.php
│       │   ├── browser-sessions.blade.php
│       │   ├── button.blade.php
│       │   ├── checkbox.blade.php
│       │   ├── confirmation-modal.blade.php
│       │   ├── confirms-password.blade.php
│       │   ├── danger-button.blade.php
│       │   ├── dialog-modal.blade.php
│       │   ├── dropdown-link.blade.php
│       │   ├── dropdown.blade.php
│       │   ├── form-section.blade.php
│       │   ├── input-error.blade.php
│       │   ├── input.blade.php
│       │   ├── label.blade.php
│       │   ├── layout/
│       │   │   ├── footer.blade.php
│       │   │   ├── header.blade.php
│       │   │   └── mobile-menu.blade.php
│       │   ├── legal-document.blade.php
│       │   ├── marketing/
│       │   │   ├── button.blade.php
│       │   │   ├── input.blade.php
│       │   │   └── textarea.blade.php
│       │   ├── modal.blade.php
│       │   ├── nav-link.blade.php
│       │   ├── responsive-nav-link.blade.php
│       │   ├── secondary-button.blade.php
│       │   ├── section-border.blade.php
│       │   ├── section-title.blade.php
│       │   ├── switchable-team.blade.php
│       │   ├── theme-switcher.blade.php
│       │   ├── validation-errors.blade.php
│       │   └── welcome.blade.php
│       ├── contact.blade.php
│       ├── emails/
│       │   └── team-invitation.blade.php
│       ├── filament/
│       │   ├── actions/
│       │   │   └── ai-summary.blade.php
│       │   ├── app/
│       │   │   ├── analytics.blade.php
│       │   │   ├── import-preview-alpine.blade.php
│       │   │   ├── import-value-reviewer-alpine.blade.php
│       │   │   ├── logo-empty.blade.php
│       │   │   └── logo.blade.php
│       │   ├── auth/
│       │   │   └── social_login_buttons.blade.php
│       │   ├── components/
│       │   │   └── infolists/
│       │   │       └── avatar-name.blade.php
│       │   ├── pages/
│       │   │   ├── access-tokens.blade.php
│       │   │   ├── create-team.blade.php
│       │   │   ├── dashboard.blade.php
│       │   │   ├── edit-profile.blade.php
│       │   │   └── edit-team.blade.php
│       │   └── tables/
│       │       └── columns/
│       │           ├── avatar-name-column.blade.php
│       │           └── logo-name-column.blade.php
│       ├── home/
│       │   ├── index.blade.php
│       │   └── partials/
│       │       ├── community.blade.php
│       │       ├── faq.blade.php
│       │       ├── features.blade.php
│       │       ├── hero-agent-preview.blade.php
│       │       ├── hero.blade.php
│       │       └── start-building.blade.php
│       ├── layouts/
│       │   └── guest.blade.php
│       ├── livewire/
│       │   └── app/
│       │       ├── access-tokens/
│       │       │   ├── create-access-token.blade.php
│       │       │   └── manage-access-tokens.blade.php
│       │       ├── profile/
│       │       │   ├── delete-account.blade.php
│       │       │   ├── logout-other-browser-sessions.blade.php
│       │       │   ├── update-password.blade.php
│       │       │   └── update-profile-information.blade.php
│       │       └── teams/
│       │           ├── add-team-member.blade.php
│       │           ├── delete-team.blade.php
│       │           ├── pending-team-invitations.blade.php
│       │           ├── team-members.blade.php
│       │           └── update-team-name.blade.php
│       ├── mail/
│       │   └── new-contact-submission.blade.php
│       ├── policy.blade.php
│       ├── pricing.blade.php
│       ├── profile/
│       │   ├── delete-user-form.blade.php
│       │   ├── logout-other-browser-sessions-form.blade.php
│       │   ├── two-factor-authentication-form.blade.php
│       │   ├── update-password-form.blade.php
│       │   └── update-profile-information-form.blade.php
│       ├── teams/
│       │   ├── create-team-form.blade.php
│       │   ├── delete-team-form.blade.php
│       │   ├── invitation-expired.blade.php
│       │   ├── team-member-manager.blade.php
│       │   └── update-team-name-form.blade.php
│       ├── terms.blade.php
│       └── vendor/
│           ├── filament-panels/
│           │   └── components/
│           │       └── layout/
│           │           └── index.blade.php
│           ├── mail/
│           │   ├── html/
│           │   │   ├── button.blade.php
│           │   │   ├── footer.blade.php
│           │   │   ├── header.blade.php
│           │   │   ├── layout.blade.php
│           │   │   ├── message.blade.php
│           │   │   ├── panel.blade.php
│           │   │   ├── subcopy.blade.php
│           │   │   ├── table.blade.php
│           │   │   └── themes/
│           │   │       └── default.css
│           │   └── text/
│           │       ├── button.blade.php
│           │       ├── footer.blade.php
│           │       ├── header.blade.php
│           │       ├── layout.blade.php
│           │       ├── message.blade.php
│           │       ├── panel.blade.php
│           │       ├── subcopy.blade.php
│           │       └── table.blade.php
│           └── scribe/
│               ├── components/
│               │   ├── badges/
│               │   │   ├── auth.blade.php
│               │   │   ├── base.blade.php
│               │   │   ├── deprecated.blade.php
│               │   │   └── http-method.blade.php
│               │   ├── field-details.blade.php
│               │   └── nested-fields.blade.php
│               ├── external/
│               │   ├── elements.blade.php
│               │   ├── rapidoc.blade.php
│               │   └── scalar.blade.php
│               ├── markdown/
│               │   ├── auth.blade.php
│               │   └── intro.blade.php
│               ├── partials/
│               │   └── example-requests/
│               │       ├── bash.md.blade.php
│               │       ├── javascript.md.blade.php
│               │       ├── php.md.blade.php
│               │       └── python.md.blade.php
│               └── themes/
│                   ├── default/
│                   │   ├── endpoint.blade.php
│                   │   ├── groups.blade.php
│                   │   ├── index.blade.php
│                   │   └── sidebar.blade.php
│                   └── elements/
│                       ├── components/
│                       │   ├── field-details.blade.php
│                       │   └── nested-fields.blade.php
│                       ├── endpoint.blade.php
│                       ├── groups.blade.php
│                       ├── index.blade.php
│                       ├── sidebar.blade.php
│                       └── try_it_out.blade.php
├── routes/
│   ├── ai.php
│   ├── api.php
│   └── web.php
├── storage/
│   ├── app/
│   │   └── .gitignore
│   ├── clockwork/
│   │   └── .gitignore
│   ├── framework/
│   │   ├── .gitignore
│   │   ├── cache/
│   │   │   └── .gitignore
│   │   ├── sessions/
│   │   │   └── .gitignore
│   │   ├── testing/
│   │   │   └── .gitignore
│   │   └── views/
│   │       └── .gitignore
│   ├── logs/
│   │   └── .gitignore
│   └── pail/
│       └── .gitignore
├── stubs/
│   └── Mailcoach.stub
├── tests/
│   ├── Arch/
│   │   └── ArchTest.php
│   ├── Browser/
│   │   ├── Auth/
│   │   │   ├── LoginBrowserTest.php
│   │   │   └── PasswordResetBrowserTest.php
│   │   ├── CRM/
│   │   │   └── CompanyBrowserTest.php
│   │   ├── ImportWizard/
│   │   │   └── ImportWizardBrowserTest.php
│   │   ├── Onboarding/
│   │   │   └── OnboardingBrowserTest.php
│   │   ├── SmokeBrowserTest.php
│   │   └── Teams/
│   │       └── TeamBrowserTest.php
│   ├── Feature/
│   │   ├── AI/
│   │   │   └── RecordSummaryServiceTest.php
│   │   ├── AccessTokens/
│   │   │   ├── AccessTokenPermissionsTest.php
│   │   │   ├── CreateAccessTokenTest.php
│   │   │   └── DeleteAccessTokenTest.php
│   │   ├── Api/
│   │   │   └── V1/
│   │   │       ├── ApiMiddlewareTest.php
│   │   │       ├── ApiTeamScopingTest.php
│   │   │       ├── CompaniesApiTest.php
│   │   │       ├── CustomFieldsApiTest.php
│   │   │       ├── NotesApiTest.php
│   │   │       ├── OpportunitiesApiTest.php
│   │   │       ├── PeopleApiTest.php
│   │   │       ├── TasksApiTest.php
│   │   │       ├── TokenAbilitiesApiTest.php
│   │   │       └── UserEndpointTest.php
│   │   ├── Auth/
│   │   │   ├── AuthenticationTest.php
│   │   │   ├── PasswordResetTest.php
│   │   │   ├── RegistrationTest.php
│   │   │   ├── SocialiteLoginTest.php
│   │   │   ├── TwoFactorAuthenticationSettingsTest.php
│   │   │   └── UserModelTest.php
│   │   ├── CRM/
│   │   │   └── CompanyModelTest.php
│   │   ├── Commands/
│   │   │   └── InstallCommandTest.php
│   │   ├── ContactFormTest.php
│   │   ├── Filament/
│   │   │   └── App/
│   │   │       ├── Exports/
│   │   │       │   ├── CompanyExporterTest.php
│   │   │       │   ├── NoteExporterTest.php
│   │   │       │   ├── OpportunityExporterTest.php
│   │   │       │   ├── PeopleExporterTest.php
│   │   │       │   └── TaskExporterTest.php
│   │   │       ├── Pages/
│   │   │       │   ├── OpportunitiesBoardTest.php
│   │   │       │   └── TasksBoardTest.php
│   │   │       └── Resources/
│   │   │           ├── CompanyResourceTest.php
│   │   │           ├── NoteResourceTest.php
│   │   │           ├── OpportunityResourceTest.php
│   │   │           ├── PeopleResourceTest.php
│   │   │           └── TaskResourceTest.php
│   │   ├── HealthChecks/
│   │   │   └── HealthServiceProviderTest.php
│   │   ├── ImportWizard/
│   │   │   ├── Commands/
│   │   │   │   └── CleanupImportsCommandTest.php
│   │   │   ├── Components/
│   │   │   │   ├── MultiValueInputTest.php
│   │   │   │   └── SelectMenuInvalidOptionsTest.php
│   │   │   ├── Jobs/
│   │   │   │   ├── ExecuteImportJobTest.php
│   │   │   │   ├── ResolveMatchesJobTest.php
│   │   │   │   └── ValidateColumnJobTest.php
│   │   │   ├── Livewire/
│   │   │   │   ├── ImportWizardTest.php
│   │   │   │   ├── MappingStepTest.php
│   │   │   │   ├── PreviewStepTest.php
│   │   │   │   ├── ReviewStepTest.php
│   │   │   │   └── UploadStepTest.php
│   │   │   ├── Support/
│   │   │   │   └── EntityLinkResolverTest.php
│   │   │   └── Validation/
│   │   │       ├── ColumnValidatorTest.php
│   │   │       └── EntityLinkValidatorTest.php
│   │   ├── Mcp/
│   │   │   ├── CompanyToolsTest.php
│   │   │   ├── CrmSummaryResourceTest.php
│   │   │   ├── Filters/
│   │   │   │   ├── CustomFieldFilterTest.php
│   │   │   │   └── CustomFieldSortTest.php
│   │   │   ├── McpToolFeaturesTest.php
│   │   │   ├── NoteToolsTest.php
│   │   │   ├── OpportunityToolsTest.php
│   │   │   ├── PeopleToolsTest.php
│   │   │   ├── RelaticleServerTest.php
│   │   │   ├── SchemaResourcesTest.php
│   │   │   ├── TaskToolsTest.php
│   │   │   ├── TokenAbilitiesMcpTest.php
│   │   │   └── WhoAmiToolTest.php
│   │   ├── Migrations/
│   │   │   └── UlidMigrationTest.php
│   │   ├── Models/
│   │   │   └── Scopes/
│   │   │       └── TeamScopeTest.php
│   │   ├── Onboarding/
│   │   │   └── CreateTeamOnboardingTest.php
│   │   ├── PersonalAccessToken/
│   │   │   └── TeamIdImmutabilityTest.php
│   │   ├── Profile/
│   │   │   ├── AvatarServiceTest.php
│   │   │   ├── BrowserSessionsTest.php
│   │   │   ├── DeleteAccountTest.php
│   │   │   ├── GitHubServiceTest.php
│   │   │   ├── UpdatePasswordTest.php
│   │   │   └── UpdateUserProfileInformationTest.php
│   │   ├── Public/
│   │   │   └── PublicPagesTest.php
│   │   ├── Routing/
│   │   │   ├── AppPanelRoutingTest.php
│   │   │   └── SubdomainRoutingTest.php
│   │   ├── SystemAdmin/
│   │   │   ├── ActivationRateWidgetTest.php
│   │   │   ├── SystemAdminResourceTest.php
│   │   │   ├── SystemAdminSecurityTest.php
│   │   │   └── UserRetentionChartWidgetTest.php
│   │   ├── Teams/
│   │   │   ├── AcceptTeamInvitationTest.php
│   │   │   ├── CreateTeamTest.php
│   │   │   ├── DeleteTeamTest.php
│   │   │   ├── InvitationUxTest.php
│   │   │   ├── InviteTeamMemberTest.php
│   │   │   ├── LeaveTeamTest.php
│   │   │   ├── ManageTeamInvitationsTest.php
│   │   │   ├── RemoveTeamMemberTest.php
│   │   │   ├── TeamModelTest.php
│   │   │   ├── UpdateTeamMemberRoleTest.php
│   │   │   └── UpdateTeamNameTest.php
│   │   └── ValidTeamSlugTest.php
│   ├── Pest.php
│   ├── Smoke/
│   │   └── RouteTest.php
│   ├── TestCase.php
│   └── fixtures/
│       └── imports/
│           ├── companies.csv
│           ├── companies.xlsx
│           └── people.xlsx
└── vite.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
# Git
.git
.gitignore
.gitattributes
.githooks

# IDE
.idea
.vscode
*.swp
*.swo

# Dependencies (will be installed during build)
/vendor
/node_modules

# Build artifacts
/public/build
/public/hot
/public/storage

# Local environment files
.env
.env.local
.env.*.local
.env.backup

# Testing
.env.testing
.env.ci
/coverage
/.phpunit.cache
/phpunit.xml
/phpunit.ci.xml
/tests

# Development tools
.editorconfig
.styleci.yml
compose.dev.yml
Makefile

# Documentation
*.md
!README.md
CLAUDE.md

# Cache and logs
/storage/app/*
!/storage/app/.gitignore
!/storage/app/public
/storage/framework/cache/*
!/storage/framework/cache/.gitignore
/storage/framework/sessions/*
!/storage/framework/sessions/.gitignore
/storage/framework/views/*
!/storage/framework/views/.gitignore
/storage/logs/*
!/storage/logs/.gitignore
/storage/clockwork
/storage/pail

# Laravel specific
/bootstrap/cache/*.php

# Other
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
Thumbs.db


================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2

[compose.{yml,dev.yml}]
indent_size = 4


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php

/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore


================================================
FILE: .githooks/pre-commit
================================================
#!/bin/sh
composer lint
composer test


================================================
FILE: .github/ISSUE_TEMPLATE/1-bug_report.yml
================================================
name: Bug report
description: Report a problem you're experiencing with Relaticle
labels: ["bug", "unconfirmed"]
projects: ["Relaticle/1"]
body:
  - type: markdown
    attributes:
      value: |
        Before opening a bug report, please search the existing issues (both open and closed).

        ---

        Thank you for taking the time to file a bug report. To address this bug as fast as possible, we need some information.

  - type: input
    id: relaticle-version
    attributes:
      label: Relaticle Version
      description: What version of Relaticle are you running?
      placeholder: v2.0.8
    validations:
      required: true

  - type: input
    id: php-version
    attributes:
      label: PHP Version
      description: What PHP version are you using?
      placeholder: 8.4.16
    validations:
      required: true

  - type: dropdown
    id: database
    attributes:
      label: Database
      description: Which database are you using?
      options:
        - PostgreSQL 17+
        - Other
    validations:
      required: true

  - type: dropdown
    id: deployment
    attributes:
      label: Deployment Method
      description: How are you running Relaticle?
      options:
        - Laravel Herd (local)
        - Docker (compose.yml)
        - Manual installation
        - Other

  - type: textarea
    id: description
    attributes:
      label: Problem description
      description: What happened when you experienced the problem?
    validations:
      required: true

  - type: textarea
    id: expectation
    attributes:
      label: Expected behavior
      description: What did you expect to happen instead?
    validations:
      required: true

  - type: textarea
    id: steps
    attributes:
      label: Steps to reproduce
      description: |
        Which steps do we need to take to reproduce the problem?
        Any code examples need to be **as short as possible**, remove any code that is unrelated to the bug.
      placeholder: |
        1. Go to '...'
        2. Click on '...'
        3. Scroll down to '...'
        4. See error
    validations:
      required: true

  - type: textarea
    id: logs
    attributes:
      label: Relevant log output
      description: If applicable, provide relevant log output from `storage/logs/laravel.log` or browser console. No need for backticks here.
      render: shell

  - type: checkboxes
    id: terms
    attributes:
      label: Code of Conduct
      description: By submitting this issue, you agree to follow our Code of Conduct
      options:
        - label: I agree to follow this project's Code of Conduct
          required: true


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Feature request or idea
    url: https://github.com/Relaticle/relaticle/discussions/new?category=ideas
    about: Share ideas for new features or improvements
  - name: Support question
    url: https://github.com/Relaticle/relaticle/discussions/new?category=q-a
    about: Ask the community for help
  - name: Discord Community
    url: https://discord.gg/jSfdU9zxTt
    about: Join our Discord server for quick help and community chat


================================================
FILE: .github/copilot-instructions.md
================================================
# Relaticle Code Review Guidelines

## Repository Context

Multi-tenant SaaS CRM with paying customers. Tenant isolation is the highest-priority concern — a single cross-tenant data leak is a critical security incident. The app uses Filament panels with a per-request `TeamScope` global scope applied via middleware, not in model boot. `Model::unguard()` is enabled globally.

Stack: PHP 8.4, Laravel 12, Filament 5, Livewire 4, Pest 4, Tailwind CSS 4.

CI enforces: PHPStan level 7, Pint formatting, Rector, 99.9% type coverage, full test suite. CI does **not** enforce: code coverage percentage, mutation testing, or required reviewer count.

## Tenant Isolation — Flag These

This app scopes data via `ApplyTenantScopes` middleware which registers `TeamScope` on: Company, People, Opportunity, Task, Note. Scoping happens per-request inside the Filament panel. Code running outside that middleware context (jobs, commands, API routes) has no automatic tenant filter.

Flag any of these patterns:

- `DB::table()` or `DB::select()` on a team-scoped table without a `WHERE team_id` clause
- `withoutGlobalScopes()` that removes all scopes instead of only `SoftDeletingScope`
- New Eloquent model on a team-scoped table missing the `HasTeam` trait
- New model with `HasTeam` not added to `ApplyTenantScopes` middleware
- New routes, Livewire components, or jobs that query team-scoped models without ensuring tenant context
- Queries using `->toBase()` which strips all Eloquent scopes

```php
// Correct: only strips soft delete scope, TeamScope remains active
return parent::getEloquentQuery()
    ->withoutGlobalScopes([SoftDeletingScope::class]);

// Dangerous: strips ALL scopes including TeamScope
return parent::getEloquentQuery()
    ->withoutGlobalScopes();
```

## Authorization — Flag These

Policies exist for Company, People, Opportunity, Task, Note. They check `$user->belongsToTeam($record->team)`.

- New controller action or Livewire method without `$this->authorize()` or policy check
- New Filament resource without a corresponding policy
- Livewire actions that modify records without verifying the record belongs to the current team
- Mass assignment from user-supplied request data — `Model::unguard()` is global, so `$fillable` is the only guard

```php
// Correct: authorize before acting
public function delete(string $id): void
{
    $record = Company::findOrFail($id);
    $this->authorize('delete', $record);
    $record->delete();
}

// Dangerous: no authorization, any authenticated user can delete any record
public function delete(string $id): void
{
    Company::findOrFail($id)->delete();
}
```

## Data Safety — Flag These

- Raw SQL with interpolated variables instead of parameter bindings (`?`)
- `DB::table()->upsert()` or `DB::table()->insert()` on team-scoped tables without a `team_id` in the data payload
- Export logic that doesn't filter data rows by `team_id`
- New public routes without auth middleware
- File uploads without MIME type and size validation
- `env()` calls outside of `config/` files

```php
// Correct: parameterized binding
DB::select('SELECT * FROM companies WHERE team_id = ?', [$teamId]);

// Dangerous: interpolated variable in SQL
DB::select("SELECT * FROM companies WHERE team_id = {$teamId}");
```

## Test Coverage — Flag These

New features or modified behavior should include corresponding Pest tests. There is no coverage gate in CI, so this must be caught in review.

- New Filament resource, Livewire component, or controller action without tests
- Modified business logic without updated tests
- Tests that only check the happy path — also cover validation failures and authorization denials
- Tests that create records without scoping to a specific team (relying on implicit scope rather than explicit `->for($team)`)

## PHP Standards

- Every file: `declare(strict_types=1);`
- Typed properties, explicit return types (including `void`), parameter type hints
- Constructor property promotion: `public function __construct(private UserService $service) {}`
- No empty zero-parameter constructors
- Short nullable: `?string` not `string|null`
- Always use curly braces, even single-line bodies
- PHPDoc over inline comments; only comment genuinely complex logic
- Enum keys: TitleCase (`FavoritePerson`, `Monthly`)

## Code Style

- Happy path last — handle errors first, return early
- Avoid `else` — use early returns
- String interpolation over concatenation
- Descriptive names: `$failedChecks` not `$checks` with a comment

## Laravel Conventions

- `Model::query()` not `DB::` for team-scoped data
- Eager load relationships to prevent N+1
- Form Request classes for validation, not inline
- `config()` not `env()` outside config files
- Named routes with `route()`
- Policies and gates for authorization
- Queued jobs with `ShouldQueue` for expensive operations
- `casts()` method, not `$casts` property
- Middleware in `bootstrap/app.php`, not a Kernel class
- **PostgreSQL exclusively** — no SQLite/MySQL compatibility layers, driver checks, or conditional SQL
- Migrations: only `up()` methods — no `down()` methods

## Filament 5

- Form fields: `Filament\Forms\Components\`
- Layout (Grid, Section, Tabs): `Filament\Schemas\Components\`
- Infolist entries: `Filament\Infolists\Components\`
- Utilities (Get, Set): `Filament\Schemas\Components\Utilities\`
- All actions: `Filament\Actions\` — no `Filament\Tables\Actions\`
- Icons: `Heroicon` enum, not strings
- File visibility: `private` by default
- `Grid`, `Section`, `Fieldset` no longer span all columns by default
- `deferFilters()` is now the default table behavior

## Livewire 4

- `wire:model` is deferred by default; `wire:model.live` for real-time
- Namespace: `App\Livewire`
- Events: `$this->dispatch()`
- Validate and authorize in actions
- `wire:key` in loops

## Testing

- All tests use Pest with factories and factory states
- `mutates(ClassName::class)` to declare coverage intent
- Named assertions: `assertForbidden()` not `assertStatus(403)`
- Datasets for repetitive validation tests

## Tailwind CSS 4

- No deprecated utilities: `bg-opacity-*` is `bg-black/*`, `flex-shrink-*` is `shrink-*`
- Gap utilities for spacing, not margins between siblings
- `dark:` variants when existing components support dark mode
- CSS-first config with `@theme`, not `tailwind.config.js`


================================================
FILE: .github/workflows/docker-publish.yml
================================================
name: Build and Push Docker Image

on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  DOCKERHUB_IMAGE: manukminasyan/relaticle

jobs:
  build:
    runs-on: ${{ matrix.runner }}
    permissions:
      contents: read
      packages: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm

    steps:
      - name: Prepare
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
          echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV

      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Log in to Docker Hub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
            ${{ env.DOCKERHUB_IMAGE }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix=
            type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}

      - name: Build and push by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          target: production
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.meta.outputs.labels }}
          tags: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
            ${{ env.DOCKERHUB_IMAGE }}
          cache-from: type=gha,scope=${{ matrix.platform }}
          cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
          outputs: ${{ github.event_name != 'pull_request' && 'type=image,push-by-digest=true,name-canonical=true,push=true' || '' }}

      - name: Export digest
        if: github.event_name != 'pull_request'
        run: |
          mkdir -p ${{ runner.temp }}/digests
          digest="${{ steps.build.outputs.digest }}"
          touch "${{ runner.temp }}/digests/${digest#sha256:}"

      - name: Upload digest
        if: github.event_name != 'pull_request'
        uses: actions/upload-artifact@v4
        with:
          name: digests-${{ env.PLATFORM_PAIR }}
          path: ${{ runner.temp }}/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    runs-on: ubuntu-latest
    if: github.event_name != 'pull_request'
    needs: build
    permissions:
      contents: read
      packages: write

    steps:
      - name: Prepare
        run: echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV

      - name: Download digests
        uses: actions/download-artifact@v4
        with:
          path: ${{ runner.temp }}/digests
          pattern: digests-*
          merge-multiple: true

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Extract metadata for GHCR
        id: meta-ghcr
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix=
            type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}

      - name: Extract metadata for Docker Hub
        id: meta-dockerhub
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.DOCKERHUB_IMAGE }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix=
            type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}

      - name: Create manifest list and push to GHCR
        working-directory: ${{ runner.temp }}/digests
        env:
          DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta-ghcr.outputs.json }}
        run: |
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)

      - name: Create manifest list and push to Docker Hub
        working-directory: ${{ runner.temp }}/digests
        env:
          DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta-dockerhub.outputs.json }}
        run: |
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf '${{ env.DOCKERHUB_IMAGE }}@sha256:%s ' *)

      - name: Inspect GHCR image
        run: |
          docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta-ghcr.outputs.version }}

      - name: Inspect Docker Hub image
        run: |
          docker buildx imagetools inspect ${{ env.DOCKERHUB_IMAGE }}:${{ steps.meta-dockerhub.outputs.version }}


================================================
FILE: .github/workflows/filament-view-monitor-simple.yml
================================================
name: Monitor Filament View Updates (Simple)

on:
  schedule:
    # Run daily at 9 AM UTC
    - cron: '0 9 * * *'
  workflow_dispatch: # Allow manual trigger

jobs:
  check-filament-updates:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
          coverage: none

      - name: Install dependencies
        run: composer install --no-interaction --no-progress

      - name: Check for Filament view changes
        id: check
        run: |
          # Define the files we're monitoring
          FILES=(
            "vendor/filament/filament/resources/views/components/layout/index.blade.php"
            "vendor/filament/filament/resources/views/livewire/topbar.blade.php"
          )

          # Calculate hash of current files
          CURRENT_HASH=""
          for FILE in "${FILES[@]}"; do
            if [ -f "$FILE" ]; then
              CURRENT_HASH="${CURRENT_HASH}$(sha256sum "$FILE" | cut -d' ' -f1)"
            fi
          done

          # Hash the combined hashes
          FINAL_HASH=$(echo -n "$CURRENT_HASH" | sha256sum | cut -d' ' -f1)

          echo "Current hash: $FINAL_HASH"

          # Compare with stored hash
          HASH_FILE=".github/filament-views-hash.txt"

          if [ -f "$HASH_FILE" ]; then
            STORED_HASH=$(cat "$HASH_FILE")
            echo "Stored hash: $STORED_HASH"

            if [ "$FINAL_HASH" != "$STORED_HASH" ]; then
              echo "changes_detected=true" >> $GITHUB_OUTPUT
              echo "🔔 Filament views have changed!"

              # Update the hash file
              echo "$FINAL_HASH" > "$HASH_FILE"
            else
              echo "changes_detected=false" >> $GITHUB_OUTPUT
              echo "✅ No changes detected"
            fi
          else
            # First run - save the hash
            echo "$FINAL_HASH" > "$HASH_FILE"
            echo "changes_detected=false" >> $GITHUB_OUTPUT
            echo "📝 Initial hash saved"
          fi

      - name: Get Filament version
        id: version
        if: steps.check.outputs.changes_detected == 'true'
        run: |
          VERSION=$(composer show filament/filament | grep "versions" | cut -d':' -f2 | xargs)
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: Create issue notification
        if: steps.check.outputs.changes_detected == 'true'
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const today = new Date().toISOString().split('T')[0];

            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: `🔔 Filament Views Updated - ${today}`,
              body: `## Filament view files have been updated!

            **Filament Version:** ${{ steps.version.outputs.version }}
            **Date:** ${today}

            The following Filament view files that you've published have been updated in the package:
            - \`components/layout/index.blade.php\`
            - \`livewire/topbar.blade.php\`

            ### What to do:
            1. Check the [Filament changelog](https://github.com/filamentphp/filament/releases)
            2. Review what changed in the views
            3. Decide if you need to update your published versions

            ### How to review changes:
            \`\`\`bash
            # Compare your published views with the vendor versions
            diff -u resources/views/vendor/filament-panels/components/layout/index.blade.php \\
                    vendor/filament/filament/resources/views/components/layout/index.blade.php

            diff -u resources/views/vendor/filament-panels/livewire/topbar.blade.php \\
                    vendor/filament/filament/resources/views/livewire/topbar.blade.php
            \`\`\``,
              labels: ['filament-update', 'vendor-views']
            });

            console.log('✅ Issue created for Filament view updates');

      - name: Commit hash update
        if: steps.check.outputs.changes_detected == 'true'
        run: |
          git config --local user.email "github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"
          git add .github/filament-views-hash.txt
          git diff --staged --quiet || git commit -m "Update Filament views hash [skip ci]"
          git push


================================================
FILE: .github/workflows/tests.yml
================================================
name: Tests

on: [push]

jobs:
  lint-and-static-analysis:
    runs-on: ubuntu-latest
    name: Code Quality Checks

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Cache Dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.composer/cache
            vendor
          key: ${{ runner.os }}-php-8.4-composer-${{ hashFiles('composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-php-8.4-composer-

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.4
          extensions: json, dom, curl, libxml, mbstring, zip
          tools: composer:v2

      - name: Install PHP dependencies
        run: composer install --no-interaction --no-progress --ansi --prefer-dist --optimize-autoloader

      - name: Prepare Laravel Application
        run: |
          cp .env.ci .env
          php artisan key:generate

      - name: Run Lint
        run: composer test:lint

      - name: Run Refactor Check
        run: composer test:refactor

      - name: Run Type Coverage
        run: composer test:type-coverage

      - name: Run Static Analysis
        run: composer test:types

      - name: Architecture Tests
        run: composer test:arch

  tests:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        php: [8.4]
        shard: [1, 2, 3, 4, 5]

    name: Tests (Shard ${{ matrix.shard }}/5)

    services:
      postgres:
        image: postgres:alpine
        env:
          POSTGRES_DB: relaticle_testing
          POSTGRES_PASSWORD: postgres
          POSTGRES_PORT: 5432
          POSTGRES_USER: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Cache Dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.composer/cache
            vendor
          key: ${{ runner.os }}-php-8.4-composer-${{ hashFiles('composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-php-8.4-composer-

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: json, dom, curl, libxml, mbstring, zip
          tools: composer:v2
          coverage: none

      - name: Set up Node & NPM
        uses: actions/setup-node@v5
        with:
          node-version: '22.x'

      - name: Setup Problem Matches
        run: |
          echo "::add-matcher::${{ runner.tool_cache }}/php.json"
          echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

      - name: Install PHP dependencies
        run: composer install --no-interaction --no-progress --ansi --prefer-dist --optimize-autoloader

      - name: Get NPM cache directory
        id: npm-cache-dir
        shell: bash
        run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

      - name: Cache dependencies
        id: npm-cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.npm-cache-dir.outputs.dir }}
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm ci

      - name: Build dependencies
        run: npm run build

      - name: Prepare Laravel
        run: |
          cp .env.ci .env
          php artisan key:generate

      - name: Tests
        run: composer test:pest:ci
        env:
          SHARD: ${{ matrix.shard }}/5

  browser-tests:
    runs-on: ubuntu-latest
    name: Browser Tests

    services:
      postgres:
        image: postgres:alpine
        env:
          POSTGRES_DB: relaticle_testing
          POSTGRES_PASSWORD: postgres
          POSTGRES_PORT: 5432
          POSTGRES_USER: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Cache Dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.composer/cache
            vendor
          key: ${{ runner.os }}-php-8.4-composer-${{ hashFiles('composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-php-8.4-composer-

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.4
          extensions: json, dom, curl, libxml, mbstring, zip
          tools: composer:v2
          coverage: none

      - name: Set up Node & NPM
        uses: actions/setup-node@v5
        with:
          node-version: '22.x'

      - name: Install PHP dependencies
        run: composer install --no-interaction --no-progress --ansi --prefer-dist --optimize-autoloader

      - name: Get NPM cache directory
        id: npm-cache-dir
        shell: bash
        run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

      - name: Cache NPM dependencies
        uses: actions/cache@v4
        with:
          path: ${{ steps.npm-cache-dir.outputs.dir }}
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Prepare Laravel
        run: |
          cp .env.ci .env
          php artisan key:generate

      - name: Install NPM dependencies
        run: npm ci

      - name: Build assets
        run: npm run build

      - name: Install Playwright
        run: npx playwright install --with-deps chromium

      - name: Browser Tests
        run: vendor/bin/pest tests/Browser/ --configuration phpunit.ci.xml


================================================
FILE: .gitignore
================================================
.DS_Store
.superpowers
/.phpunit.cache
.scribe
/node_modules
/public/build
/public/hot
/public/storage
/public/sitemap.xml
/storage/*.key
/vendor
.env
.env.backup
.env.production
.phpactor.json
.phpunit.result.cache
/coverage-html/
coverage.xml
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
AGENTS.md
boost.json
.mcp.json
/.ai/*
!/.ai/guidelines/
/.ai/guidelines/*
!/.ai/guidelines/relaticle/
/.github/skills
/.fleet
/.idea
/.vscode
/.claude
/.superset
/.cursor
/.junie
/.playwright-mcp
/docs
api.json
.scribe/
/public/vendor/scribe
/resources/views/scribe
/storage/app/scribe
/tests/Feature/Scribe
.context
polyscope.json
/bin/setup-preview.sh
.gstack/


================================================
FILE: CLAUDE.md
================================================
<laravel-boost-guidelines>
=== .ai/core rules ===

# Project

This is production code for a commercial SaaS product with paying customers.
Bugs directly impact revenue and user trust.

Treat every change like it's going through senior code review:

- No lazy shortcuts or placeholder code
- Handle errors and edge cases properly
- Write code that won't embarrass you in 6 months

## Database

- This project uses **PostgreSQL exclusively** — do not add SQLite/MySQL compatibility layers, driver checks, or conditional SQL
- Migrations must only have `up()` methods — do not write `down()` methods

## Pre-Commit Quality Checks

Before committing any changes, always run these checks in order:

1. `vendor/bin/pint --dirty --format agent` — fix code style
2. `vendor/bin/rector --dry-run` — if rector suggests changes, apply them with `vendor/bin/rector`
3. `vendor/bin/phpstan analyse` — ensure no new static analysis errors
4. `composer test:type-coverage` — ensure type coverage stays at or above 99.9%
5. `php artisan test --compact` — run relevant tests (use `--filter` for targeted runs)

Do not add new PHPStan errors to the baseline without approval. All parameters and return types must be explicitly typed — untyped closures/parameters will fail type coverage in CI.

## Icons (Remix Icon)

- **Brand/social icons** (GitHub, Discord, Twitter, LinkedIn) → always `fill` variant
- **UI/functional icons** (arrows, chevrons, checks, close) → always `line` variant
- **Feature/section icons** → `line` variant, stay consistent within a section
- **Status/emphasis icons** (success checkmarks, alerts) → `fill` variant

## Scheduling

- All scheduled commands go in `bootstrap/app.php` via `withSchedule()` — not in `routes/console.php`

## Actions

- All write operations (create, update, delete) must go through action classes in `app/Actions/` -- never inline business logic in controllers, MCP tools, Livewire components, or Filament resources
- Actions are the single source of truth for business logic and side effects (notifications, syncs, etc.)
- Filament CRUD may use native `CreateAction`/`EditAction` when the action only does `Model::create()`/`->update()` with no extra logic -- but side effects (e.g., notifications) must still be triggered via `->after()` hooks calling the appropriate action
- When reviewing or refactoring code, extract inline business logic into action classes

## Testing

- Do not write isolated unit tests for action classes, services, or similar internal code -- test them through their real entry points (API endpoints, Filament resources, Livewire components). Unit tests for internal classes create maintenance burden without catching real bugs.
- Use `mutates(ClassName::class)` in test files to declare which source classes each test covers
- Run mutation testing per-class: `php -d xdebug.mode=coverage vendor/bin/pest --mutate --class='App\MyClass' tests/path/`
- No enforced `--min` threshold — use mutation testing as a code review tool, not a CI gate
- Use `$this->travelTo()` in tests that depend on day-of-week or weekly intervals to avoid flaky boundary failures

## Custom Fields

- Models using the `UsesCustomFields` trait handle `custom_fields` automatically — do NOT manually extract, strip, or call `saveCustomFields()` in actions
- The trait merges `'custom_fields'` into `$fillable`, intercepts it during `saving`, and persists values during `saved` — just pass `custom_fields` through in the `$data` array to `create()`/`update()`
- Tenant context for the custom-fields package is set in `SetApiTeamContext` middleware via `TenantContextService::setTenantId()` — actions don't need `withTenant()` wrappers
- In Filament, the package's own `SetTenantContextMiddleware` handles tenant context — no action-level code needed there either
- `CustomFieldValidationService` intentionally uses explicit `where('tenant_id', ...)` with `withoutGlobalScopes()` — this is defensive and correct, don't change it to rely on ambient state

=== .ai/v4 rules ===

## Filament 4

### Important Version 4 Changes

- File visibility is now `private` by default.
- The `deferFilters` method from Filament v3 is now the default behavior in Filament v4, so users must click a button before the filters are applied to the table. To disable this behavior, you can use the `deferFilters(false)` method.
- The `Grid`, `Section`, and `Fieldset` layout components no longer span all columns by default.
- The `all` pagination page method is not available for tables by default.
- All action classes extend `Filament\Actions\Action`. No action classes exist in `Filament\Tables\Actions`.
- The `Form` & `Infolist` layout components have been moved to `Filament\Schemas\Components`, for example `Grid`, `Section`, `Fieldset`, `Tabs`, `Wizard`, etc.
- A new `Repeater` component for Forms has been added.
- Icons now use the `Filament\Support\Icons\Heroicon` Enum by default. Other options are available and documented.

### Organize Component Classes Structure

- Schema components: `Schemas/Components/`
- Table columns: `Tables/Columns/`
- Table filters: `Tables/Filters/`
- Actions: `Actions/`

### Form Components in v4

- Use `Filament\Forms\Components` for form fields like TextInput, Select, Textarea, etc.
- Use `Filament\Schemas\Components` for layout components like Grid, Section, Fieldset, Tabs, Wizard.

### Actions in v4

```php
use Filament\Actions\Action;

Action::make('send')
    ->label('Send Email')
    ->icon(Heroicon::OutlinedPaperAirplane)
    ->requiresConfirmation()
    ->action(fn (Model $record) => $record->sendEmail());
```

### Table Actions in v4

```php
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;

public static function table(Table $table): Table
{
    return $table
        ->actions([
            EditAction::make(),
            DeleteAction::make(),
            Action::make('approve')
                ->action(fn (Model $record) => $record->approve()),
        ]);
}
```

### Icons in v4

```php
use Filament\Support\Icons\Heroicon;

// Instead of string icons
->icon(Heroicon::OutlinedHome)
->icon(Heroicon::SolidUser)
```

### Testing Filament 4 Resources

```php
use function Pest\Livewire\livewire;

it('can list records', function () {
    $records = Model::factory()->count(5)->create();

    livewire(ListModels::class)
        ->assertCanSeeTableRecords($records);
});

it('can create a record', function () {
    livewire(CreateModel::class)
        ->fillForm([
            'name' => 'Test Name',
        ])
        ->call('create')
        ->assertHasNoFormErrors();

    expect(Model::query()->where('name', 'Test Name')->exists())->toBeTrue();
});

it('can edit a record', function () {
    $record = Model::factory()->create();

    livewire(EditModel::class, ['record' => $record->getRouteKey()])
        ->fillForm([
            'name' => 'Updated Name',
        ])
        ->call('save')
        ->assertHasNoFormErrors();

    expect($record->refresh()->name)->toBe('Updated Name');
});
```

=== foundation rules ===

# Laravel Boost Guidelines

The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to ensure the best experience when building Laravel applications.

## Foundational Context

This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.

- php - 8.4
- filament/filament (FILAMENT) - v5
- laravel/fortify (FORTIFY) - v1
- laravel/framework (LARAVEL) - v12
- laravel/horizon (HORIZON) - v5
- laravel/mcp (MCP) - v0
- laravel/prompts (PROMPTS) - v0
- laravel/sanctum (SANCTUM) - v4
- laravel/socialite (SOCIALITE) - v5
- livewire/livewire (LIVEWIRE) - v4
- larastan/larastan (LARASTAN) - v3
- laravel/boost (BOOST) - v2
- laravel/pail (PAIL) - v1
- laravel/pint (PINT) - v1
- laravel/sail (SAIL) - v1
- pestphp/pest (PEST) - v4
- phpunit/phpunit (PHPUNIT) - v12
- rector/rector (RECTOR) - v2
- tailwindcss (TAILWINDCSS) - v4

## Skills Activation

This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.

- `laravel-best-practices` — Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization and security patterns, validation, error handling, queue and job configuration, route definitions, and architectural decisions. Also use for Laravel code reviews and refactoring existing Laravel code to follow best practices. Covers any task involving Laravel backend PHP code patterns.
- `configuring-horizon` — Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing Horizon (horizon:install, Sail setup), configuring config/horizon.php (supervisor blocks, queue assignments, balancing strategies, minProcesses/maxProcesses), fixing the dashboard (authorization via Gate::define viewHorizon, blank metrics, horizon:snapshot scheduling), and troubleshooting production issues (worker crashes, timeout chain ordering, LongWaitDetected notifications, waits config). Also covers job tagging and silencing. Do not use for generic Laravel queues without Horizon, SQS or database drivers, standalone Redis setup, Linux supervisord, Telescope, or job batching.
- `mcp-development` — Use this skill for Laravel MCP development only. Trigger when creating or editing MCP tools, resources, prompts, or servers in Laravel projects. Covers: artisan make:mcp-* generators, mcp:inspector, routes/ai.php, Tool/Resource/Prompt classes, schema validation, shouldRegister(), OAuth setup, URI templates, read-only attributes, and MCP debugging. Do not use for non-Laravel MCP projects or generic AI features without MCP.
- `socialite-development` — Manages OAuth social authentication with Laravel Socialite. Activate when adding social login providers; configuring OAuth redirect/callback flows; retrieving authenticated user details; customizing scopes or parameters; setting up community providers; testing with Socialite fakes; or when the user mentions social login, OAuth, Socialite, or third-party authentication.
- `livewire-development` — Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire.
- `pest-testing` — Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code.
- `tailwindcss-development` — Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS.
- `custom-fields-development` — Adds dynamic custom fields to Eloquent models without migrations using Filament integration. Use when adding the UsesCustomFields trait to models, integrating custom fields in Filament forms/tables/infolists, configuring field types, working with field validation, or managing feature flags for conditional visibility, encryption, and multi-tenancy.
- `flowforge-development` — Builds Kanban board interfaces for Eloquent models with drag-and-drop functionality. Use when creating board pages, configuring columns and cards, implementing drag-and-drop positioning, working with Filament board pages or standalone Livewire boards, or troubleshooting position-related issues.
- `laravel-query-builder` — Build filtered, sorted, and included API endpoints using spatie/laravel-query-builder. Activates when working with QueryBuilder, AllowedFilter, AllowedSort, AllowedInclude, or when the user mentions query parameters, API filtering, sorting, includes, or spatie/laravel-query-builder.
- `spatie-laravel-php-standards` — Apply Spatie's Laravel and PHP coding standards for any task that creates, edits, reviews, refactors, or formats Laravel/PHP code or Blade templates; use for controllers, Eloquent models, routes, config, validation, migrations, tests, and related files to align with Laravel conventions and PSR-12.

## Conventions

- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, and naming.
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
- Check for existing components to reuse before writing a new one.

## Verification Scripts

- Do not create verification scripts or tinker when tests cover that functionality and prove they work. Unit and feature tests are more important.

## Application Structure & Architecture

- Stick to existing directory structure; don't create new base folders without approval.
- Do not change the application's dependencies without approval.

## Frontend Bundling

- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them.

## Documentation Files

- You must only create documentation files if explicitly requested by the user.

## Replies

- Be concise in your explanations - focus on what's important rather than explaining obvious details.

=== boost rules ===

# Laravel Boost

## Tools

- Laravel Boost is an MCP server with tools designed specifically for this application. Prefer Boost tools over manual alternatives like shell commands or file reads.
- Use `database-query` to run read-only queries against the database instead of writing raw SQL in tinker.
- Use `database-schema` to inspect table structure before writing migrations or models.
- Use `get-absolute-url` to resolve the correct scheme, domain, and port for project URLs. Always use this before sharing a URL with the user.
- Use `browser-logs` to read browser logs, errors, and exceptions. Only recent logs are useful, ignore old entries.

## Searching Documentation (IMPORTANT)

- Always use `search-docs` before making code changes. Do not skip this step. It returns version-specific docs based on installed packages automatically.
- Pass a `packages` array to scope results when you know which packages are relevant.
- Use multiple broad, topic-based queries: `['rate limiting', 'routing rate limiting', 'routing']`. Expect the most relevant results first.
- Do not add package names to queries because package info is already shared. Use `test resource table`, not `filament 4 test resource table`.

### Search Syntax

1. Use words for auto-stemmed AND logic: `rate limit` matches both "rate" AND "limit".
2. Use `"quoted phrases"` for exact position matching: `"infinite scroll"` requires adjacent words in order.
3. Combine words and phrases for mixed queries: `middleware "rate limit"`.
4. Use multiple queries for OR logic: `queries=["authentication", "middleware"]`.

## Artisan

- Run Artisan commands directly via the command line (e.g., `php artisan route:list`). Use `php artisan list` to discover available commands and `php artisan [command] --help` to check parameters.
- Inspect routes with `php artisan route:list`. Filter with: `--method=GET`, `--name=users`, `--path=api`, `--except-vendor`, `--only-vendor`.
- Read configuration values using dot notation: `php artisan config:show app.name`, `php artisan config:show database.default`. Or read config files directly from the `config/` directory.
- To check environment variables, read the `.env` file directly.

## Tinker

- Execute PHP in app context for debugging and testing code. Do not create models without user approval, prefer tests with factories instead. Prefer existing Artisan commands over custom tinker code.
- Always use single quotes to prevent shell expansion: `php artisan tinker --execute 'Your::code();'`
  - Double quotes for PHP strings inside: `php artisan tinker --execute 'User::where("active", true)->count();'`

=== php rules ===

# PHP

- Always declare `declare(strict_types=1);` at the top of every `.php` file.
- Always use curly braces for control structures, even for single-line bodies.
- Use PHP 8 constructor property promotion: `public function __construct(public GitHub $github) { }`. Do not leave empty zero-parameter `__construct()` methods unless the constructor is private.
- Use explicit return type declarations and type hints for all method parameters: `function isAccessible(User $user, ?string $path = null): bool`
- Use TitleCase for Enum keys: `FavoritePerson`, `BestLake`, `Monthly`.
- Prefer PHPDoc blocks over inline comments. Only add inline comments for exceptionally complex logic.
- Use array shape type definitions in PHPDoc blocks.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement

- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass.
- Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test --compact` with a specific filename or filter.

=== laravel/core rules ===

# Do Things the Laravel Way

- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using `php artisan list` and check their parameters with `php artisan [command] --help`.
- If you're creating a generic PHP class, use `php artisan make:class`.
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.

### Model Creation

- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `php artisan make:model --help` to check the available options.

## APIs & Eloquent Resources

- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.

## URL Generation

- When generating links to other pages, prefer named routes and the `route()` function.

## Testing

- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
- When creating tests, make use of `php artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.

## Vite Error

- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`.

=== laravel/v12 rules ===

# Laravel 12

- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples.
- Since Laravel 11, Laravel has a new streamlined file structure which this project uses.

## Laravel 12 Structure

- In Laravel 12, middleware are no longer registered in `app/Http/Kernel.php`.
- Middleware are configured declaratively in `bootstrap/app.php` using `Application::configure()->withMiddleware()`.
- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
- `bootstrap/providers.php` contains application specific service providers.
- The `app/Console/Kernel.php` file no longer exists; use `bootstrap/app.php` or `routes/console.php` for console configuration.
- Console commands in `app/Console/Commands/` are automatically available and do not require manual registration.

## Database

- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
- Laravel 12 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.

### Models

- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.

=== livewire/core rules ===

# Livewire

- Livewire allow to build dynamic, reactive interfaces in PHP without writing JavaScript.
- You can use Alpine.js for client-side interactions instead of JavaScript frameworks.
- Keep state server-side so the UI reflects it. Validate and authorize in actions as you would in HTTP requests.

=== pint/core rules ===

# Laravel Pint Code Formatter

- If you have modified any PHP files, you must run `vendor/bin/pint --dirty --format agent` before finalizing changes to ensure your code matches the project's expected style.
- Do not run `vendor/bin/pint --test --format agent`, simply run `vendor/bin/pint --format agent` to fix any formatting issues.

=== pest/core rules ===

## Pest

- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`.
- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`.
- Do NOT delete tests without approval.

=== filament/filament rules ===

## Filament

- Filament is used by this application. Follow the existing conventions for how and where it is implemented.
- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS.
- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. If `search-docs` is unavailable, refer to https://filamentphp.com/docs.

### Artisan

- Always use Filament-specific Artisan commands to create files. Find available commands with the `list-artisan-commands` tool, or run `php artisan --help`.
- Always inspect required options before running a command, and always pass `--no-interaction`.

### Patterns

Always use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values.

Use `Get $get` to read other form field values for conditional logic:

<code-snippet name="Conditional form field visibility" lang="php">
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Utilities\Get;

Select::make('type')
    ->options(CompanyType::class)
    ->required()
    ->live(),

TextInput::make('company_name')
    ->required()
    ->visible(fn (Get $get): bool => $get('type') === 'business'),

</code-snippet>

Use `state()` with a `Closure` to compute derived column values:

<code-snippet name="Computed table column value" lang="php">
use Filament\Tables\Columns\TextColumn;

TextColumn::make('full_name')
    ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"),

</code-snippet>

Actions encapsulate a button with an optional modal form and logic:

<code-snippet name="Action with modal form" lang="php">
use Filament\Actions\Action;
use Filament\Forms\Components\TextInput;

Action::make('updateEmail')
    ->schema([
        TextInput::make('email')
            ->email()
            ->required(),
    ])
    ->action(fn (array $data, User $record) => $record->update($data))

</code-snippet>

### Testing

Always authenticate before testing panel functionality. Filament uses Livewire, so use `Livewire::test()` or `livewire()` (available when `pestphp/pest-plugin-livewire` is in `composer.json`):

<code-snippet name="Table test" lang="php">
use function Pest\Livewire\livewire;

livewire(ListUsers::class)
    ->assertCanSeeTableRecords($users)
    ->searchTable($users->first()->name)
    ->assertCanSeeTableRecords($users->take(1))
    ->assertCanNotSeeTableRecords($users->skip(1));

</code-snippet>

<code-snippet name="Create resource test" lang="php">
use function Pest\Laravel\assertDatabaseHas;
use function Pest\Livewire\livewire;

livewire(CreateUser::class)
    ->fillForm([
        'name' => 'Test',
        'email' => 'test@example.com',
    ])
    ->call('create')
    ->assertNotified()
    ->assertRedirect();

assertDatabaseHas(User::class, [
    'name' => 'Test',
    'email' => 'test@example.com',
]);

</code-snippet>

<code-snippet name="Testing validation" lang="php">
use function Pest\Livewire\livewire;

livewire(CreateUser::class)
    ->fillForm([
        'name' => null,
        'email' => 'invalid-email',
    ])
    ->call('create')
    ->assertHasFormErrors([
        'name' => 'required',
        'email' => 'email',
    ])
    ->assertNotNotified();

</code-snippet>

<code-snippet name="Calling actions in pages" lang="php">
use Filament\Actions\DeleteAction;
use function Pest\Livewire\livewire;

livewire(EditUser::class, ['record' => $user->id])
    ->callAction(DeleteAction::class)
    ->assertNotified()
    ->assertRedirect();

</code-snippet>

<code-snippet name="Calling actions in tables" lang="php">
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;

livewire(ListUsers::class)
    ->callAction(TestAction::make('promote')->table($user), [
        'role' => 'admin',
    ])
    ->assertNotified();

</code-snippet>

### Correct Namespaces

- Form fields (`TextInput`, `Select`, etc.): `Filament\Forms\Components\`
- Infolist entries (`TextEntry`, `IconEntry`, etc.): `Filament\Infolists\Components\`
- Layout components (`Grid`, `Section`, `Fieldset`, `Tabs`, `Wizard`, etc.): `Filament\Schemas\Components\`
- Schema utilities (`Get`, `Set`, etc.): `Filament\Schemas\Components\Utilities\`
- Actions (`DeleteAction`, `CreateAction`, etc.): `Filament\Actions\`. Never use `Filament\Tables\Actions\`, `Filament\Forms\Actions\`, or any other sub-namespace for actions.
- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`)

### Common Mistakes

- **Never assume public file visibility.** File visibility is `private` by default. Always use `->visibility('public')` when public access is needed.
- **Never assume full-width layout.** `Grid`, `Section`, and `Fieldset` do not span all columns by default. Explicitly set column spans when needed.

=== spatie/boost-spatie-guidelines rules ===

# Project Coding Guidelines

- This codebase follows Spatie's Laravel & PHP guidelines.
- Always activate the `spatie-laravel-php-standards` skill whenever writing, editing, reviewing, or formatting Laravel or PHP code.

</laravel-boost-guidelines>


================================================
FILE: Dockerfile
================================================
# syntax=docker/dockerfile:1

###########################################
# Stage 1: Composer dependencies
###########################################
FROM composer:2 AS composer

WORKDIR /app

COPY composer.json composer.lock ./
RUN composer install \
    --no-dev \
    --no-interaction \
    --no-scripts \
    --no-autoloader \
    --prefer-dist \
    --ignore-platform-reqs

###########################################
# Stage 2: Build frontend assets
###########################################
FROM node:22-alpine AS frontend

WORKDIR /app

# Copy package files and install
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts

# Copy source files needed for build
COPY vite.config.js ./
COPY resources ./resources
COPY public ./public
COPY packages ./packages

# Copy vendor for Filament theme CSS
COPY --from=composer /app/vendor ./vendor

RUN npm run build

###########################################
# Stage 3: Production image
###########################################
FROM serversideup/php:8.4-fpm-nginx AS production

LABEL org.opencontainers.image.title="Relaticle CRM"
LABEL org.opencontainers.image.description="Modern, open-source CRM platform"
LABEL org.opencontainers.image.source="https://github.com/Relaticle/relaticle"

# Switch to root to install dependencies
USER root

# Install required PHP extensions
RUN install-php-extensions intl exif gd imagick bcmath

# Install PostgreSQL client for health checks
RUN apt-get update \
    && apt-get install -y --no-install-recommends postgresql-client \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Switch back to www-data
USER www-data

WORKDIR /var/www/html

# Copy application source
COPY --chown=www-data:www-data . .

# Copy vendor from composer stage
COPY --chown=www-data:www-data --from=composer /app/vendor ./vendor

# Copy built frontend assets
COPY --chown=www-data:www-data --from=frontend /app/public/build ./public/build

# Generate optimized autoloader
RUN composer dump-autoload --optimize --no-dev

# Create storage directories
RUN mkdir -p \
    storage/app/public \
    storage/framework/cache/data \
    storage/framework/sessions \
    storage/framework/views \
    storage/logs \
    bootstrap/cache

# Default environment for serversideup/php Laravel automations
ENV AUTORUN_ENABLED=true
ENV AUTORUN_LARAVEL_STORAGE_LINK=true
ENV AUTORUN_LARAVEL_MIGRATION=true
ENV AUTORUN_LARAVEL_MIGRATION_ISOLATION=true
ENV AUTORUN_LARAVEL_CONFIG_CACHE=true
ENV AUTORUN_LARAVEL_ROUTE_CACHE=true
ENV AUTORUN_LARAVEL_VIEW_CACHE=true
ENV AUTORUN_LARAVEL_EVENT_CACHE=true
ENV AUTORUN_LARAVEL_OPTIMIZE=false
ENV PHP_OPCACHE_ENABLE=1
ENV SSL_MODE=off

EXPOSE 8080


================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.


================================================
FILE: README.md
================================================
<p align="center">
  <a href="https://relaticle.com">
    <img src="https://relaticle.com/brand/logomark.svg" width="100px" alt="Relaticle logo" />
  </a>
</p>

<h1 align="center">The Open-Source CRM Built for AI Agents</h1>

<p align="center">
  <a href="https://github.com/Relaticle/relaticle/actions"><img src="https://img.shields.io/github/actions/workflow/status/Relaticle/relaticle/tests.yml?branch=main&style=for-the-badge&label=tests" alt="Tests"></a>
  <a href="https://relaticle.com/docs/mcp"><img src="https://img.shields.io/badge/MCP_Tools-30-8A2BE2?style=for-the-badge" alt="30 MCP Tools"></a>
  <a href="https://laravel.com/docs/12.x"><img src="https://img.shields.io/badge/Laravel-12.x-FF2D20?style=for-the-badge&logo=laravel" alt="Laravel 12"></a>
  <a href="https://php.net"><img src="https://img.shields.io/badge/PHP-8.4-777BB4?style=for-the-badge&logo=php" alt="PHP 8.4"></a>
  <a href="https://github.com/Relaticle/relaticle/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg?style=for-the-badge" alt="License"></a>
</p>

<p align="center">
  <a href="https://relaticle.com">Website</a> ·
  <a href="https://relaticle.com/docs">Documentation</a> ·
  <a href="https://relaticle.com/docs/mcp">MCP Server</a> ·
  <a href="https://github.com/orgs/Relaticle/projects/1/views/1">Roadmap</a> ·
  <a href="https://github.com/Relaticle/relaticle/discussions">Discussions</a>
</p>

<p align="center">
  <img src="https://relaticle.com/images/github-preview-light.png?v=3" alt="Relaticle Dashboard - Manage contacts, companies, and opportunities in a modern interface" />
  <br>
  <sub>Clean, modern interface built with Filament 5 and Livewire 4</sub>
</p>

---

# About Relaticle

Relaticle is a self-hosted CRM with a production-grade MCP server. Connect any AI agent -- Claude, GPT, or open-source models -- with 30 tools for full CRM operations. 22 custom field types, REST API, and multi-team isolation.

**Perfect for:** Developer-led teams, AI-forward startups, and SMBs who want AI agent integration without vendor lock-in.

**Core Strengths:**

- **Agent-Native Infrastructure** - MCP server with 30 tools, REST API with full CRUD, schema discovery for AI agents
- **Customizable Data Model** - 22 field types including entity relationships, conditional visibility, and per-field encryption. No migrations needed.
- **Multi-Team Isolation** - 5-layer authorization with team-scoped data and workspaces
- **Modern Tech Stack** - Laravel 12, Filament 5, PHP 8.4, 1,100+ automated tests
- **Privacy-First** - Self-hosted, AGPL-3.0, your data stays on your server

**vs Other CRMs:**

| | Self-Hosted | Open Source | MCP Tools | Custom Fields | Per-Seat Pricing |
|---|---|---|---|---|---|
| **Relaticle** | Yes | AGPL-3.0 | 30 | 22 types | No |
| **HubSpot** | No | No | 9 | Limited | Yes |
| **Salesforce** | No | No | 0 | Yes (complex) | Yes |
| **Attio** | No | No | 0 | Yes | Yes |

# Requirements

- PHP 8.4+
- PostgreSQL 17+
- Composer 2 and Node.js 20+
- Redis for queues (optional for development)

# Installation

```bash
git clone https://github.com/Relaticle/relaticle.git
cd relaticle && composer app-install
```

# Development

```bash
# Start everything (server, queue, vite)
composer dev

# Run tests
composer test

# Format code
composer lint
```

# Self-Hosting

See the [Self-Hosting Guide](https://relaticle.com/docs/self-hosting) for Docker and manual deployment instructions.

# Documentation

Visit our [documentation](https://relaticle.com/docs) for guides on business usage, technical architecture, MCP server setup, REST API integration, and more.

# Community & Support

- [Report Issues](https://github.com/Relaticle/relaticle/issues)
- [Request Features](https://github.com/Relaticle/relaticle/discussions/categories/ideas)
- [Ask Questions](https://github.com/Relaticle/relaticle/discussions/categories/q-a)
- [Discord](https://discord.gg/relaticle)
- [Star us on GitHub](https://github.com/Relaticle/relaticle) to support the project

# License

Relaticle is open-source software licensed under the [AGPL-3.0 license](LICENSE).

# Star History

[![Star History Chart](https://api.star-history.com/svg?repos=Relaticle/relaticle&type=Date)](https://www.star-history.com/#Relaticle/relaticle&Date)


================================================
FILE: TODOS.md
================================================
# TODOs

Deferred work from plan reviews. Each item includes context and reasoning so it can be picked up without the original conversation.

---

## Centralize Marketing Numbers

**What:** Extract hardcoded marketing numbers (MCP tools count, custom field types, test count, authorization layers) into a single config or constants file. All marketing surfaces (hero, features, FAQ, pricing, schema markup, README) should reference this source of truth.

**Why:** The MCP tools count drifted from 20 to 30 as tools were added, but marketing copy wasn't updated. This was caught during a manual audit but could happen again with any number.

**Where numbers appear:** hero.blade.php, features.blade.php, faq.blade.php, community.blade.php, pricing.blade.php, index.blade.php (schema markup + OG description), layout.blade.php (documentation meta), mcp-guide.md, README.md.

**Approach:** Create a `config/marketing.php` with keys like `mcp_tools_count`, `field_types_count`, `test_count`. Reference via `config('marketing.mcp_tools_count')` in Blade templates. For README.md (not rendered by Laravel), keep manual but add a comment noting the config source.

**Effort:** S (CC: ~15min) | **Priority:** P2 | **Depends on:** Nothing

---

## Document the 5-Layer Authorization Model

**What:** The marketing claim "5-layer authorization" is used across multiple surfaces but the actual 5 layers are never explicitly defined. Based on code analysis, the layers appear to be: (1) User authentication (Sanctum/Fortify), (2) Team membership, (3) Team roles, (4) Eloquent policies, (5) Multi-tenancy scoping. This should be documented.

**Why:** If a technical evaluator asks "what are the 5 layers?", there's no answer in the docs. Undocumented marketing claims erode trust with developer audiences.

**Where to document:** Either the developer guide (developer-guide.md) or a dedicated security/architecture section in the getting-started guide.

**Effort:** S (CC: ~10min) | **Priority:** P2 | **Depends on:** Nothing


================================================
FILE: app/Actions/Company/CreateCompany.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Company;

use App\Enums\CreationSource;
use App\Models\Company;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class CreateCompany
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, array $data, CreationSource $source = CreationSource::WEB): Company
    {
        abort_unless($user->can('create', Company::class), 403);

        $attributes = Arr::only($data, ['name', 'custom_fields']);
        $attributes['creation_source'] = $source;

        $company = DB::transaction(fn (): Company => Company::query()->create($attributes));

        return $company->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Actions/Company/DeleteCompany.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Company;

use App\Models\Company;
use App\Models\User;

final readonly class DeleteCompany
{
    public function execute(User $user, Company $company): void
    {
        abort_unless($user->can('delete', $company), 403);

        $company->delete();
    }
}


================================================
FILE: app/Actions/Company/ListCompanies.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Company;

use App\Mcp\Filters\CustomFieldFilter;
use App\Mcp\Schema\CustomFieldFilterSchema;
use App\Models\Company;
use App\Models\User;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedInclude;
use Spatie\QueryBuilder\QueryBuilder;

final readonly class ListCompanies
{
    /**
     * @param  array<string, mixed>  $filters
     * @return CursorPaginator<int, Company>|LengthAwarePaginator<int, Company>
     */
    public function execute(
        User $user,
        int $perPage = 15,
        bool $useCursor = false,
        array $filters = [],
        ?int $page = null,
        ?Request $request = null,
    ): CursorPaginator|LengthAwarePaginator {
        abort_unless($user->can('viewAny', Company::class), 403);

        $request ??= new Request(['filter' => $filters]);
        $filterSchema = new CustomFieldFilterSchema;

        $query = QueryBuilder::for(Company::query()->withCustomFieldValues(), $request)
            ->allowedFilters(
                AllowedFilter::partial('name'),
                AllowedFilter::custom('custom_fields', new CustomFieldFilter('company')),
            )
            ->allowedFields('id', 'name', 'creator_id', 'account_owner_id', 'created_at', 'updated_at')
            ->allowedIncludes(
                'creator', 'accountOwner', 'people', 'opportunities',
                AllowedInclude::count('peopleCount', 'people'),
                AllowedInclude::count('opportunitiesCount', 'opportunities'),
                AllowedInclude::count('tasksCount', 'tasks'),
                AllowedInclude::count('notesCount', 'notes'),
            )
            ->allowedSorts(
                'name', 'created_at', 'updated_at',
                ...$filterSchema->allowedSorts($user, 'company'),
            )
            ->defaultSort('-created_at')
            ->orderBy('id');

        if ($useCursor) {
            return $query->cursorPaginate($perPage);
        }

        return $query->paginate($perPage, ['*'], 'page', $page);
    }
}


================================================
FILE: app/Actions/Company/UpdateCompany.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Company;

use App\Models\Company;
use App\Models\User;
use App\Support\CustomFieldMerger;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class UpdateCompany
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, Company $company, array $data): Company
    {
        abort_unless($user->can('update', $company), 403);

        $attributes = Arr::only($data, ['name', 'custom_fields']);

        $attributes = CustomFieldMerger::merge($company, $attributes);

        return DB::transaction(function () use ($company, $attributes): Company {
            $company->update($attributes);

            return $company->refresh()->load('customFieldValues.customField.options');
        });
    }
}


================================================
FILE: app/Actions/Fortify/CreateNewSocialUser.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Contracts\User\CreatesNewSocialUsers;
use App\Models\User;
use Filament\Auth\Events\Registered;
use Illuminate\Auth\Events\Verified;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Throwable;

final readonly class CreateNewSocialUser implements CreatesNewSocialUsers
{
    /**
     * Create a newly registered user.
     *
     * @param  array<string, string>  $input
     *
     * @throws Throwable
     */
    public function create(array $input): User
    {
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        ])->validate();

        return DB::transaction(fn () => tap(User::query()->create([
            'name' => $input['name'],
            'email' => $input['email'],
        ]), function (User $user): void {
            event(new Registered($user));
            if ($user->markEmailAsVerified()) {
                event(new Verified($user));
            }
        }));
    }
}


================================================
FILE: app/Actions/Fortify/PasswordValidationRules.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Validation\Rules\Password;

trait PasswordValidationRules
{
    /**
     * Get the validation rules used to validate passwords.
     *
     * @return array<int, Rule|array<mixed>|string>
     */
    protected function passwordRules(): array
    {
        return ['required', 'string', Password::default(), 'confirmed'];
    }
}


================================================
FILE: app/Actions/Fortify/ResetUserPassword.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords;

final readonly class ResetUserPassword implements ResetsUserPasswords
{
    use PasswordValidationRules;

    /**
     * Validate and reset the user's forgotten password.
     *
     * @param  array<string, string>  $input
     */
    public function reset(User $user, array $input): void
    {
        Validator::make($input, [
            'password' => $this->passwordRules(),
        ])->validate();

        $user->forceFill([
            'password' => Hash::make($input['password']),
        ])->save();
    }
}


================================================
FILE: app/Actions/Fortify/UpdateUserPassword.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;

final readonly class UpdateUserPassword implements UpdatesUserPasswords
{
    use PasswordValidationRules;

    /**
     * Validate and update the user's password.
     *
     * @param  array<string, string>  $input
     */
    public function update(User $user, array $input): void
    {
        Validator::make($input, [
            'current_password' => ['required', 'string', 'current_password:web'],
            'password' => $this->passwordRules(),
        ], [
            'current_password.current_password' => __('The provided password does not match your current password.'),
        ])->validateWithBag('updatePassword');

        $user->forceFill([
            'password' => Hash::make($input['password']),
        ])->save();
    }
}


================================================
FILE: app/Actions/Fortify/UpdateUserProfileInformation.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Models\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;

final readonly class UpdateUserProfileInformation implements UpdatesUserProfileInformation
{
    /**
     * Validate and update the given user's profile information.
     *
     * @param  array<string, mixed>  $input
     */
    public function update(User $user, array $input): void
    {
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
            'profile_photo_path' => ['nullable', 'string', 'max:255'],
        ])->validateWithBag('updateProfileInformation');

        if (array_key_exists('profile_photo_path', $input)) {
            if ($input['profile_photo_path']) {
                $user->updateProfilePhoto($input['profile_photo_path']);
            } else {
                $user->deleteProfilePhoto();
            }
        }

        if ($input['email'] !== $user->email) {
            $this->updateVerifiedUser($user, $input);
        } else {
            $user->forceFill([
                'name' => $input['name'],
                'email' => $input['email'],
            ])->save();
        }
    }

    /**
     * Update the given verified user's profile information.
     *
     * @param  array<string, string>  $input
     */
    private function updateVerifiedUser(User $user, array $input): void
    {
        $user->forceFill([
            'name' => $input['name'],
            'email' => $input['email'],
            'email_verified_at' => null,
        ])->save();

        $user->sendEmailVerificationNotification();
    }
}


================================================
FILE: app/Actions/Jetstream/AddTeamMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use Closure;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Laravel\Jetstream\Contracts\AddsTeamMembers;
use Laravel\Jetstream\Events\AddingTeamMember;
use Laravel\Jetstream\Events\TeamMemberAdded;
use Laravel\Jetstream\Jetstream;
use Laravel\Jetstream\Rules\Role;

final readonly class AddTeamMember implements AddsTeamMembers
{
    /**
     * Add a new team member to the given team.
     */
    public function add(User $user, Team $team, string $email, ?string $role = null): void
    {
        Gate::forUser($user)->authorize('addTeamMember', $team);

        $this->validate($team, $email, $role);

        $newTeamMember = Jetstream::findUserByEmailOrFail($email);

        event(new AddingTeamMember($team, $newTeamMember));

        $team->users()->attach(
            $newTeamMember, ['role' => $role]
        );

        event(new TeamMemberAdded($team, $newTeamMember));
    }

    /**
     * Validate the add member operation.
     */
    private function validate(Team $team, string $email, ?string $role): void
    {
        Validator::make([
            'email' => $email,
            'role' => $role,
        ], $this->rules(), [
            'email.exists' => __('We were unable to find a registered user with this email address.'),
        ])->after(
            $this->ensureUserIsNotAlreadyOnTeam($team, $email)
        )->validateWithBag('addTeamMember');
    }

    /**
     * Get the validation rules for adding a team member.
     *
     * @return array<string, array<int, string|Rule>>
     */
    private function rules(): array
    {
        return [
            'email' => ['required', 'email', 'exists:users'],
            'role' => ['required', 'string', new Role],
        ];
    }

    /**
     * Ensure that the user is not already on the team.
     */
    private function ensureUserIsNotAlreadyOnTeam(Team $team, string $email): Closure
    {
        return function ($validator) use ($team, $email): void { // @pest-ignore-type

            $validator->errors()->addIf(
                $team->hasUserWithEmail($email),
                'email',
                __('This user already belongs to the team.')
            );
        };
    }
}


================================================
FILE: app/Actions/Jetstream/CreateTeam.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use App\Rules\ValidTeamSlug;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Laravel\Jetstream\Contracts\CreatesTeams;
use Laravel\Jetstream\Events\AddingTeam;
use Laravel\Jetstream\Jetstream;

final readonly class CreateTeam implements CreatesTeams
{
    /**
     * Validate and create a new team for the given user.
     *
     * @param  array<string, string>  $input
     */
    public function create(User $user, array $input): Team
    {
        Gate::forUser($user)->authorize('create', Jetstream::newTeamModel());

        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'slug' => ['required', 'string', 'max:255', new ValidTeamSlug, 'unique:teams,slug'],
        ])->validateWithBag('createTeam');

        $isFirstTeam = ! $user->ownedTeams()->exists();

        event(new AddingTeam($user));

        $user->switchTeam($team = $user->ownedTeams()->create([
            'name' => $input['name'],
            'slug' => $input['slug'],
            'personal_team' => $isFirstTeam,
        ]));

        /** @var Team $team */
        return $team;
    }
}


================================================
FILE: app/Actions/Jetstream/DeleteTeam.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use Laravel\Jetstream\Contracts\DeletesTeams;

final readonly class DeleteTeam implements DeletesTeams
{
    /**
     * Delete the given team.
     */
    public function delete(Team $team): void
    {
        $team->purge();
    }
}


================================================
FILE: app/Actions/Jetstream/DeleteUser.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Laravel\Jetstream\Contracts\DeletesTeams;
use Laravel\Jetstream\Contracts\DeletesUsers;

final readonly class DeleteUser implements DeletesUsers
{
    /**
     * Create a new action instance.
     */
    public function __construct(private DeletesTeams $deletesTeams) {}

    /**
     * Delete the given user.
     */
    public function delete(User $user): void
    {
        DB::transaction(function () use ($user): void {
            $this->deleteTeams($user);
            $user->deleteProfilePhoto();
            $user->tokens->each->delete();
            $user->delete();
        });
    }

    /**
     * Delete the teams and team associations attached to the user.
     */
    private function deleteTeams(User $user): void
    {
        $user->teams()->detach();

        $user->ownedTeams->each(function (Model $team): void {
            /** @var Team $team */
            $this->deletesTeams->delete($team);
        });
    }
}


================================================
FILE: app/Actions/Jetstream/InviteTeamMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use Closure;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Unique;
use Laravel\Jetstream\Contracts\InvitesTeamMembers;
use Laravel\Jetstream\Events\InvitingTeamMember;
use Laravel\Jetstream\Jetstream;
use Laravel\Jetstream\Mail\TeamInvitation;
use Laravel\Jetstream\Rules\Role;
use Laravel\Jetstream\TeamInvitation as TeamInvitationModel;

final readonly class InviteTeamMember implements InvitesTeamMembers
{
    /**
     * Invite a new team member to the given team.
     */
    public function invite(User $user, Team $team, string $email, ?string $role = null): void
    {
        Gate::forUser($user)->authorize('addTeamMember', $team);

        $this->validate($team, $email, $role);

        event(new InvitingTeamMember($team, $email, $role));

        $expiryDays = (int) config('jetstream.invitation_expiry_days', 7);

        $invitation = $team->teamInvitations()->create([
            'email' => $email,
            'role' => $role,
            'expires_at' => now()->addDays($expiryDays),
        ]);

        /** @var TeamInvitationModel $invitation */
        Mail::to($email)->send(new TeamInvitation($invitation));
    }

    /**
     * Validate the invite member operation.
     */
    private function validate(Team $team, string $email, ?string $role): void
    {
        Validator::make([
            'email' => $email,
            'role' => $role,
        ], $this->rules($team), [
            'email.unique' => __('This user has already been invited to the team.'),
        ])->after(
            $this->ensureUserIsNotAlreadyOnTeam($team, $email)
        )->validateWithBag('addTeamMember');
    }

    /**
     * Get the validation rules for inviting a team member.
     *
     * @return array<string, list<Unique|Role|string>>
     */
    private function rules(Team $team): array
    {
        return [
            'email' => [
                'required', 'email',
                Rule::unique(Jetstream::teamInvitationModel())->where(function (Builder $query) use ($team): void {
                    $query->where('team_id', $team->id);
                }),
            ],
            'role' => ['required', 'string', new Role],
        ];
    }

    /**
     * Ensure that the user is not already on the team.
     */
    private function ensureUserIsNotAlreadyOnTeam(Team $team, string $email): Closure
    {
        return function ($validator) use ($team, $email): void { // @pest-ignore-type
            $validator->errors()->addIf(
                $team->hasUserWithEmail($email),
                'email',
                __('This user already belongs to the team.')
            );
        };
    }
}


================================================
FILE: app/Actions/Jetstream/RemoveTeamMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\ValidationException;
use Laravel\Jetstream\Contracts\RemovesTeamMembers;
use Laravel\Jetstream\Events\TeamMemberRemoved;

final readonly class RemoveTeamMember implements RemovesTeamMembers
{
    /**
     * Remove the team member from the given team.
     */
    public function remove(User $user, Team $team, User $teamMember): void
    {
        $this->authorize($user, $team, $teamMember);

        $this->ensureUserDoesNotOwnTeam($teamMember, $team);

        $team->removeUser($teamMember);

        event(new TeamMemberRemoved($team, $teamMember));
    }

    /**
     * Authorize that the user can remove the team member.
     */
    private function authorize(User $user, Team $team, User $teamMember): void
    {
        throw_if(! Gate::forUser($user)->check('removeTeamMember', $team) &&
            $user->id !== $teamMember->id, AuthorizationException::class);
    }

    /**
     * Ensure that the currently authenticated user does not own the team.
     */
    private function ensureUserDoesNotOwnTeam(User $teamMember, Team $team): void
    {
        /** @var User $owner */
        $owner = $team->owner;
        if ($teamMember->id === $owner->id) {
            throw ValidationException::withMessages([
                'team' => [__('You may not leave a team that you created.')],
            ])->errorBag('removeTeamMember');
        }
    }
}


================================================
FILE: app/Actions/Jetstream/UpdateTeamName.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Team;
use App\Models\User;
use App\Rules\ValidTeamSlug;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Laravel\Jetstream\Contracts\UpdatesTeamNames;

final readonly class UpdateTeamName implements UpdatesTeamNames
{
    /**
     * Validate and update the given team's name.
     *
     * @param  array<string, string>  $input
     */
    public function update(User $user, Team $team, array $input): void
    {
        Gate::forUser($user)->authorize('update', $team);

        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'slug' => ['required', 'string', 'max:255', new ValidTeamSlug(ignoreValue: $team->slug), "unique:teams,slug,{$team->id}"],
        ])->validateWithBag('updateTeamName');

        $team->update([
            'name' => $input['name'],
            'slug' => $input['slug'],
        ]);
    }
}


================================================
FILE: app/Actions/Note/CreateNote.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Note;

use App\Enums\CreationSource;
use App\Models\Note;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class CreateNote
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, array $data, CreationSource $source = CreationSource::WEB): Note
    {
        abort_unless($user->can('create', Note::class), 403);

        $companyIds = Arr::pull($data, 'company_ids');
        $peopleIds = Arr::pull($data, 'people_ids');
        $opportunityIds = Arr::pull($data, 'opportunity_ids');

        $attributes = Arr::only($data, ['title', 'custom_fields']);
        $attributes['creation_source'] = $source;

        $note = DB::transaction(function () use ($attributes, $companyIds, $peopleIds, $opportunityIds): Note {
            $note = Note::query()->create($attributes);

            if ($companyIds !== null) {
                $note->companies()->sync($companyIds);
            }
            if ($peopleIds !== null) {
                $note->people()->sync($peopleIds);
            }
            if ($opportunityIds !== null) {
                $note->opportunities()->sync($opportunityIds);
            }

            return $note;
        });

        return $note->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Actions/Note/DeleteNote.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Note;

use App\Models\Note;
use App\Models\User;

final readonly class DeleteNote
{
    public function execute(User $user, Note $note): void
    {
        abort_unless($user->can('delete', $note), 403);

        $note->delete();
    }
}


================================================
FILE: app/Actions/Note/ListNotes.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Note;

use App\Mcp\Filters\CustomFieldFilter;
use App\Mcp\Schema\CustomFieldFilterSchema;
use App\Models\Note;
use App\Models\User;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedInclude;
use Spatie\QueryBuilder\QueryBuilder;

final readonly class ListNotes
{
    /**
     * @param  array<string, mixed>  $filters
     * @return CursorPaginator<int, Note>|LengthAwarePaginator<int, Note>
     */
    public function execute(
        User $user,
        int $perPage = 15,
        bool $useCursor = false,
        array $filters = [],
        ?int $page = null,
        ?Request $request = null,
    ): CursorPaginator|LengthAwarePaginator {
        abort_unless($user->can('viewAny', Note::class), 403);

        $request ??= new Request(['filter' => $filters]);
        $filterSchema = new CustomFieldFilterSchema;

        $query = QueryBuilder::for(Note::query()->withCustomFieldValues(), $request)
            ->allowedFilters(
                AllowedFilter::partial('title'),
                AllowedFilter::scope('notable_type', 'forNotableType'),
                AllowedFilter::scope('notable_id', 'forNotableId'),
                AllowedFilter::custom('custom_fields', new CustomFieldFilter('note')),
            )
            ->allowedFields('id', 'title', 'creator_id', 'created_at', 'updated_at')
            ->allowedIncludes(
                'creator', 'companies', 'people', 'opportunities',
                AllowedInclude::count('companiesCount', 'companies'),
                AllowedInclude::count('peopleCount', 'people'),
                AllowedInclude::count('opportunitiesCount', 'opportunities'),
            )
            ->allowedSorts(
                'title', 'created_at', 'updated_at',
                ...$filterSchema->allowedSorts($user, 'note'),
            )
            ->defaultSort('-created_at')
            ->orderBy('id');

        if ($useCursor) {
            return $query->cursorPaginate($perPage);
        }

        return $query->paginate($perPage, ['*'], 'page', $page);
    }
}


================================================
FILE: app/Actions/Note/UpdateNote.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Note;

use App\Models\Note;
use App\Models\User;
use App\Support\CustomFieldMerger;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class UpdateNote
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, Note $note, array $data): Note
    {
        abort_unless($user->can('update', $note), 403);

        $attributes = Arr::only($data, ['title', 'custom_fields']);

        $attributes = CustomFieldMerger::merge($note, $attributes);

        return DB::transaction(function () use ($note, $attributes, $data): Note {
            $note->update($attributes);

            if (array_key_exists('company_ids', $data)) {
                $note->companies()->sync($data['company_ids']);
            }
            if (array_key_exists('people_ids', $data)) {
                $note->people()->sync($data['people_ids']);
            }
            if (array_key_exists('opportunity_ids', $data)) {
                $note->opportunities()->sync($data['opportunity_ids']);
            }

            return $note->refresh()->load('customFieldValues.customField.options');
        });
    }
}


================================================
FILE: app/Actions/Opportunity/CreateOpportunity.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Opportunity;

use App\Enums\CreationSource;
use App\Models\Opportunity;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class CreateOpportunity
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, array $data, CreationSource $source = CreationSource::WEB): Opportunity
    {
        abort_unless($user->can('create', Opportunity::class), 403);

        $attributes = Arr::only($data, ['name', 'company_id', 'contact_id', 'custom_fields']);
        $attributes['creation_source'] = $source;

        $opportunity = DB::transaction(fn (): Opportunity => Opportunity::query()->create($attributes));

        return $opportunity->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Actions/Opportunity/DeleteOpportunity.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Opportunity;

use App\Models\Opportunity;
use App\Models\User;

final readonly class DeleteOpportunity
{
    public function execute(User $user, Opportunity $opportunity): void
    {
        abort_unless($user->can('delete', $opportunity), 403);

        $opportunity->delete();
    }
}


================================================
FILE: app/Actions/Opportunity/ListOpportunities.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Opportunity;

use App\Mcp\Filters\CustomFieldFilter;
use App\Mcp\Schema\CustomFieldFilterSchema;
use App\Models\Opportunity;
use App\Models\User;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedInclude;
use Spatie\QueryBuilder\QueryBuilder;

final readonly class ListOpportunities
{
    /**
     * @param  array<string, mixed>  $filters
     * @return CursorPaginator<int, Opportunity>|LengthAwarePaginator<int, Opportunity>
     */
    public function execute(
        User $user,
        int $perPage = 15,
        bool $useCursor = false,
        array $filters = [],
        ?int $page = null,
        ?Request $request = null,
    ): CursorPaginator|LengthAwarePaginator {
        abort_unless($user->can('viewAny', Opportunity::class), 403);

        $request ??= new Request(['filter' => $filters]);
        $filterSchema = new CustomFieldFilterSchema;

        $query = QueryBuilder::for(Opportunity::query()->withCustomFieldValues(), $request)
            ->allowedFilters(
                AllowedFilter::partial('name'),
                AllowedFilter::exact('company_id'),
                AllowedFilter::exact('contact_id'),
                AllowedFilter::custom('custom_fields', new CustomFieldFilter('opportunity')),
            )
            ->allowedFields('id', 'name', 'company_id', 'contact_id', 'creator_id', 'created_at', 'updated_at')
            ->allowedIncludes(
                'creator', 'company', 'contact',
                AllowedInclude::count('tasksCount', 'tasks'),
                AllowedInclude::count('notesCount', 'notes'),
            )
            ->allowedSorts(
                'name', 'created_at', 'updated_at',
                ...$filterSchema->allowedSorts($user, 'opportunity'),
            )
            ->defaultSort('-created_at')
            ->orderBy('id');

        if ($useCursor) {
            return $query->cursorPaginate($perPage);
        }

        return $query->paginate($perPage, ['*'], 'page', $page);
    }
}


================================================
FILE: app/Actions/Opportunity/UpdateOpportunity.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Opportunity;

use App\Models\Opportunity;
use App\Models\User;
use App\Support\CustomFieldMerger;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class UpdateOpportunity
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, Opportunity $opportunity, array $data): Opportunity
    {
        abort_unless($user->can('update', $opportunity), 403);

        $attributes = Arr::only($data, ['name', 'company_id', 'contact_id', 'custom_fields']);

        $attributes = CustomFieldMerger::merge($opportunity, $attributes);

        return DB::transaction(function () use ($opportunity, $attributes): Opportunity {
            $opportunity->update($attributes);

            return $opportunity->refresh()->load('customFieldValues.customField.options');
        });
    }
}


================================================
FILE: app/Actions/People/CreatePeople.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\People;

use App\Enums\CreationSource;
use App\Models\People;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class CreatePeople
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, array $data, CreationSource $source = CreationSource::WEB): People
    {
        abort_unless($user->can('create', People::class), 403);

        $attributes = Arr::only($data, ['name', 'company_id', 'custom_fields']);
        $attributes['creation_source'] = $source;

        $person = DB::transaction(fn (): People => People::query()->create($attributes));

        return $person->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Actions/People/DeletePeople.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\People;

use App\Models\People;
use App\Models\User;

final readonly class DeletePeople
{
    public function execute(User $user, People $people): void
    {
        abort_unless($user->can('delete', $people), 403);

        $people->delete();
    }
}


================================================
FILE: app/Actions/People/ListPeople.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\People;

use App\Mcp\Filters\CustomFieldFilter;
use App\Mcp\Schema\CustomFieldFilterSchema;
use App\Models\People;
use App\Models\User;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedInclude;
use Spatie\QueryBuilder\QueryBuilder;

final readonly class ListPeople
{
    /**
     * @param  array<string, mixed>  $filters
     * @return CursorPaginator<int, People>|LengthAwarePaginator<int, People>
     */
    public function execute(
        User $user,
        int $perPage = 15,
        bool $useCursor = false,
        array $filters = [],
        ?int $page = null,
        ?Request $request = null,
    ): CursorPaginator|LengthAwarePaginator {
        abort_unless($user->can('viewAny', People::class), 403);

        $request ??= new Request(['filter' => $filters]);
        $filterSchema = new CustomFieldFilterSchema;

        $query = QueryBuilder::for(People::query()->withCustomFieldValues(), $request)
            ->allowedFilters(
                AllowedFilter::partial('name'),
                AllowedFilter::exact('company_id'),
                AllowedFilter::custom('custom_fields', new CustomFieldFilter('people')),
            )
            ->allowedFields('id', 'name', 'company_id', 'creator_id', 'created_at', 'updated_at')
            ->allowedIncludes(
                'creator', 'company',
                AllowedInclude::count('tasksCount', 'tasks'),
                AllowedInclude::count('notesCount', 'notes'),
            )
            ->allowedSorts(
                'name', 'created_at', 'updated_at',
                ...$filterSchema->allowedSorts($user, 'people'),
            )
            ->defaultSort('-created_at')
            ->orderBy('id');

        if ($useCursor) {
            return $query->cursorPaginate($perPage);
        }

        return $query->paginate($perPage, ['*'], 'page', $page);
    }
}


================================================
FILE: app/Actions/People/UpdatePeople.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\People;

use App\Models\People;
use App\Models\User;
use App\Support\CustomFieldMerger;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class UpdatePeople
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, People $people, array $data): People
    {
        abort_unless($user->can('update', $people), 403);

        $attributes = Arr::only($data, ['name', 'company_id', 'custom_fields']);

        $attributes = CustomFieldMerger::merge($people, $attributes);

        return DB::transaction(function () use ($people, $attributes): People {
            $people->update($attributes);

            return $people->refresh()->load('customFieldValues.customField.options');
        });
    }
}


================================================
FILE: app/Actions/Task/CreateTask.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Task;

use App\Enums\CreationSource;
use App\Models\Task;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class CreateTask
{
    public function __construct(
        private NotifyTaskAssignees $notifyAssignees,
    ) {}

    /**
     * @param  array<string, mixed>  $data
     */
    public function execute(User $user, array $data, CreationSource $source = CreationSource::WEB): Task
    {
        abort_unless($user->can('create', Task::class), 403);

        $companyIds = Arr::pull($data, 'company_ids');
        $peopleIds = Arr::pull($data, 'people_ids');
        $opportunityIds = Arr::pull($data, 'opportunity_ids');
        $assigneeIds = Arr::pull($data, 'assignee_ids');

        $attributes = Arr::only($data, ['title', 'custom_fields']);
        $attributes['creation_source'] = $source;

        $task = DB::transaction(function () use ($attributes, $companyIds, $peopleIds, $opportunityIds, $assigneeIds): Task {
            $task = Task::query()->create($attributes);

            if ($companyIds !== null) {
                $task->companies()->sync($companyIds);
            }
            if ($peopleIds !== null) {
                $task->people()->sync($peopleIds);
            }
            if ($opportunityIds !== null) {
                $task->opportunities()->sync($opportunityIds);
            }
            if ($assigneeIds !== null) {
                $task->assignees()->sync($assigneeIds);
            }

            return $task;
        });

        $this->notifyAssignees->execute($task);

        return $task->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Actions/Task/DeleteTask.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Task;

use App\Models\Task;
use App\Models\User;

final readonly class DeleteTask
{
    public function execute(User $user, Task $task): void
    {
        abort_unless($user->can('delete', $task), 403);

        $task->delete();
    }
}


================================================
FILE: app/Actions/Task/ListTasks.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Task;

use App\Mcp\Filters\CustomFieldFilter;
use App\Mcp\Schema\CustomFieldFilterSchema;
use App\Models\Task;
use App\Models\User;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedInclude;
use Spatie\QueryBuilder\QueryBuilder;

final readonly class ListTasks
{
    /**
     * @param  array<string, mixed>  $filters
     * @return CursorPaginator<int, Task>|LengthAwarePaginator<int, Task>
     */
    public function execute(
        User $user,
        int $perPage = 15,
        bool $useCursor = false,
        array $filters = [],
        ?int $page = null,
        ?Request $request = null,
    ): CursorPaginator|LengthAwarePaginator {
        abort_unless($user->can('viewAny', Task::class), 403);

        $request ??= new Request(['filter' => $filters]);
        $filterSchema = new CustomFieldFilterSchema;

        $query = QueryBuilder::for(Task::query()->withCustomFieldValues(), $request)
            ->allowedFilters(
                AllowedFilter::partial('title'),
                AllowedFilter::callback('assigned_to_me', function (Builder $query, mixed $value) use ($user): void {
                    if (filter_var($value, FILTER_VALIDATE_BOOLEAN)) {
                        $query->whereHas('assignees', fn (Builder $q) => $q->where('users.id', $user->getKey()));
                    }
                }),
                AllowedFilter::scope('company_id', 'forCompany'),
                AllowedFilter::scope('people_id', 'forPerson'),
                AllowedFilter::scope('opportunity_id', 'forOpportunity'),
                AllowedFilter::custom('custom_fields', new CustomFieldFilter('task')),
            )
            ->allowedFields('id', 'title', 'creator_id', 'created_at', 'updated_at')
            ->allowedIncludes(
                'creator', 'assignees', 'companies', 'people', 'opportunities',
                AllowedInclude::count('assigneesCount', 'assignees'),
                AllowedInclude::count('companiesCount', 'companies'),
                AllowedInclude::count('peopleCount', 'people'),
                AllowedInclude::count('opportunitiesCount', 'opportunities'),
            )
            ->allowedSorts(
                'title', 'created_at', 'updated_at',
                ...$filterSchema->allowedSorts($user, 'task'),
            )
            ->defaultSort('-created_at')
            ->orderBy('id');

        if ($useCursor) {
            return $query->cursorPaginate($perPage);
        }

        return $query->paginate($perPage, ['*'], 'page', $page);
    }
}


================================================
FILE: app/Actions/Task/NotifyTaskAssignees.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Task;

use App\Filament\Resources\TaskResource\Pages\ManageTasks;
use App\Models\Task;
use App\Models\User;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Support\Icons\Heroicon;

final readonly class NotifyTaskAssignees
{
    /**
     * @param  array<int>  $previousAssigneeIds
     */
    public function execute(Task $task, array $previousAssigneeIds = []): void
    {
        $currentIds = $task->assignees()->pluck('users.id')->all();
        $newIds = array_diff($currentIds, $previousAssigneeIds);

        if ($newIds === []) {
            return;
        }

        $taskTitle = $task->title;
        $taskId = $task->id;
        $taskUrl = $this->resolveTaskUrl($task);

        defer(function () use ($newIds, $taskTitle, $taskId, $taskUrl): void {
            User::query()
                ->whereIn('id', $newIds)
                ->get()
                ->each(function (User $recipient) use ($taskTitle, $taskId, $taskUrl): void {
                    Notification::make()
                        ->title("New Task Assignment: {$taskTitle}")
                        ->actions([
                            Action::make('view')
                                ->button()
                                ->label('View Task')
                                ->url($taskUrl)
                                ->markAsRead(),
                        ])
                        ->icon(Heroicon::OutlinedCheckCircle)
                        ->iconColor('primary')
                        ->viewData(['task_id' => $taskId])
                        ->sendToDatabase($recipient);
                });
        });
    }

    private function resolveTaskUrl(Task $task): string
    {
        try {
            return ManageTasks::getUrl(['record' => $task]);
        } catch (\Throwable) {
            return '#';
        }
    }
}


================================================
FILE: app/Actions/Task/UpdateTask.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Task;

use App\Models\Task;
use App\Models\User;
use App\Support\CustomFieldMerger;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final readonly class UpdateTask
{
    public function __construct(
        private NotifyTaskAssignees $notifyAssignees,
    ) {}

    /**
     * @param  array<string, mixed>  $data
     *
     * @throws \Throwable
     */
    public function execute(User $user, Task $task, array $data): Task
    {
        abort_unless($user->can('update', $task), 403);

        $attributes = Arr::only($data, ['title', 'custom_fields']);

        $attributes = CustomFieldMerger::merge($task, $attributes);

        $previousAssigneeIds = $task->assignees()->pluck('users.id')->all();

        $task = DB::transaction(function () use ($task, $attributes, $data): Task {
            $task->update($attributes);

            if (array_key_exists('company_ids', $data)) {
                $task->companies()->sync($data['company_ids']);
            }
            if (array_key_exists('people_ids', $data)) {
                $task->people()->sync($data['people_ids']);
            }
            if (array_key_exists('opportunity_ids', $data)) {
                $task->opportunities()->sync($data['opportunity_ids']);
            }
            if (array_key_exists('assignee_ids', $data)) {
                $task->assignees()->sync($data['assignee_ids']);
            }

            return $task->refresh();
        });

        $this->notifyAssignees->execute($task, $previousAssigneeIds);

        return $task->load('customFieldValues.customField.options');
    }
}


================================================
FILE: app/Concerns/DetectsTeamInvitation.php
================================================
<?php

declare(strict_types=1);

namespace App\Concerns;

use App\Models\TeamInvitation;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\HtmlString;

trait DetectsTeamInvitation
{
    protected function getTeamInvitationFromSession(): ?TeamInvitation
    {
        $intendedUrl = session('url.intended', '');

        if (! str_contains((string) $intendedUrl, '/team-invitations/')) {
            return null;
        }

        $path = parse_url((string) $intendedUrl, PHP_URL_PATH);

        if (! $path) {
            return null;
        }

        $segments = explode('/', trim($path, '/'));
        $invitationIndex = array_search('team-invitations', $segments, true);

        if ($invitationIndex === false || ! isset($segments[$invitationIndex + 1])) {
            return null;
        }

        return TeamInvitation::query()
            ->whereKey($segments[$invitationIndex + 1])
            ->first();
    }

    protected function getTeamInvitationSubheading(): ?Htmlable
    {
        $invitation = $this->getTeamInvitationFromSession();

        if (! $invitation || $invitation->isExpired()) {
            return null;
        }

        return new HtmlString(
            __('You\'ve been invited to join <strong>:team</strong>', [
                'team' => e($invitation->team->name),
            ])
        );
    }

    protected function getInvitationContentHtml(): string
    {
        $subheading = $this->getTeamInvitationSubheading();

        if ($subheading === null) {
            return '';
        }

        return '<p class="text-center text-sm text-gray-500 dark:text-gray-400">'.$subheading->toHtml().'</p>';
    }
}


================================================
FILE: app/Console/Commands/BackfillCustomFieldColorsCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Enums\CustomFields\OpportunityField as OpportunityCustomField;
use App\Enums\CustomFields\TaskField as TaskCustomField;
use App\Models\CustomField;
use App\Models\Opportunity;
use App\Models\Task;
use Illuminate\Console\Command;
use Relaticle\CustomFields\Data\CustomFieldOptionSettingsData;
use Relaticle\CustomFields\Data\CustomFieldSettingsData;

final class BackfillCustomFieldColorsCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'custom-fields:backfill-colors
                            {--team= : Specific team ID to backfill (optional)}
                            {--dry-run : Show what would be updated without making changes}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Backfill colors for existing custom field options (Task status/priority and Opportunity stages)';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->info('🎨 Backfilling custom field colors...');

        $dryRun = $this->option('dry-run');
        $specificTeam = $this->option('team');

        if ($dryRun) {
            $this->warn('🔍 DRY RUN MODE - No changes will be made');
        }

        // Get fields to update
        $query = CustomField::with('options')
            ->whereIn('name', ['Status', 'Priority', 'Stage'])
            ->whereIn('entity_type', [Task::class, Opportunity::class])
            ->where('type', 'select');

        if ($specificTeam) {
            $query->where('tenant_id', $specificTeam);
        }

        $fields = $query->get();

        $this->info("Found {$fields->count()} fields to process");

        $updatedFields = 0;
        $updatedOptions = 0;

        foreach ($fields as $field) {
            $colorMapping = $this->getColorMappingForField($field);

            if ($colorMapping === null) {
                continue;
            }

            $this->info("Processing: {$field->name} for {$field->entity_type} (Team {$field->tenant_id})");

            // Enable colors on the field if not already enabled
            if (! $field->settings->enable_option_colors) {
                if (! $dryRun) {
                    $field->update([
                        'settings' => new CustomFieldSettingsData(
                            visible_in_list: $field->settings->visible_in_list ?? true,
                            list_toggleable_hidden: $field->settings->list_toggleable_hidden,
                            visible_in_view: $field->settings->visible_in_view ?? true,
                            searchable: $field->settings->searchable ?? false,
                            encrypted: $field->settings->encrypted ?? false,
                            enable_option_colors: true,
                            visibility: $field->settings->visibility ?? null,
                            additional: $field->settings->additional ?? [],
                        ),
                    ]);
                }
                $this->line('  ✓ Enabled color options for field');
                $updatedFields++;
            } else {
                $this->line('  ℹ Field already has color options enabled');
            }

            // Apply colors to options
            foreach ($field->options as $option) {
                $color = $colorMapping[$option->name] ?? null;
                if ($color !== null) {
                    $currentColor = $option->settings->color ?? null;
                    if ($currentColor !== $color) {
                        if (! $dryRun) {
                            $option->update([
                                'settings' => new CustomFieldOptionSettingsData(color: $color),
                            ]);
                        }
                        $this->line("  ✓ Set color for '{$option->name}': $color");
                        $updatedOptions++;
                    } else {
                        $this->line("  ℹ '{$option->name}' already has correct color: $color");
                    }
                } else {
                    $this->line("  ⚠ No color mapping found for option: '{$option->name}'");
                }
            }
        }

        if ($dryRun) {
            $this->info('🔍 DRY RUN COMPLETE:');
            $this->info("  - Would enable colors on $updatedFields fields");
            $this->info("  - Would update colors on $updatedOptions options");
        } else {
            $this->info('✅ BACKFILL COMPLETE:');
            $this->info("  - Enabled colors on $updatedFields fields");
            $this->info("  - Updated colors on $updatedOptions options");
        }

        return self::SUCCESS;
    }

    /**
     * Get color mapping for a field based on its configuration
     */
    /**
     * @return array<int|string, string>|null
     */
    private function getColorMappingForField(CustomField $field): ?array
    {
        return match ([$field->entity_type, $field->name]) {
            [Task::class, 'Status'] => TaskCustomField::STATUS->getOptionColors(),
            [Task::class, 'Priority'] => TaskCustomField::PRIORITY->getOptionColors(),
            [Opportunity::class, 'Stage'] => OpportunityCustomField::STAGE->getOptionColors(),
            default => null,
        };
    }
}


================================================
FILE: app/Console/Commands/CleanupExpiredInvitationsCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\TeamInvitation;
use Illuminate\Console\Command;
use Illuminate\Contracts\Database\Query\Builder;

final class CleanupExpiredInvitationsCommand extends Command
{
    /**
     * @var string
     */
    protected $signature = 'invitations:cleanup
                            {--days=30 : Delete invitations expired more than this many days ago}';

    /**
     * @var string
     */
    protected $description = 'Delete team invitations that have been expired for a specified number of days';

    public function handle(): void
    {
        $days = (int) $this->option('days');

        $cutoff = now()->subDays($days);

        $deleted = TeamInvitation::query()
            ->where(function (Builder $query) use ($cutoff): void {
                $query->where('expires_at', '<', $cutoff)
                    ->orWhere(function (Builder $query) use ($cutoff): void {
                        $query->whereNull('expires_at')
                            ->where('created_at', '<', $cutoff);
                    });
            })
            ->delete();

        $this->info("Purged {$deleted} expired invitation(s).");
    }
}


================================================
FILE: app/Console/Commands/CreateSystemAdminCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Relaticle\SystemAdmin\Enums\SystemAdministratorRole;
use Relaticle\SystemAdmin\Models\SystemAdministrator;
use Throwable;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\password;
use function Laravel\Prompts\text;

final class CreateSystemAdminCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sysadmin:create
                            {--name= : The name of the system administrator}
                            {--email= : The email address of the system administrator}
                            {--password= : The password for the system administrator}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new system administrator account';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->info('Create System Administrator Account');
        $this->line('────────────────────────────────────');
        $this->newLine();

        try {
            // Check if any system administrators exist
            $existingCount = SystemAdministrator::query()->count();
            if ($existingCount > 0) {
                $this->warn("There are currently {$existingCount} system administrator(s).");

                if (! $this->option('no-interaction')) {
                    $continue = confirm(
                        label: 'Do you want to create another system administrator?',
                        default: true
                    );

                    if (! $continue) {
                        $this->info('Operation cancelled.');

                        return self::SUCCESS;
                    }
                }
            }

            // Get administrator details
            $name = $this->option('name') ?? text(
                label: 'Name',
                placeholder: 'John Doe',
                required: true,
                validate: fn (string $value): ?string => strlen($value) < 2 ? 'Name must be at least 2 characters' : null
            );

            $email = $this->option('email') ?? text(
                label: 'Email address',
                placeholder: 'admin@example.com',
                required: true,
                validate: function (string $value): ?string {
                    if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
                        return 'Please enter a valid email address';
                    }

                    if (SystemAdministrator::query()->where('email', $value)->exists()) {
                        return "An administrator with email '{$value}' already exists";
                    }

                    return null;
                }
            );

            // Validate email from command option
            if ($this->option('email')) {
                if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
                    $this->error('Invalid email address provided.');

                    return self::FAILURE;
                }

                if (SystemAdministrator::query()->where('email', $email)->exists()) {
                    $this->error("An administrator with email '{$email}' already exists.");

                    return self::FAILURE;
                }
            }

            $password = $this->option('password') ?? password(
                label: 'Password',
                placeholder: 'Minimum 8 characters',
                required: true,
                validate: fn (string $value): ?string => strlen($value) < 8 ? 'Password must be at least 8 characters' : null
            );

            // Validate password from command option
            if ($this->option('password') && strlen($password) < 8) {
                $this->error('Password must be at least 8 characters.');

                return self::FAILURE;
            }

            // Show summary
            if (! $this->option('no-interaction') && ! ($this->option('name') && $this->option('email') && $this->option('password'))) {
                $this->newLine();
                $this->info('Summary:');
                $this->line("  Name:  {$name}");
                $this->line("  Email: {$email}");
                $this->line('  Role:  Super Administrator');
                $this->newLine();

                $confirmed = confirm(
                    label: 'Create this system administrator?',
                    default: true
                );

                if (! $confirmed) {
                    $this->info('Operation cancelled.');

                    return self::SUCCESS;
                }
            }

            // Create the system administrator
            $admin = SystemAdministrator::query()->create([
                'name' => $name,
                'email' => $email,
                'password' => bcrypt($password),
                'email_verified_at' => now(),
                'role' => SystemAdministratorRole::SuperAdministrator,
            ]);

            $this->newLine();
            $this->info('✅ System Administrator created successfully!');
            $this->newLine();
            $this->line('  Details:');
            $this->line("  ├─ Name:  {$admin->name}");
            $this->line("  ├─ Email: {$admin->email}");
            $this->line('  ├─ Role:  Super Administrator');
            $this->line('  └─ Panel: /sysadmin');
            $this->newLine();
            $this->line('  You can now log in at: '.url('/sysadmin'));
            $this->newLine();

            return self::SUCCESS;
        } catch (Throwable $e) {
            $this->error('Failed to create system administrator:');
            $this->line($e->getMessage());

            if ($this->option('verbose')) {
                $this->newLine();
                $this->line($e->getTraceAsString());
            }

            return self::FAILURE;
        }
    }
}


================================================
FILE: app/Console/Commands/GenerateSitemapCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Spatie\Sitemap\SitemapGenerator;

final class GenerateSitemapCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:generate-sitemap';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate the sitemap';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        SitemapGenerator::create(config('app.url'))
            ->writeToFile(public_path('sitemap.xml'));
    }
}


================================================
FILE: app/Console/Commands/InstallCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Process;
use Relaticle\SystemAdmin\Enums\SystemAdministratorRole;
use Relaticle\SystemAdmin\Models\SystemAdministrator;
use Throwable;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\select;
use function Laravel\Prompts\spin;
use function Laravel\Prompts\text;
use function Laravel\Prompts\warning;

final class InstallCommand extends Command
{
    protected $signature = 'relaticle:install
                            {--force : Force installation even if already configured}
                            {--env-file= : Custom path to .env file (for testing)}';

    protected $description = 'Install and configure Relaticle';

    public function handle(): int
    {
        $this->displayWelcome();

        if (! $this->shouldProceed()) {
            return self::SUCCESS;
        }

        $config = $this->getConfiguration();

        return $this->runInstallation($config);
    }

    private function displayWelcome(): void
    {
        $this->output->write(PHP_EOL.'  <fg=cyan>
 ____      _       _   _      _
|  _ \ ___| | __ _| |_(_) ___| | ___
| |_) / _ \ |/ _` | __| |/ __| |/ _ \
|  _ <  __/ | (_| | |_| | (__| |  __/
|_| \_\___|_|\__,_|\__|_|\___|_|\___|</>'.PHP_EOL.PHP_EOL);
    }

    private function shouldProceed(): bool
    {
        if (! $this->option('force') && $this->isAlreadyInstalled()) {
            warning('Relaticle appears to be already installed.');

            return confirm(
                label: 'Do you want to continue anyway?',
                default: false,
                hint: 'This may overwrite existing configuration'
            );
        }

        return true;
    }

    private function isAlreadyInstalled(): bool
    {
        return File::exists($this->envPath()) &&
               config('app.key') &&
               File::exists(public_path('storage'));
    }

    /** @return array<string, mixed> */
    private function getConfiguration(): array
    {
        $this->info('Let\'s configure your Relaticle installation...');

        $database = select(
            label: 'Which database would you like to use?',
            options: [
                'sqlite' => 'SQLite (Recommended for local development)',
                'pgsql' => 'PostgreSQL (Recommended for production)',
            ],
            default: 'sqlite',
            hint: 'SQLite requires no additional setup'
        );

        $installDemoData = confirm(
            label: 'Install demo data?',
            default: true,
            hint: 'Includes sample companies, contacts, and more'
        );

        $createSysAdmin = confirm(
            label: 'Create system administrator account?',
            default: true,
            hint: 'You can create one later using: php artisan sysadmin:create'
        );

        return [
            'database' => $database,
            'demo_data' => $installDemoData,
            'sysadmin_user' => $createSysAdmin,
        ];
    }

    /** @param array<string, mixed> $config */
    private function runInstallation(array $config): int
    {
        /** @var array<string, callable(): bool> */
        $installationSteps = [
            'System Requirements' => $this->checkSystemRequirements(...),
            'Environment Setup' => fn (): bool => $this->setupEnvironment($config),
            'Dependencies' => $this->installDependencies(...),
            'Database' => $this->setupDatabase(...),
            'Assets' => $this->buildAssets(...),
            'Storage' => $this->setupStorage(...),
            'Demo Data' => fn (): bool => $config['demo_data'] ? $this->seedDemoData() : true,
        ];

        $this->info('🚀 Starting installation process...');

        // Process non-interactive steps with spinner
        foreach ($installationSteps as $stepName => $stepFunction) {
            $success = spin(
                callback: fn (): mixed => $stepFunction(),
                message: "Installing {$stepName}..."
            );

            if (! $success) {
                $this->newLine();
                $this->error("❌ Installation failed during: {$stepName}");
                $this->newLine();
                $this->line('<comment>Check the error messages above for more details.</comment>');
                $this->line('<comment>You can re-run the installer with --force to retry.</comment>');

                return self::FAILURE;
            }

            $this->line("   ✅ {$stepName} completed");
        }

        // Handle System Administrator creation separately (requires user interaction)
        if ($config['sysadmin_user']) {
            $this->newLine();
            $this->info('Creating System Administrator account...');

            if (! $this->createSystemAdministrator()) {
                $this->newLine();
                $this->error('❌ Installation failed during: System Administrator creation');
                $this->newLine();
                $this->line('<comment>You can create a system administrator later using: php artisan sysadmin:create</comment>');

                return self::FAILURE;
            }

            $this->line('   ✅ System Administrator created');
        }

        $this->newLine();
        $this->displaySuccessMessage($config);

        return self::SUCCESS;
    }

    private function checkSystemRequirements(): bool
    {
        $requirements = [
            'PHP 8.4+' => version_compare(PHP_VERSION, '8.3.0', '>='),
            'Composer' => $this->commandExists('composer'),
            'Node.js' => $this->commandExists('node'),
            'NPM' => $this->commandExists('npm'),
        ];

        $extensions = [
            'pdo_sqlite', 'gd', 'bcmath', 'ctype', 'fileinfo',
            'json', 'mbstring', 'openssl', 'tokenizer', 'xml',
        ];

        foreach ($extensions as $extension) {
            $requirements["PHP {$extension}"] = extension_loaded($extension);
        }

        $failed = array_filter($requirements, fn (bool $passed): bool => ! $passed);

        if ($failed !== []) {
            $this->newLine();
            $this->error('✗ Missing system requirements:');
            foreach (array_keys($failed) as $requirement) {
                $this->line("  • {$requirement}");
            }
            $this->newLine();
            $this->line('<comment>Please install the missing requirements and try again.</comment>');

            return false;
        }

        return true;
    }

    private function commandExists(string $command): bool
    {
        return Process::run("which {$command} 2>/dev/null")->successful();
    }

    /** @param array<string, mixed> $config */
    private function setupEnvironment(array $config): bool
    {
        // Create .env file
        if (! File::exists($this->envPath())) {
            if (! File::exists(base_path('.env.example'))) {
                return false;
            }
            File::copy(base_path('.env.example'), $this->envPath());
        }

        // Generate app key
        if (! config('app.key')) {
            Artisan::call('key:generate', ['--force' => true]);
        }

        // Configure database
        return $this->configureDatabaseConnection($config['database']);
    }

    private function configureDatabaseConnection(string $type): bool
    {
        $envContent = File::get($this->envPath());

        if ($type === 'sqlite') {
            if (! File::exists(database_path())) {
                File::makeDirectory(database_path(), 0755, true);
            }

            $dbPath = database_path('database.sqlite');
            if (! File::exists($dbPath)) {
                File::put($dbPath, '');
            }

            $config = [
                'DB_CONNECTION=sqlite',
                "DB_DATABASE={$dbPath}",
                'DB_HOST=',
                'DB_PORT=',
                'DB_USERNAME=',
                'DB_PASSWORD=',
            ];
        } else {
            // For non-SQLite, we'll use the existing .env values or prompt if needed
            return true;
        }

        foreach ($config as $line) {
            [$key, $value] = explode('=', $line, 2);
            $envContent = preg_replace("/^{$key}=.*/m", $line, (string) $envContent);
        }

        File::put($this->envPath(), $envContent);

        return true;
    }

    private function installDependencies(): bool
    {
        $composerResult = Process::run('composer install --no-interaction --prefer-dist --optimize-autoloader');
        if (! $composerResult->successful()) {
            $this->error('Composer install failed:');
            $this->line($composerResult->errorOutput());

            return false;
        }

        $npmResult = Process::run('npm ci --silent');
        if (! $npmResult->successful()) {
            $this->error('NPM install failed:');
            $this->line($npmResult->errorOutput());

            return false;
        }

        return true;
    }

    private function setupDatabase(): bool
    {
        try {
            Artisan::call('migrate', ['--force' => true]);

            return true;
        } catch (Throwable $e) {
            $this->error('Database migration failed:');
            $this->line($e->getMessage());

            return false;
        }
    }

    private function buildAssets(): bool
    {
        $result = Process::run('npm run build');

        if (! $result->successful()) {
            $this->error('Asset compilation failed:');
            $this->line($result->errorOutput());

            return false;
        }

        return true;
    }

    private function setupStorage(): bool
    {
        try {
            Artisan::call('storage:link', ['--force' => true]);

            return true;
        } catch (Throwable $e) {
            $this->error('Storage link failed:');
            $this->line($e->getMessage());

            return false;
        }
    }

    private function seedDemoData(): bool
    {
        try {
            // When using --force, we might be re-running installation
            // Use migrate:fresh to reset the database cleanly
            if ($this->option('force')) {
                Artisan::call('migrate:fresh', ['--force' => true]);
            }

            Artisan::call('db:seed', ['--force' => true]);

            return true;
        } catch (Throwable $e) {
            $this->error('Demo data seeding failed:');
            $this->line($e->getMessage());

            return false;
        }
    }

    private function createSystemAdministrator(): bool
    {
        try {
            // Check if system administrator already exists
            if (SystemAdministrator::query()->exists()) {
                $this->warn('A System Administrator already exists.');
                $overwrite = confirm(
                    label: 'Do you want to create another one?',
                    default: false,
                    hint: 'You can have multiple system administrators'
                );

                if (! $overwrite) {
                    return true;
                }
            }

            $name = text(
                label: 'System Administrator name',
                default: 'System Admin',
                required: true
            );

            $email = text(
                label: 'System Administrator email address',
                default: 'sysadmin@relaticle.local',
                required: true,
                validate: fn (string $value): ?string => filter_var($value, FILTER_VALIDATE_EMAIL) ? null : 'Please enter a valid email address'
            );

            // Check if email already exists
            if (SystemAdministrator::query()->where('email', $email)->exists()) {
                $this->error("A System Administrator with email '{$email}' already exists.");

                return false;
            }

            $password = text(
                label: 'System Administrator password (min. 8 characters)',
                default: 'password123',
                required: true,
                validate: fn (string $value): ?string => strlen($value) >= 8 ? null : 'Password must be at least 8 characters'
            );

            // Create the system administrator
            SystemAdministrator::query()->create([
                'name' => $name,
                'email' => $email,
                'password' => bcrypt($password),
                'email_verified_at' => now(),
                'role' => SystemAdministratorRole::SuperAdministrator,
            ]);

            $this->info('  System Administrator created successfully!');
            $this->line("  Email: {$email}");
            $this->line('  Access panel at: /sysadmin');

            return true;
        } catch (Throwable $e) {
            $this->error('System Administrator creation failed:');
            $this->line($e->getMessage());

            return false;
        }
    }

    /** @param array<string, mixed> $config */
    private function displaySuccessMessage(array $config): void
    {
        $this->newLine();

        $this->info('🎉 Relaticle installed successfully!');

        $this->newLine();
        $this->line('  <options=bold>Start all development services:</>');
        $this->line('  composer run dev');
        $this->newLine();

        $this->line('  <options=bold>Your application:</>');
        $this->line('  http://localhost:8000');

        if ($config['sysadmin_user'] ?? false) {
            $this->newLine();
            $this->line('  <options=bold>System Admin panel:</>');
            $this->line('  http://localhost:8000/sysadmin');
        }

        if ($config['demo_data']) {
            $this->newLine();
            $this->line('  <options=bold>Demo data included:</>');
            $this->line('  • Sample companies and contacts');
            $this->line('  • Example opportunities and tasks');
            $this->line('  • Pre-configured custom fields');
        }

        $this->newLine();
        $this->line('  <options=bold>Development services:</>');
        $this->line('  • Laravel development server');
        $this->line('  • Vite asset watcher with HMR');
        $this->line('  • Queue worker (Horizon)');
        $this->line('  • Real-time logs (Pail)');

        $this->newLine();
        $this->line('  Documentation: https://relaticle.com/documentation');
        $this->newLine();

        $this->info('Happy CRM-ing! 🚀');
    }

    private function envPath(): string
    {
        return $this->option('env-file') ?: base_path('.env');
    }
}


================================================
FILE: app/Contracts/User/CreatesNewSocialUsers.php
================================================
<?php

declare(strict_types=1);

namespace App\Contracts\User;

use App\Models\User;

interface CreatesNewSocialUsers
{
    /**
     * Create a new social user.
     *
     * @param  array<string, string>  $input
     */
    public function create(array $input): User;
}


================================================
FILE: app/Data/SubscriberData.php
================================================
<?php

declare(strict_types=1);

namespace App\Data;

use Spatie\LaravelData\Data;

final class SubscriberData extends Data
{
    public function __construct(
        public string $email,
        public ?string $first_name = '',
        public ?string $last_name = '',
        /** @var array<string> */
        public ?array $tags = [],
        public bool $skip_confirmation = true,
    ) {}
}


================================================
FILE: app/Enums/CreationSource.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Filament\Support\Contracts\HasColor;
use Filament\Support\Contracts\HasLabel;

enum CreationSource: string implements HasColor, HasLabel
{
    /**
     * Created through the web application interface by a user.
     * This includes records created through forms, dashboards, and
     * admin interfaces where a user directly inputs the data.
     */
    case WEB = 'web';

    /**
     * Created by automated system processes without direct user action.
     * Examples include scheduled jobs, event-triggered workflows,
     * and background processes that generate records automatically.
     */
    case SYSTEM = 'system';

    /**
     * Created through bulk data import functionality.
     * This applies to records generated when users upload files
     * (CSV, Excel, etc.) through import tools or when data is
     * migrated from another system in bulk operations.
     */
    case IMPORT = 'import';

    /**
     * Created through the REST API.
     * This applies to records created by external integrations
     * and third-party applications using API tokens.
     */
    case API = 'api';

    /**
     * Created through the MCP server by AI agents.
     * This applies to records created via Model Context Protocol
     * tools, typically by AI assistants interacting with the system.
     */
    case MCP = 'mcp';

    public function getColor(): string
    {
        return match ($this) {
            self::WEB => 'info',
            self::SYSTEM => 'warning',
            self::IMPORT => 'success',
            self::API => 'purple',
            self::MCP => 'gray',
        };
    }

    public function getLabel(): string
    {
        return match ($this) {
            self::WEB => 'Web Interface',
            self::SYSTEM => 'System Process',
            self::IMPORT => 'Data Import',
            self::API => 'API',
            self::MCP => 'MCP Agent',
        };
    }
}


================================================
FILE: app/Enums/CustomFieldType.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

/**
 * ABOUTME: Maps to the field types available in the relaticle/custom-fields package
 * ABOUTME: Provides type-safe references to custom field types for maintainability
 */
enum CustomFieldType: string
{
    case TEXT = 'text';
    case NUMBER = 'number';
    case EMAIL = 'email';
    case PHONE = 'phone';
    case LINK = 'link';
    case TEXTAREA = 'textarea';
    case CHECKBOX = 'checkbox';
    case CHECKBOX_LIST = 'checkbox-list';
    case RADIO = 'radio';
    case RICH_EDITOR = 'rich-editor';
    case MARKDOWN_EDITOR = 'markdown-editor';
    case TAGS_INPUT = 'tags-input';
    case COLOR_PICKER = 'color-picker';
    case TOGGLE = 'toggle';
    case TOGGLE_BUTTONS = 'toggle-buttons';
    case CURRENCY = 'currency';
    case DATE = 'date';
    case DATE_TIME = 'date-time';
    case SELECT = 'select';
    case MULTI_SELECT = 'multi-select';
    case FILE_UPLOAD = 'file-upload';
    case RECORD = 'record';
}


================================================
FILE: app/Enums/CustomFields/CompanyField.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use App\Enums\CustomFieldType;

enum CompanyField: string
{
    use CustomFieldTrait;

    /**
     * Ideal Customer Profile: Indicates whether the company is the most suitable customer for you
     */
    case ICP = 'icp';

    /**
     * Domains: Website domains of the company (system field)
     */
    case DOMAINS = 'domains';

    /**
     * LinkedIn: The LinkedIn profile URL of the company
     */
    case LINKEDIN = 'linkedin';

    public function getDisplayName(): string
    {
        return match ($this) {
            self::ICP => 'ICP',
            self::DOMAINS => 'Domains',
            self::LINKEDIN => 'LinkedIn',
        };
    }

    public function getFieldType(): string
    {
        return match ($this) {
            self::ICP => CustomFieldType::TOGGLE->value,
            self::DOMAINS, self::LINKEDIN => CustomFieldType::LINK->value,
        };
    }

    public function isSystemDefined(): bool
    {
        return match ($this) {
            self::DOMAINS => true,
            default => false,
        };
    }

    public function isListToggleableHidden(): bool
    {
        return match ($this) {
            self::ICP, self::DOMAINS => false,
            default => true,
        };
    }

    public function getDescription(): string
    {
        return match ($this) {
            self::ICP => 'Indicates whether this company is an Ideal Customer Profile',
            self::DOMAINS => 'Website domains of the company (e.g., example.com)',
            self::LINKEDIN => 'URL to the company\'s LinkedIn profile',
        };
    }

    public function allowsMultipleValues(): bool
    {
        return match ($this) {
            self::DOMAINS => true,
            default => false,
        };
    }

    public function isUniquePerEntityType(): bool
    {
        return match ($this) {
            self::DOMAINS => true,
            default => false,
        };
    }
}


================================================
FILE: app/Enums/CustomFields/CustomFieldTrait.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use Illuminate\Support\Str;
use Relaticle\CustomFields\Enums\CustomFieldWidth;

/**
 * Trait for custom field enums to provide configuration data
 *
 * This trait provides a standardized interface for custom field enums
 * and default implementations for optional methods.
 */
trait CustomFieldTrait
{
    /**
     * Get the display name for the field
     *
     * @return string The human-readable name of the field
     */
    public function getDisplayName(): string
    {
        return Str::title($this->name);
    }

    /**
     * Get the field type
     *
     * @return string The type of form field to use
     */
    abstract public function getFieldType(): string;

    /**
     * Get whether this field is system defined
     *
     * System-defined fields cannot be deleted by users, only deactivated.
     *
     * @return bool True if the field is system defined
     */
    public function isSystemDefined(): bool
    {
        return true;
    }

    /**
     * Get whether the field is hidden in list toggle
     *
     * Fields that aren't toggleable hidden are always shown in lists.
     *
     * @return bool True if the field can be hidden in list view
     */
    public function isListToggleableHidden(): bool
    {
        return true;
    }

    /**
     * Get the field width
     *
     * @return CustomFieldWidth The width of the field or null for default width
     */
    public function getWidth(): CustomFieldWidth
    {
        return CustomFieldWidth::_100;
    }

    /**
     * Get options for select fields
     *
     * @return array<int|string, string>|null Array of options for select/multi-select fields or null if not applicable
     */
    public function getOptions(): ?array
    {
        return null;
    }

    /**
     * Get field description (tooltip)
     *
     * @return string|null The field description or null if not provided
     */
    public function getDescription(): ?string
    {
        return null;
    }

    /**
     * Get color mapping for select field options
     *
     * @return array<int|string, string>|null Array of option => color mappings or null if not applicable
     */
    public function getOptionColors(): ?array
    {
        return null;
    }

    /**
     * Get whether this field should have color options enabled
     *
     * @return bool True if color options should be enabled
     */
    public function hasColorOptions(): bool
    {
        return $this->getOptionColors() !== null;
    }

    /**
     * Get whether this field allows multiple values
     *
     * @return bool True if multiple values are allowed
     */
    public function allowsMultipleValues(): bool
    {
        return false;
    }

    /**
     * Get the maximum number of values allowed for this field
     *
     * @return int Maximum values (1 for single value fields)
     */
    public function getMaxValues(): int
    {
        return $this->allowsMultipleValues() ? 5 : 1;
    }

    /**
     * Get whether this field value must be unique per entity type
     *
     * @return bool True if values must be unique across all records of this entity type
     */
    public function isUniquePerEntityType(): bool
    {
        return false;
    }

    /**
     * Get complete field configuration
     *
     * @return array{
     *     name: string,
     *     type: string,
     *     systemDefined: bool,
     *     listToggleableHidden: bool,
     *     width: CustomFieldWidth|null,
     *     options: array<int|string, string>|null,
     *     description: string|null,
     *     optionColors: array<int|string, string>|null,
     *     hasColorOptions: bool,
     *     allowsMultipleValues: bool
     * } The complete field configuration
     */
    public function getConfiguration(): array
    {
        return [
            'name' => $this->getDisplayName(),
            'type' => $this->getFieldType(),
            'systemDefined' => $this->isSystemDefined(),
            'listToggleableHidden' => $this->isListToggleableHidden(),
            'width' => $this->getWidth(),
            'options' => $this->getOptions(),
            'description' => $this->getDescription(),
            'optionColors' => $this->getOptionColors(),
            'hasColorOptions' => $this->hasColorOptions(),
            'allowsMultipleValues' => $this->allowsMultipleValues(),
        ];
    }
}


================================================
FILE: app/Enums/CustomFields/NoteField.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use App\Enums\CustomFieldType;

/**
 * Note custom field codes
 */
enum NoteField: string
{
    use CustomFieldTrait;

    case BODY = 'body';

    public function getFieldType(): string
    {
        return match ($this) {
            self::BODY => CustomFieldType::RICH_EDITOR->value,
        };
    }

    public function getDisplayName(): string
    {
        return match ($this) {
            self::BODY => 'Body',
        };
    }

    public function isListToggleableHidden(): bool
    {
        return match ($this) {
            self::BODY => true,
        };
    }
}


================================================
FILE: app/Enums/CustomFields/OpportunityField.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use App\Enums\CustomFieldType;

enum OpportunityField: string
{
    use CustomFieldTrait;

    case AMOUNT = 'amount';
    case CLOSE_DATE = 'close_date';
    case STAGE = 'stage';

    /**
     * @return string[]|null
     */
    public function getOptions(): ?array
    {
        return match ($this) {
            self::STAGE => [
                'Prospecting',
                'Qualification',
                'Needs Analysis',
                'Value Proposition',
                'Id. Decision Makers',
                'Perception Analysis',
                'Proposal/Price Quote',
                'Negotiation/Review',
                'Closed Won',
                'Closed Lost',
            ],
            default => null,
        };
    }

    public function getFieldType(): string
    {
        return match ($this) {
            self::AMOUNT => CustomFieldType::CURRENCY->value,
            self::CLOSE_DATE => CustomFieldType::DATE->value,
            self::STAGE => CustomFieldType::SELECT->value,
        };
    }

    public function getDisplayName(): string
    {
        return match ($this) {
            self::AMOUNT => 'Amount',
            self::CLOSE_DATE => 'Close Date',
            self::STAGE => 'Stage',
        };
    }

    public function isListToggleableHidden(): bool
    {
        return false;
    }

    /**
     * Get color mapping for select field options
     *
     * 2024 Sophisticated Sales Journey - A unique emotional progression through the
     * pipeline using earth-inspired, professional colors that tell the story of
     * building energy, trust, and momentum from first contact to final outcome.
     * Based on latest color psychology and 2024 design sophistication trends.
     *
     * @return array<int|string, string>|null Array of option => color mappings or null if not applicable
     */
    public function getOptionColors(): ?array
    {
        return match ($this) {
            self::STAGE => [
                'Prospecting' => '#a5b4fc',           // Misty Dawn - Soft exploration of possibilities
                'Qualification' => '#1e40af',         // Ocean Depth - Deep analytical thinking
                'Needs Analysis' => '#0d9488',        // Teal Understanding - Empathy & insight
                'Value Proposition' => '#eab308',     // Golden Clarity - Bright ideas & value
                'Id. Decision Makers' => '#7c3aed',   // Royal Authority - Power & influence
                'Perception Analysis' => '#f59e0b',   // Warm Amber - Comfortable evaluation
                'Proposal/Price Quote' => '#1e293b',  // Professional Navy - Serious business
                'Negotiation/Review' => '#f97316',    // Electric Coral - Dynamic energy
                'Closed Won' => '#059669',            // Victory Emerald - Success celebration
                'Closed Lost' => '#6b7280',           // Silver Acceptance - Respectful closure
            ],
            default => null,
        };
    }
}


================================================
FILE: app/Enums/CustomFields/PeopleField.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use App\Enums\CustomFieldType;

/**
 * People custom field codes
 */
enum PeopleField: string
{
    use CustomFieldTrait;

    case EMAILS = 'emails';
    case PHONE_NUMBER = 'phone_number';
    case JOB_TITLE = 'job_title';
    case LINKEDIN = 'linkedin';

    public function getFieldType(): string
    {
        return match ($this) {
            self::EMAILS => CustomFieldType::EMAIL->value,
            self::PHONE_NUMBER => CustomFieldType::PHONE->value,
            self::JOB_TITLE => CustomFieldType::TEXT->value,
            self::LINKEDIN => CustomFieldType::LINK->value,
        };
    }

    public function getDisplayName(): string
    {
        return match ($this) {
            self::EMAILS => 'Emails',
            self::PHONE_NUMBER => 'Phone Number',
            self::JOB_TITLE => 'Job Title',
            self::LINKEDIN => 'LinkedIn',
        };
    }

    public function isListToggleableHidden(): bool
    {
        return match ($this) {
            self::JOB_TITLE, self::EMAILS => false,
            default => true,
        };
    }

    public function isSystemDefined(): bool
    {
        return match ($this) {
            self::EMAILS => true,
            default => false,
        };
    }

    public function allowsMultipleValues(): bool
    {
        return match ($this) {
            self::EMAILS => true,
            default => false,
        };
    }

    public function isUniquePerEntityType(): bool
    {
        return match ($this) {
            self::EMAILS => true,
            default => false,
        };
    }
}


================================================
FILE: app/Enums/CustomFields/TaskField.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums\CustomFields;

use App\Enums\CustomFieldType;
use Relaticle\CustomFields\Enums\CustomFieldWidth;

enum TaskField: string
{
    use CustomFieldTrait;

    /**
     * Task status tracking
     */
    case STATUS = 'status';

    /**
     * Task priority level
     */
    case PRIORITY = 'priority';

    /**
     * Detailed task description
     */
    case DESCRIPTION = 'description';

    /**
     * Task due date and time
     */
    case DUE_DATE = 'due_date';

    /**
     * Get the display name for the field
     *
     * @return string The human-readable field name
     */
    public function getDisplayName(): string
    {
        return match ($this) {
            self::STATUS => 'Status',
            self::PRIORITY => 'Priority',
            self::DESCRIPTION => 'Description',
            self::DUE_DATE => 'Due Date',
        };
    }

    /**
     * Get the field type
     *
     * @return string The type of form control to use
     */
    public function getFieldType(): string
    {
        return match ($this) {
            self::STATUS, self::PRIORITY => CustomFieldType::SELECT->value,
            self::DESCRIPTION => CustomFieldType::RICH_EDITOR->value,
            self::DUE_DATE => CustomFieldType::DATE_TIME->value,
        };
    }

    /**
     * Get whether this field is system defined
     *
     * @return bool True if the field is system defined
     */
    public function isSystemDefined(): bool
    {
        return match ($this) {
            self::STATUS, self::PRIORITY => true,
            default => false,
        };
    }

    /**
     * Get whether the field is hidden in list toggle
     *
     * @return bool True if the field can be hidden in list view
     */
    public function isListToggleableHidden(): bool
    {
        return match ($this) {
            self::STATUS, self::PRIORITY, self::DUE_DATE => false,
            default => true,
        };
    }

    /**
     * Get the field width
     *
     * @return CustomFieldWidth The width of the field or null for default width
     */
    public function getWidth(): CustomFieldWidth
    {
        return match ($this) {
            self::STATUS, self::PRIORITY => CustomFieldWidth::_50,
            default => CustomFieldWidth::_100,
        };
    }

    /**
     * Get available options for this field
     *
     * @return array<int|string, string>|null Array of options for select/multi-select fields or null if not applicable
     */
    public function getOptions(): ?array
    {
        return match ($this) {
            self::STATUS => [
                'To do',
                'In progress',
                'Done',
            ],
            self::PRIORITY => [
                'Low',
                'Medium',
                'High',
            ],
            default => null,
        };
    }

    /**
     * Get color mapping for select field options
     *
     * 2024 sophisticated color psychology system - completely unique colors designed for
     * emotional resonance and semantic meaning. Based on latest color trends including
     * Digital Lavender, Mocha Mousse sophistication, and retro-futuristic aesthetics.
     *
     * @return array<int|string, string>|null Array of option => color mappings or null if not applicable
     */
    public function getOptionColors(): ?array
    {
        return match ($this) {
            self::STATUS => [
                'To do' => '#c4b5fd',       // Soft Periwinkle - Digital Lavender inspired calm potential
                'In progress' => '#0A80EA', // Professional Blue - Clear active progress state
                'Done' => '#2A9764',        // Success Green - Confident completion achievement
            ],
            self::PRIORITY => [
                'Low' => '#94a3b8',         // Sage Whisper - Natural earth tone, subtle presence
                'Medium' => '#d4a574',      // Burnished Gold - Mocha Mousse warmth & confidence
                'High' => '#dc2626',        // Crimson Velvet - Sophisticated urgent co
Download .txt
gitextract_xr43z_zf/

├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .githooks/
│   └── pre-commit
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug_report.yml
│   │   └── config.yml
│   ├── copilot-instructions.md
│   └── workflows/
│       ├── docker-publish.yml
│       ├── filament-view-monitor-simple.yml
│       └── tests.yml
├── .gitignore
├── CLAUDE.md
├── Dockerfile
├── LICENSE
├── README.md
├── TODOS.md
├── app/
│   ├── Actions/
│   │   ├── Company/
│   │   │   ├── CreateCompany.php
│   │   │   ├── DeleteCompany.php
│   │   │   ├── ListCompanies.php
│   │   │   └── UpdateCompany.php
│   │   ├── Fortify/
│   │   │   ├── CreateNewSocialUser.php
│   │   │   ├── PasswordValidationRules.php
│   │   │   ├── ResetUserPassword.php
│   │   │   ├── UpdateUserPassword.php
│   │   │   └── UpdateUserProfileInformation.php
│   │   ├── Jetstream/
│   │   │   ├── AddTeamMember.php
│   │   │   ├── CreateTeam.php
│   │   │   ├── DeleteTeam.php
│   │   │   ├── DeleteUser.php
│   │   │   ├── InviteTeamMember.php
│   │   │   ├── RemoveTeamMember.php
│   │   │   └── UpdateTeamName.php
│   │   ├── Note/
│   │   │   ├── CreateNote.php
│   │   │   ├── DeleteNote.php
│   │   │   ├── ListNotes.php
│   │   │   └── UpdateNote.php
│   │   ├── Opportunity/
│   │   │   ├── CreateOpportunity.php
│   │   │   ├── DeleteOpportunity.php
│   │   │   ├── ListOpportunities.php
│   │   │   └── UpdateOpportunity.php
│   │   ├── People/
│   │   │   ├── CreatePeople.php
│   │   │   ├── DeletePeople.php
│   │   │   ├── ListPeople.php
│   │   │   └── UpdatePeople.php
│   │   └── Task/
│   │       ├── CreateTask.php
│   │       ├── DeleteTask.php
│   │       ├── ListTasks.php
│   │       ├── NotifyTaskAssignees.php
│   │       └── UpdateTask.php
│   ├── Concerns/
│   │   └── DetectsTeamInvitation.php
│   ├── Console/
│   │   └── Commands/
│   │       ├── BackfillCustomFieldColorsCommand.php
│   │       ├── CleanupExpiredInvitationsCommand.php
│   │       ├── CreateSystemAdminCommand.php
│   │       ├── GenerateSitemapCommand.php
│   │       └── InstallCommand.php
│   ├── Contracts/
│   │   └── User/
│   │       └── CreatesNewSocialUsers.php
│   ├── Data/
│   │   └── SubscriberData.php
│   ├── Enums/
│   │   ├── CreationSource.php
│   │   ├── CustomFieldType.php
│   │   ├── CustomFields/
│   │   │   ├── CompanyField.php
│   │   │   ├── CustomFieldTrait.php
│   │   │   ├── NoteField.php
│   │   │   ├── OpportunityField.php
│   │   │   ├── PeopleField.php
│   │   │   └── TaskField.php
│   │   ├── SocialiteProvider.php
│   │   └── SubscriberTagEnum.php
│   ├── Filament/
│   │   ├── Actions/
│   │   │   └── GenerateRecordSummaryAction.php
│   │   ├── Components/
│   │   │   └── Infolists/
│   │   │       └── AvatarName.php
│   │   ├── Exports/
│   │   │   ├── BaseExporter.php
│   │   │   ├── CompanyExporter.php
│   │   │   ├── NoteExporter.php
│   │   │   ├── OpportunityExporter.php
│   │   │   ├── PeopleExporter.php
│   │   │   └── TaskExporter.php
│   │   ├── Pages/
│   │   │   ├── AccessTokens.php
│   │   │   ├── Auth/
│   │   │   │   ├── Login.php
│   │   │   │   └── Register.php
│   │   │   ├── CreateTeam.php
│   │   │   ├── EditProfile.php
│   │   │   ├── EditTeam.php
│   │   │   ├── OpportunitiesBoard.php
│   │   │   └── TasksBoard.php
│   │   └── Resources/
│   │       ├── CompanyResource/
│   │       │   ├── Pages/
│   │       │   │   ├── ListCompanies.php
│   │       │   │   └── ViewCompany.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       ├── PeopleRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── CompanyResource.php
│   │       ├── NoteResource/
│   │       │   ├── Forms/
│   │       │   │   └── NoteForm.php
│   │       │   └── Pages/
│   │       │       └── ManageNotes.php
│   │       ├── NoteResource.php
│   │       ├── OpportunityResource/
│   │       │   ├── Forms/
│   │       │   │   └── OpportunityForm.php
│   │       │   ├── Pages/
│   │       │   │   ├── ListOpportunities.php
│   │       │   │   └── ViewOpportunity.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── OpportunityResource.php
│   │       ├── PeopleResource/
│   │       │   ├── Pages/
│   │       │   │   ├── ListPeople.php
│   │       │   │   └── ViewPeople.php
│   │       │   └── RelationManagers/
│   │       │       ├── NotesRelationManager.php
│   │       │       └── TasksRelationManager.php
│   │       ├── PeopleResource.php
│   │       ├── TaskResource/
│   │       │   ├── Forms/
│   │       │   │   └── TaskForm.php
│   │       │   └── Pages/
│   │       │       └── ManageTasks.php
│   │       └── TaskResource.php
│   ├── Health/
│   │   └── AnthropicModelCheck.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── AcceptTeamInvitationController.php
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── CompaniesController.php
│   │   │   │       ├── CustomFieldsController.php
│   │   │   │       ├── NotesController.php
│   │   │   │       ├── OpportunitiesController.php
│   │   │   │       ├── PeopleController.php
│   │   │   │       └── TasksController.php
│   │   │   ├── Auth/
│   │   │   │   ├── CallbackController.php
│   │   │   │   └── RedirectController.php
│   │   │   ├── ContactController.php
│   │   │   ├── HomeController.php
│   │   │   ├── PrivacyPolicyController.php
│   │   │   └── TermsOfServiceController.php
│   │   ├── Middleware/
│   │   │   ├── ApplyTenantScopes.php
│   │   │   ├── EnsureTokenHasAbility.php
│   │   │   ├── ForceJsonResponse.php
│   │   │   ├── SetApiTeamContext.php
│   │   │   ├── SubdomainRootResponse.php
│   │   │   └── ValidateSignature.php
│   │   ├── Requests/
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── IndexCustomFieldsRequest.php
│   │   │   │       ├── IndexRequest.php
│   │   │   │       ├── StoreCompanyRequest.php
│   │   │   │       ├── StoreNoteRequest.php
│   │   │   │       ├── StoreOpportunityRequest.php
│   │   │   │       ├── StorePeopleRequest.php
│   │   │   │       ├── StoreTaskRequest.php
│   │   │   │       ├── UpdateCompanyRequest.php
│   │   │   │       ├── UpdateNoteRequest.php
│   │   │   │       ├── UpdateOpportunityRequest.php
│   │   │   │       ├── UpdatePeopleRequest.php
│   │   │   │       └── UpdateTaskRequest.php
│   │   │   └── ContactRequest.php
│   │   ├── Resources/
│   │   │   └── V1/
│   │   │       ├── CompanyResource.php
│   │   │       ├── Concerns/
│   │   │       │   └── FormatsCustomFields.php
│   │   │       ├── CustomFieldResource.php
│   │   │       ├── NoteResource.php
│   │   │       ├── OpportunityResource.php
│   │   │       ├── PeopleResource.php
│   │   │       ├── TaskResource.php
│   │   │       └── UserResource.php
│   │   └── Responses/
│   │       └── LoginResponse.php
│   ├── Jobs/
│   │   ├── Email/
│   │   │   ├── CreateSubscriberJob.php
│   │   │   └── UpdateSubscriberJob.php
│   │   └── FetchFaviconForCompany.php
│   ├── Listeners/
│   │   ├── CreateTeamCustomFields.php
│   │   ├── Email/
│   │   │   └── NewSubscriberListener.php
│   │   └── SwitchTeam.php
│   ├── Livewire/
│   │   ├── App/
│   │   │   ├── AccessTokens/
│   │   │   │   ├── CreateAccessToken.php
│   │   │   │   └── ManageAccessTokens.php
│   │   │   ├── Profile/
│   │   │   │   ├── DeleteAccount.php
│   │   │   │   ├── LogoutOtherBrowserSessions.php
│   │   │   │   ├── UpdatePassword.php
│   │   │   │   └── UpdateProfileInformation.php
│   │   │   └── Teams/
│   │   │       ├── AddTeamMember.php
│   │   │       ├── DeleteTeam.php
│   │   │       ├── PendingTeamInvitations.php
│   │   │       ├── TeamMembers.php
│   │   │       └── UpdateTeamName.php
│   │   ├── BaseLivewireComponent.php
│   │   └── UpdateProfileInformationForm.php
│   ├── Mail/
│   │   └── NewContactSubmissionMail.php
│   ├── Mcp/
│   │   ├── Filters/
│   │   │   ├── CustomFieldFilter.php
│   │   │   └── CustomFieldSort.php
│   │   ├── Prompts/
│   │   │   └── CrmOverviewPrompt.php
│   │   ├── Resources/
│   │   │   ├── CompanySchemaResource.php
│   │   │   ├── Concerns/
│   │   │   │   └── ResolvesEntitySchema.php
│   │   │   ├── CrmSummaryResource.php
│   │   │   ├── NoteSchemaResource.php
│   │   │   ├── OpportunitySchemaResource.php
│   │   │   ├── PeopleSchemaResource.php
│   │   │   └── TaskSchemaResource.php
│   │   ├── Schema/
│   │   │   └── CustomFieldFilterSchema.php
│   │   ├── Servers/
│   │   │   └── RelaticleServer.php
│   │   └── Tools/
│   │       ├── BaseAttachTool.php
│   │       ├── BaseCreateTool.php
│   │       ├── BaseDeleteTool.php
│   │       ├── BaseDetachTool.php
│   │       ├── BaseListTool.php
│   │       ├── BaseShowTool.php
│   │       ├── BaseUpdateTool.php
│   │       ├── Company/
│   │       │   ├── CreateCompanyTool.php
│   │       │   ├── DeleteCompanyTool.php
│   │       │   ├── GetCompanyTool.php
│   │       │   ├── ListCompaniesTool.php
│   │       │   └── UpdateCompanyTool.php
│   │       ├── Concerns/
│   │       │   ├── BuildsRelationshipResponse.php
│   │       │   ├── ChecksTokenAbility.php
│   │       │   └── SerializesRelatedModels.php
│   │       ├── Note/
│   │       │   ├── AttachNoteToEntitiesTool.php
│   │       │   ├── CreateNoteTool.php
│   │       │   ├── DeleteNoteTool.php
│   │       │   ├── DetachNoteFromEntitiesTool.php
│   │       │   ├── GetNoteTool.php
│   │       │   ├── ListNotesTool.php
│   │       │   └── UpdateNoteTool.php
│   │       ├── Opportunity/
│   │       │   ├── CreateOpportunityTool.php
│   │       │   ├── DeleteOpportunityTool.php
│   │       │   ├── GetOpportunityTool.php
│   │       │   ├── ListOpportunitiesTool.php
│   │       │   └── UpdateOpportunityTool.php
│   │       ├── People/
│   │       │   ├── CreatePeopleTool.php
│   │       │   ├── DeletePeopleTool.php
│   │       │   ├── GetPeopleTool.php
│   │       │   ├── ListPeopleTool.php
│   │       │   └── UpdatePeopleTool.php
│   │       ├── Task/
│   │       │   ├── AttachTaskToEntitiesTool.php
│   │       │   ├── CreateTaskTool.php
│   │       │   ├── DeleteTaskTool.php
│   │       │   ├── DetachTaskFromEntitiesTool.php
│   │       │   ├── GetTaskTool.php
│   │       │   ├── ListTasksTool.php
│   │       │   └── UpdateTaskTool.php
│   │       └── WhoAmiTool.php
│   ├── Models/
│   │   ├── AiSummary.php
│   │   ├── Company.php
│   │   ├── Concerns/
│   │   │   ├── BelongsToTeamCreator.php
│   │   │   ├── HasAiSummary.php
│   │   │   ├── HasCreator.php
│   │   │   ├── HasNotes.php
│   │   │   ├── HasProfilePhoto.php
│   │   │   ├── HasTeam.php
│   │   │   └── InvalidatesRelatedAiSummaries.php
│   │   ├── CustomField.php
│   │   ├── CustomFieldOption.php
│   │   ├── CustomFieldSection.php
│   │   ├── CustomFieldValue.php
│   │   ├── Export.php
│   │   ├── Membership.php
│   │   ├── Note.php
│   │   ├── Opportunity.php
│   │   ├── People.php
│   │   ├── PersonalAccessToken.php
│   │   ├── Scopes/
│   │   │   └── TeamScope.php
│   │   ├── Task.php
│   │   ├── Team.php
│   │   ├── TeamInvitation.php
│   │   ├── User.php
│   │   └── UserSocialAccount.php
│   ├── Observers/
│   │   ├── CompanyObserver.php
│   │   ├── NoteObserver.php
│   │   ├── OpportunityObserver.php
│   │   ├── PeopleObserver.php
│   │   └── TaskObserver.php
│   ├── Policies/
│   │   ├── CompanyPolicy.php
│   │   ├── NotePolicy.php
│   │   ├── OpportunityPolicy.php
│   │   ├── PeoplePolicy.php
│   │   ├── TaskPolicy.php
│   │   └── TeamPolicy.php
│   ├── Providers/
│   │   ├── AppServiceProvider.php
│   │   ├── FaviconServiceProvider.php
│   │   ├── Filament/
│   │   │   └── AppPanelProvider.php
│   │   ├── FortifyServiceProvider.php
│   │   ├── HealthServiceProvider.php
│   │   ├── HorizonServiceProvider.php
│   │   ├── JetstreamServiceProvider.php
│   │   └── MacroServiceProvider.php
│   ├── Rules/
│   │   ├── ValidCustomFields.php
│   │   └── ValidTeamSlug.php
│   ├── Scribe/
│   │   └── Strategies/
│   │       └── GetFromSpatieQueryBuilder.php
│   ├── Services/
│   │   ├── AI/
│   │   │   ├── RecordContextBuilder.php
│   │   │   └── RecordSummaryService.php
│   │   ├── AvatarService.php
│   │   ├── Favicon/
│   │   │   └── Drivers/
│   │   │       ├── GoogleHighResDriver.php
│   │   │       └── HighQualityDriver.php
│   │   └── GitHubService.php
│   ├── Support/
│   │   └── CustomFieldMerger.php
│   └── View/
│       └── Components/
│           └── GuestLayout.php
├── artisan
├── bootstrap/
│   ├── app.php
│   ├── cache/
│   │   └── .gitignore
│   └── providers.php
├── compose.dev.yml
├── compose.yml
├── composer.json
├── config/
│   ├── app.php
│   ├── auth.php
│   ├── avatar.php
│   ├── blade-icons.php
│   ├── cache.php
│   ├── custom-fields.php
│   ├── data.php
│   ├── database.php
│   ├── eloquent-sortable.php
│   ├── favicon-fetcher.php
│   ├── filament.php
│   ├── filesystems.php
│   ├── fortify.php
│   ├── health.php
│   ├── horizon-watcher.php
│   ├── horizon.php
│   ├── jetstream.php
│   ├── logging.php
│   ├── login-link.php
│   ├── mail.php
│   ├── mailcoach-sdk.php
│   ├── markdown-response.php
│   ├── markdown.php
│   ├── media-library.php
│   ├── prism.php
│   ├── queue.php
│   ├── relaticle.php
│   ├── sanctum.php
│   ├── scribe.php
│   ├── sentry.php
│   ├── services.php
│   ├── session.php
│   └── sitemap.php
├── database/
│   ├── .gitignore
│   ├── factories/
│   │   ├── CompanyFactory.php
│   │   ├── CustomFieldFactory.php
│   │   ├── NoteFactory.php
│   │   ├── OpportunityFactory.php
│   │   ├── PeopleFactory.php
│   │   ├── SystemAdministratorFactory.php
│   │   ├── TaskFactory.php
│   │   ├── TeamFactory.php
│   │   ├── TeamInvitationFactory.php
│   │   ├── UserFactory.php
│   │   └── UserSocialAccountFactory.php
│   ├── migrations/
│   │   ├── 0001_01_01_000000_create_users_table.php
│   │   ├── 0001_01_01_000001_create_cache_table.php
│   │   ├── 0001_01_01_000002_create_jobs_table.php
│   │   ├── 2024_08_23_110718_create_teams_table.php
│   │   ├── 2024_08_23_110719_create_team_user_table.php
│   │   ├── 2024_08_23_110720_create_team_invitations_table.php
│   │   ├── 2024_08_24_133803_create_companies_table.php
│   │   ├── 2024_09_11_114549_create_tasks_table.php
│   │   ├── 2024_09_22_084119_create_notes_table.php
│   │   ├── 2024_09_22_091034_create_people_table.php
│   │   ├── 2024_09_22_092300_create_task_user_table.php
│   │   ├── 2024_09_22_110651_add_two_factor_columns_to_users_table.php
│   │   ├── 2024_09_22_110718_create_personal_access_tokens_table.php
│   │   ├── 2024_09_22_114735_create_opportunities_table.php
│   │   ├── 2024_09_26_160649_create_user_social_accounts_table.php
│   │   ├── 2024_09_26_170133_create_notifications_table.php
│   │   ├── 2025_02_07_192236_create_custom_fields_table.php
│   │   ├── 2025_03_15_180559_create_taskables_table.php
│   │   ├── 2025_03_15_192334_create_notables_table.php
│   │   ├── 2025_03_17_180206_create_media_table.php
│   │   ├── 2025_04_30_143551_add_creation_source_to_entity_tables.php
│   │   ├── 2025_05_08_112613_create_imports_table.php
│   │   ├── 2025_05_08_112614_create_exports_table.php
│   │   ├── 2025_05_08_112615_create_failed_import_rows_table.php
│   │   ├── 2025_07_05_093310_update_opportunity_amount_field_type_to_currency.php
│   │   ├── 2025_08_12_202409_add_settings_to_custom_field_options_table.php
│   │   ├── 2025_08_25_173222_update_order_column_to_flowforge_position_for_tasks_and_opportunities.php
│   │   ├── 2025_08_26_124042_create_system_administrators_table.php
│   │   ├── 2025_11_30_202612_create_ai_summaries_table.php
│   │   ├── 2025_12_10_191207_update_people_emails_field_type_to_email.php
│   │   ├── 2025_12_11_000001_update_company_domain_name_settings.php
│   │   ├── 2025_12_20_000000_migrate_to_ulid.php
│   │   ├── 2025_12_27_122241_convert_order_column_to_decimal_and_regenerate_positions.php
│   │   ├── 2026_01_02_152157_update_phone_number_custom_fields_type.php
│   │   ├── 2026_01_12_225824_upgrade_custom_fields_to_v3.php
│   │   ├── 2026_02_11_232804_add_slug_to_teams_table.php
│   │   ├── 2026_02_12_222910_expand_imports_table.php
│   │   ├── 2026_02_13_002721_cleanup_imports_table.php
│   │   ├── 2026_02_15_214730_drop_sessions_user_id_foreign_key.php
│   │   ├── 2026_02_20_212853_add_team_id_to_personal_access_tokens_table.php
│   │   ├── 2026_02_25_124942_add_team_id_indexes_to_entity_tables.php
│   │   ├── 2026_03_15_201741_add_custom_field_value_filtering_indexes.php
│   │   └── 2026_03_18_202956_add_expires_at_to_team_invitations_table.php
│   └── seeders/
│       ├── DatabaseSeeder.php
│       ├── LocalSeeder.php
│       └── SystemAdministratorSeeder.php
├── lang/
│   └── en/
│       ├── access-tokens.php
│       ├── profile.php
│       └── teams.php
├── package.json
├── packages/
│   ├── Documentation/
│   │   ├── README.md
│   │   ├── config/
│   │   │   └── documentation.php
│   │   ├── resources/
│   │   │   ├── css/
│   │   │   │   └── documentation.css
│   │   │   ├── js/
│   │   │   │   └── documentation.js
│   │   │   ├── markdown/
│   │   │   │   ├── developer-guide.md
│   │   │   │   ├── getting-started.md
│   │   │   │   ├── import-guide.md
│   │   │   │   ├── mcp-guide.md
│   │   │   │   └── self-hosting-guide.md
│   │   │   └── views/
│   │   │       ├── components/
│   │   │       │   ├── card.blade.php
│   │   │       │   ├── layout.blade.php
│   │   │       │   └── search-form.blade.php
│   │   │       ├── index.blade.php
│   │   │       ├── search.blade.php
│   │   │       └── show.blade.php
│   │   ├── routes/
│   │   │   └── web.php
│   │   └── src/
│   │       ├── Components/
│   │       │   └── Card.php
│   │       ├── Data/
│   │       │   ├── DocumentData.php
│   │       │   ├── DocumentSearchRequest.php
│   │       │   └── DocumentSearchResultData.php
│   │       ├── DocumentationServiceProvider.php
│   │       ├── Http/
│   │       │   └── Controllers/
│   │       │       └── DocumentationController.php
│   │       └── Services/
│   │           └── DocumentationService.php
│   ├── ImportWizard/
│   │   ├── config/
│   │   │   └── import-wizard.php
│   │   ├── resources/
│   │   │   ├── lang/
│   │   │   │   └── en/
│   │   │   │       └── validation.php
│   │   │   └── views/
│   │   │       ├── components/
│   │   │       │   ├── field-select.blade.php
│   │   │       │   ├── multi-value-input.blade.php
│   │   │       │   ├── select-menu.blade.php
│   │   │       │   └── value-row-actions.blade.php
│   │   │       ├── filament/
│   │   │       │   └── pages/
│   │   │       │       ├── import-history.blade.php
│   │   │       │       └── import-page.blade.php
│   │   │       └── livewire/
│   │   │           ├── import-wizard.blade.php
│   │   │           ├── partials/
│   │   │           │   └── step-indicator.blade.php
│   │   │           └── steps/
│   │   │               ├── mapping-step.blade.php
│   │   │               ├── partials/
│   │   │               │   ├── value-row-choice.blade.php
│   │   │               │   ├── value-row-date.blade.php
│   │   │               │   ├── value-row-multi-value.blade.php
│   │   │               │   ├── value-row-number.blade.php
│   │   │               │   ├── value-row-skipped.blade.php
│   │   │               │   └── value-row-text.blade.php
│   │   │               ├── preview-step.blade.php
│   │   │               ├── review-step.blade.php
│   │   │               └── upload-step.blade.php
│   │   ├── routes/
│   │   │   └── web.php
│   │   └── src/
│   │       ├── Commands/
│   │       │   └── CleanupImportsCommand.php
│   │       ├── Data/
│   │       │   ├── ColumnData.php
│   │       │   ├── EntityLink.php
│   │       │   ├── ImportField.php
│   │       │   ├── ImportFieldCollection.php
│   │       │   ├── InferenceResult.php
│   │       │   ├── MatchableField.php
│   │       │   └── RelationshipMatch.php
│   │       ├── Enums/
│   │       │   ├── DateFormat.php
│   │       │   ├── EntityLinkSource.php
│   │       │   ├── EntityLinkStorage.php
│   │       │   ├── ImportEntityType.php
│   │       │   ├── ImportStatus.php
│   │       │   ├── MatchBehavior.php
│   │       │   ├── NumberFormat.php
│   │       │   ├── ReviewFilter.php
│   │       │   ├── RowMatchAction.php
│   │       │   ├── SortDirection.php
│   │       │   └── SortField.php
│   │       ├── Filament/
│   │       │   └── Pages/
│   │       │       ├── ImportCompanies.php
│   │       │       ├── ImportHistory.php
│   │       │       ├── ImportNotes.php
│   │       │       ├── ImportOpportunities.php
│   │       │       ├── ImportPage.php
│   │       │       ├── ImportPeople.php
│   │       │       └── ImportTasks.php
│   │       ├── Http/
│   │       │   └── Controllers/
│   │       │       └── DownloadFailedRowsController.php
│   │       ├── ImportWizardNewServiceProvider.php
│   │       ├── Importers/
│   │       │   ├── BaseImporter.php
│   │       │   ├── CompanyImporter.php
│   │       │   ├── Contracts/
│   │       │   │   └── ImporterContract.php
│   │       │   ├── NoteImporter.php
│   │       │   ├── OpportunityImporter.php
│   │       │   ├── PeopleImporter.php
│   │       │   └── TaskImporter.php
│   │       ├── Jobs/
│   │       │   ├── ExecuteImportJob.php
│   │       │   ├── ResolveMatchesJob.php
│   │       │   └── ValidateColumnJob.php
│   │       ├── Livewire/
│   │       │   ├── Concerns/
│   │       │   │   └── WithImportStore.php
│   │       │   ├── ImportWizard.php
│   │       │   └── Steps/
│   │       │       ├── MappingStep.php
│   │       │       ├── PreviewStep.php
│   │       │       ├── ReviewStep.php
│   │       │       └── UploadStep.php
│   │       ├── Models/
│   │       │   ├── FailedImportRow.php
│   │       │   └── Import.php
│   │       ├── Rules/
│   │       │   ├── ImportChoiceRule.php
│   │       │   ├── ImportDateRule.php
│   │       │   └── ImportNumberRule.php
│   │       ├── Store/
│   │       │   ├── ImportRow.php
│   │       │   └── ImportStore.php
│   │       └── Support/
│   │           ├── DataTypeInferencer.php
│   │           ├── EntityLinkResolver.php
│   │           ├── EntityLinkStorage/
│   │           │   ├── CustomFieldValueStorage.php
│   │           │   ├── EntityLinkStorageInterface.php
│   │           │   ├── ForeignKeyStorage.php
│   │           │   └── MorphToManyStorage.php
│   │           ├── EntityLinkValidator.php
│   │           ├── MatchResolver.php
│   │           └── Validation/
│   │               ├── ColumnValidator.php
│   │               └── ValidationError.php
│   ├── OnboardSeed/
│   │   ├── README.md
│   │   ├── resources/
│   │   │   ├── fixtures/
│   │   │   │   ├── companies/
│   │   │   │   │   ├── airbnb.yaml
│   │   │   │   │   ├── apple.yaml
│   │   │   │   │   ├── figma.yaml
│   │   │   │   │   └── notion.yaml
│   │   │   │   ├── notes/
│   │   │   │   │   ├── airbnb_note.yaml
│   │   │   │   │   ├── apple_note.yaml
│   │   │   │   │   ├── dylan_note.yaml
│   │   │   │   │   ├── figma_note.yaml
│   │   │   │   │   └── notion_note.yaml
│   │   │   │   ├── opportunities/
│   │   │   │   │   ├── airbnb_analytics.yaml
│   │   │   │   │   ├── apple_partnership.yaml
│   │   │   │   │   ├── figma_enterprise.yaml
│   │   │   │   │   └── notion_integration.yaml
│   │   │   │   ├── people/
│   │   │   │   │   ├── brian.yaml
│   │   │   │   │   ├── dylan.yaml
│   │   │   │   │   ├── ivan.yaml
│   │   │   │   │   └── tim.yaml
│   │   │   │   └── tasks/
│   │   │   │       ├── brian_call.yaml
│   │   │   │       ├── dylan_followup.yaml
│   │   │   │       ├── ivan_meeting.yaml
│   │   │   │       └── tim_proposal.yaml
│   │   │   └── templates/
│   │   │       └── entity_template.yaml
│   │   └── src/
│   │       ├── Contracts/
│   │       │   └── ModelSeederInterface.php
│   │       ├── ModelSeeders/
│   │       │   ├── CompanySeeder.php
│   │       │   ├── NoteSeeder.php
│   │       │   ├── OpportunitySeeder.php
│   │       │   ├── PeopleSeeder.php
│   │       │   └── TaskSeeder.php
│   │       ├── OnboardSeedManager.php
│   │       ├── OnboardSeeder.php
│   │       └── Support/
│   │           ├── BaseModelSeeder.php
│   │           ├── BulkCustomFieldValueWriter.php
│   │           ├── FixtureLoader.php
│   │           └── FixtureRegistry.php
│   └── SystemAdmin/
│       └── src/
│           ├── Enums/
│           │   └── SystemAdministratorRole.php
│           ├── Filament/
│           │   ├── Exports/
│           │   │   └── CompanyExporter.php
│           │   ├── Pages/
│           │   │   ├── Dashboard.php
│           │   │   └── EngagementDashboard.php
│           │   ├── Resources/
│           │   │   ├── CompanyResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateCompany.php
│           │   │   │       ├── EditCompany.php
│           │   │   │       ├── ListCompanies.php
│           │   │   │       └── ViewCompany.php
│           │   │   ├── CompanyResource.php
│           │   │   ├── ImportResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── ListImports.php
│           │   │   │   │   └── ViewImport.php
│           │   │   │   └── RelationManagers/
│           │   │   │       └── FailedRowsRelationManager.php
│           │   │   ├── ImportResource.php
│           │   │   ├── NoteResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateNote.php
│           │   │   │       ├── EditNote.php
│           │   │   │       ├── ListNotes.php
│           │   │   │       └── ViewNote.php
│           │   │   ├── NoteResource.php
│           │   │   ├── OpportunityResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateOpportunity.php
│           │   │   │       ├── EditOpportunity.php
│           │   │   │       ├── ListOpportunities.php
│           │   │   │       └── ViewOpportunity.php
│           │   │   ├── OpportunityResource.php
│           │   │   ├── PeopleResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreatePeople.php
│           │   │   │       ├── EditPeople.php
│           │   │   │       ├── ListPeople.php
│           │   │   │       └── ViewPeople.php
│           │   │   ├── PeopleResource.php
│           │   │   ├── SystemAdministrators/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateSystemAdministrator.php
│           │   │   │   │   ├── EditSystemAdministrator.php
│           │   │   │   │   ├── ListSystemAdministrators.php
│           │   │   │   │   └── ViewSystemAdministrator.php
│           │   │   │   ├── Schemas/
│           │   │   │   │   ├── SystemAdministratorForm.php
│           │   │   │   │   └── SystemAdministratorInfolist.php
│           │   │   │   ├── SystemAdministratorResource.php
│           │   │   │   └── Tables/
│           │   │   │       └── SystemAdministratorsTable.php
│           │   │   ├── TaskResource/
│           │   │   │   └── Pages/
│           │   │   │       ├── CreateTask.php
│           │   │   │       ├── EditTask.php
│           │   │   │       ├── ListTasks.php
│           │   │   │       └── ViewTask.php
│           │   │   ├── TaskResource.php
│           │   │   ├── TeamResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateTeam.php
│           │   │   │   │   ├── EditTeam.php
│           │   │   │   │   ├── ListTeams.php
│           │   │   │   │   └── ViewTeam.php
│           │   │   │   └── RelationManagers/
│           │   │   │       ├── CompaniesRelationManager.php
│           │   │   │       ├── MembersRelationManager.php
│           │   │   │       ├── NotesRelationManager.php
│           │   │   │       ├── OpportunitiesRelationManager.php
│           │   │   │       ├── PeopleRelationManager.php
│           │   │   │       └── TasksRelationManager.php
│           │   │   ├── TeamResource.php
│           │   │   ├── UserResource/
│           │   │   │   ├── Pages/
│           │   │   │   │   ├── CreateUser.php
│           │   │   │   │   ├── EditUser.php
│           │   │   │   │   ├── ListUsers.php
│           │   │   │   │   └── ViewUser.php
│           │   │   │   └── RelationManagers/
│           │   │   │       ├── OwnedTeamsRelationManager.php
│           │   │   │       └── TeamsRelationManager.php
│           │   │   └── UserResource.php
│           │   └── Widgets/
│           │       ├── ActivationRateWidget.php
│           │       ├── Concerns/
│           │       │   └── HasPeriodComparison.php
│           │       ├── PlatformGrowthStatsWidget.php
│           │       ├── RecordDistributionChartWidget.php
│           │       ├── SignupTrendChartWidget.php
│           │       ├── TopTeamsTableWidget.php
│           │       └── UserRetentionChartWidget.php
│           ├── Models/
│           │   └── SystemAdministrator.php
│           ├── Policies/
│           │   ├── CompanyPolicy.php
│           │   ├── FailedImportRowPolicy.php
│           │   ├── ImportPolicy.php
│           │   ├── NotePolicy.php
│           │   ├── OpportunityPolicy.php
│           │   ├── PeoplePolicy.php
│           │   ├── SystemAdministratorPolicy.php
│           │   ├── TaskPolicy.php
│           │   ├── TeamPolicy.php
│           │   └── UserPolicy.php
│           └── SystemAdminPanelProvider.php
├── phpstan.neon
├── phpunit.ci.xml
├── phpunit.xml
├── pint.json
├── public/
│   ├── .htaccess
│   ├── css/
│   │   ├── asmit/
│   │   │   └── resized-column/
│   │   │       └── resized-column.css
│   │   ├── filament/
│   │   │   ├── filament/
│   │   │   │   └── app.css
│   │   │   ├── forms/
│   │   │   │   └── forms.css
│   │   │   └── support/
│   │   │       └── support.css
│   │   └── relaticle/
│   │       ├── custom-fields/
│   │       │   └── custom-fields.css
│   │       └── flowforge/
│   │           └── flowforge.css
│   ├── fonts/
│   │   └── filament/
│   │       └── filament/
│   │           └── inter/
│   │               └── index.css
│   ├── index.php
│   ├── js/
│   │   ├── asmit/
│   │   │   └── resized-column/
│   │   │       └── resized-column.js
│   │   ├── filament/
│   │   │   ├── actions/
│   │   │   │   └── actions.js
│   │   │   ├── filament/
│   │   │   │   ├── app.js
│   │   │   │   └── echo.js
│   │   │   ├── forms/
│   │   │   │   └── components/
│   │   │   │       ├── checkbox-list.js
│   │   │   │       ├── code-editor.js
│   │   │   │       ├── color-picker.js
│   │   │   │       ├── date-time-picker.js
│   │   │   │       ├── file-upload.js
│   │   │   │       ├── key-value.js
│   │   │   │       ├── markdown-editor.js
│   │   │   │       ├── rich-editor.js
│   │   │   │       ├── select.js
│   │   │   │       ├── slider.js
│   │   │   │       ├── tags-input.js
│   │   │   │       └── textarea.js
│   │   │   ├── notifications/
│   │   │   │   └── notifications.js
│   │   │   ├── schemas/
│   │   │   │   ├── components/
│   │   │   │   │   ├── actions.js
│   │   │   │   │   ├── tabs.js
│   │   │   │   │   └── wizard.js
│   │   │   │   └── schemas.js
│   │   │   ├── support/
│   │   │   │   ├── async-alpine.js
│   │   │   │   └── support.js
│   │   │   ├── tables/
│   │   │   │   ├── components/
│   │   │   │   │   ├── columns/
│   │   │   │   │   │   ├── checkbox.js
│   │   │   │   │   │   ├── select.js
│   │   │   │   │   │   ├── text-input.js
│   │   │   │   │   │   └── toggle.js
│   │   │   │   │   └── table.js
│   │   │   │   └── tables.js
│   │   │   └── widgets/
│   │   │       └── components/
│   │   │           ├── chart.js
│   │   │           └── stats-overview/
│   │   │               └── stat/
│   │   │                   └── chart.js
│   │   └── relaticle/
│   │       └── flowforge/
│   │           ├── components/
│   │           │   └── flowforge.js
│   │           └── flowforge.js
│   ├── manifest.webmanifest
│   ├── robots.txt
│   └── site.webmanifest
├── rector.php
├── resources/
│   ├── css/
│   │   ├── app.css
│   │   ├── filament/
│   │   │   ├── admin/
│   │   │   │   └── theme.css
│   │   │   └── app/
│   │   │       └── theme.css
│   │   ├── fonts.css
│   │   └── theme.css
│   ├── js/
│   │   ├── app.js
│   │   └── motion.js
│   ├── markdown/
│   │   ├── brand-assets.md
│   │   ├── font-sources.md
│   │   ├── policy.md
│   │   └── terms.md
│   └── views/
│       ├── api/
│       │   └── api-token-manager.blade.php
│       ├── components/
│       │   ├── action-message.blade.php
│       │   ├── action-section.blade.php
│       │   ├── application-logo.blade.php
│       │   ├── application-mark.blade.php
│       │   ├── authentication-card-logo.blade.php
│       │   ├── authentication-card.blade.php
│       │   ├── banner.blade.php
│       │   ├── brand/
│       │   │   ├── logo-lockup.blade.php
│       │   │   ├── logomark.blade.php
│       │   │   └── wordmark.blade.php
│       │   ├── browser-sessions.blade.php
│       │   ├── button.blade.php
│       │   ├── checkbox.blade.php
│       │   ├── confirmation-modal.blade.php
│       │   ├── confirms-password.blade.php
│       │   ├── danger-button.blade.php
│       │   ├── dialog-modal.blade.php
│       │   ├── dropdown-link.blade.php
│       │   ├── dropdown.blade.php
│       │   ├── form-section.blade.php
│       │   ├── input-error.blade.php
│       │   ├── input.blade.php
│       │   ├── label.blade.php
│       │   ├── layout/
│       │   │   ├── footer.blade.php
│       │   │   ├── header.blade.php
│       │   │   └── mobile-menu.blade.php
│       │   ├── legal-document.blade.php
│       │   ├── marketing/
│       │   │   ├── button.blade.php
│       │   │   ├── input.blade.php
│       │   │   └── textarea.blade.php
│       │   ├── modal.blade.php
│       │   ├── nav-link.blade.php
│       │   ├── responsive-nav-link.blade.php
│       │   ├── secondary-button.blade.php
│       │   ├── section-border.blade.php
│       │   ├── section-title.blade.php
│       │   ├── switchable-team.blade.php
│       │   ├── theme-switcher.blade.php
│       │   ├── validation-errors.blade.php
│       │   └── welcome.blade.php
│       ├── contact.blade.php
│       ├── emails/
│       │   └── team-invitation.blade.php
│       ├── filament/
│       │   ├── actions/
│       │   │   └── ai-summary.blade.php
│       │   ├── app/
│       │   │   ├── analytics.blade.php
│       │   │   ├── import-preview-alpine.blade.php
│       │   │   ├── import-value-reviewer-alpine.blade.php
│       │   │   ├── logo-empty.blade.php
│       │   │   └── logo.blade.php
│       │   ├── auth/
│       │   │   └── social_login_buttons.blade.php
│       │   ├── components/
│       │   │   └── infolists/
│       │   │       └── avatar-name.blade.php
│       │   ├── pages/
│       │   │   ├── access-tokens.blade.php
│       │   │   ├── create-team.blade.php
│       │   │   ├── dashboard.blade.php
│       │   │   ├── edit-profile.blade.php
│       │   │   └── edit-team.blade.php
│       │   └── tables/
│       │       └── columns/
│       │           ├── avatar-name-column.blade.php
│       │           └── logo-name-column.blade.php
│       ├── home/
│       │   ├── index.blade.php
│       │   └── partials/
│       │       ├── community.blade.php
│       │       ├── faq.blade.php
│       │       ├── features.blade.php
│       │       ├── hero-agent-preview.blade.php
│       │       ├── hero.blade.php
│       │       └── start-building.blade.php
│       ├── layouts/
│       │   └── guest.blade.php
│       ├── livewire/
│       │   └── app/
│       │       ├── access-tokens/
│       │       │   ├── create-access-token.blade.php
│       │       │   └── manage-access-tokens.blade.php
│       │       ├── profile/
│       │       │   ├── delete-account.blade.php
│       │       │   ├── logout-other-browser-sessions.blade.php
│       │       │   ├── update-password.blade.php
│       │       │   └── update-profile-information.blade.php
│       │       └── teams/
│       │           ├── add-team-member.blade.php
│       │           ├── delete-team.blade.php
│       │           ├── pending-team-invitations.blade.php
│       │           ├── team-members.blade.php
│       │           └── update-team-name.blade.php
│       ├── mail/
│       │   └── new-contact-submission.blade.php
│       ├── policy.blade.php
│       ├── pricing.blade.php
│       ├── profile/
│       │   ├── delete-user-form.blade.php
│       │   ├── logout-other-browser-sessions-form.blade.php
│       │   ├── two-factor-authentication-form.blade.php
│       │   ├── update-password-form.blade.php
│       │   └── update-profile-information-form.blade.php
│       ├── teams/
│       │   ├── create-team-form.blade.php
│       │   ├── delete-team-form.blade.php
│       │   ├── invitation-expired.blade.php
│       │   ├── team-member-manager.blade.php
│       │   └── update-team-name-form.blade.php
│       ├── terms.blade.php
│       └── vendor/
│           ├── filament-panels/
│           │   └── components/
│           │       └── layout/
│           │           └── index.blade.php
│           ├── mail/
│           │   ├── html/
│           │   │   ├── button.blade.php
│           │   │   ├── footer.blade.php
│           │   │   ├── header.blade.php
│           │   │   ├── layout.blade.php
│           │   │   ├── message.blade.php
│           │   │   ├── panel.blade.php
│           │   │   ├── subcopy.blade.php
│           │   │   ├── table.blade.php
│           │   │   └── themes/
│           │   │       └── default.css
│           │   └── text/
│           │       ├── button.blade.php
│           │       ├── footer.blade.php
│           │       ├── header.blade.php
│           │       ├── layout.blade.php
│           │       ├── message.blade.php
│           │       ├── panel.blade.php
│           │       ├── subcopy.blade.php
│           │       └── table.blade.php
│           └── scribe/
│               ├── components/
│               │   ├── badges/
│               │   │   ├── auth.blade.php
│               │   │   ├── base.blade.php
│               │   │   ├── deprecated.blade.php
│               │   │   └── http-method.blade.php
│               │   ├── field-details.blade.php
│               │   └── nested-fields.blade.php
│               ├── external/
│               │   ├── elements.blade.php
│               │   ├── rapidoc.blade.php
│               │   └── scalar.blade.php
│               ├── markdown/
│               │   ├── auth.blade.php
│               │   └── intro.blade.php
│               ├── partials/
│               │   └── example-requests/
│               │       ├── bash.md.blade.php
│               │       ├── javascript.md.blade.php
│               │       ├── php.md.blade.php
│               │       └── python.md.blade.php
│               └── themes/
│                   ├── default/
│                   │   ├── endpoint.blade.php
│                   │   ├── groups.blade.php
│                   │   ├── index.blade.php
│                   │   └── sidebar.blade.php
│                   └── elements/
│                       ├── components/
│                       │   ├── field-details.blade.php
│                       │   └── nested-fields.blade.php
│                       ├── endpoint.blade.php
│                       ├── groups.blade.php
│                       ├── index.blade.php
│                       ├── sidebar.blade.php
│                       └── try_it_out.blade.php
├── routes/
│   ├── ai.php
│   ├── api.php
│   └── web.php
├── storage/
│   ├── app/
│   │   └── .gitignore
│   ├── clockwork/
│   │   └── .gitignore
│   ├── framework/
│   │   ├── .gitignore
│   │   ├── cache/
│   │   │   └── .gitignore
│   │   ├── sessions/
│   │   │   └── .gitignore
│   │   ├── testing/
│   │   │   └── .gitignore
│   │   └── views/
│   │       └── .gitignore
│   ├── logs/
│   │   └── .gitignore
│   └── pail/
│       └── .gitignore
├── stubs/
│   └── Mailcoach.stub
├── tests/
│   ├── Arch/
│   │   └── ArchTest.php
│   ├── Browser/
│   │   ├── Auth/
│   │   │   ├── LoginBrowserTest.php
│   │   │   └── PasswordResetBrowserTest.php
│   │   ├── CRM/
│   │   │   └── CompanyBrowserTest.php
│   │   ├── ImportWizard/
│   │   │   └── ImportWizardBrowserTest.php
│   │   ├── Onboarding/
│   │   │   └── OnboardingBrowserTest.php
│   │   ├── SmokeBrowserTest.php
│   │   └── Teams/
│   │       └── TeamBrowserTest.php
│   ├── Feature/
│   │   ├── AI/
│   │   │   └── RecordSummaryServiceTest.php
│   │   ├── AccessTokens/
│   │   │   ├── AccessTokenPermissionsTest.php
│   │   │   ├── CreateAccessTokenTest.php
│   │   │   └── DeleteAccessTokenTest.php
│   │   ├── Api/
│   │   │   └── V1/
│   │   │       ├── ApiMiddlewareTest.php
│   │   │       ├── ApiTeamScopingTest.php
│   │   │       ├── CompaniesApiTest.php
│   │   │       ├── CustomFieldsApiTest.php
│   │   │       ├── NotesApiTest.php
│   │   │       ├── OpportunitiesApiTest.php
│   │   │       ├── PeopleApiTest.php
│   │   │       ├── TasksApiTest.php
│   │   │       ├── TokenAbilitiesApiTest.php
│   │   │       └── UserEndpointTest.php
│   │   ├── Auth/
│   │   │   ├── AuthenticationTest.php
│   │   │   ├── PasswordResetTest.php
│   │   │   ├── RegistrationTest.php
│   │   │   ├── SocialiteLoginTest.php
│   │   │   ├── TwoFactorAuthenticationSettingsTest.php
│   │   │   └── UserModelTest.php
│   │   ├── CRM/
│   │   │   └── CompanyModelTest.php
│   │   ├── Commands/
│   │   │   └── InstallCommandTest.php
│   │   ├── ContactFormTest.php
│   │   ├── Filament/
│   │   │   └── App/
│   │   │       ├── Exports/
│   │   │       │   ├── CompanyExporterTest.php
│   │   │       │   ├── NoteExporterTest.php
│   │   │       │   ├── OpportunityExporterTest.php
│   │   │       │   ├── PeopleExporterTest.php
│   │   │       │   └── TaskExporterTest.php
│   │   │       ├── Pages/
│   │   │       │   ├── OpportunitiesBoardTest.php
│   │   │       │   └── TasksBoardTest.php
│   │   │       └── Resources/
│   │   │           ├── CompanyResourceTest.php
│   │   │           ├── NoteResourceTest.php
│   │   │           ├── OpportunityResourceTest.php
│   │   │           ├── PeopleResourceTest.php
│   │   │           └── TaskResourceTest.php
│   │   ├── HealthChecks/
│   │   │   └── HealthServiceProviderTest.php
│   │   ├── ImportWizard/
│   │   │   ├── Commands/
│   │   │   │   └── CleanupImportsCommandTest.php
│   │   │   ├── Components/
│   │   │   │   ├── MultiValueInputTest.php
│   │   │   │   └── SelectMenuInvalidOptionsTest.php
│   │   │   ├── Jobs/
│   │   │   │   ├── ExecuteImportJobTest.php
│   │   │   │   ├── ResolveMatchesJobTest.php
│   │   │   │   └── ValidateColumnJobTest.php
│   │   │   ├── Livewire/
│   │   │   │   ├── ImportWizardTest.php
│   │   │   │   ├── MappingStepTest.php
│   │   │   │   ├── PreviewStepTest.php
│   │   │   │   ├── ReviewStepTest.php
│   │   │   │   └── UploadStepTest.php
│   │   │   ├── Support/
│   │   │   │   └── EntityLinkResolverTest.php
│   │   │   └── Validation/
│   │   │       ├── ColumnValidatorTest.php
│   │   │       └── EntityLinkValidatorTest.php
│   │   ├── Mcp/
│   │   │   ├── CompanyToolsTest.php
│   │   │   ├── CrmSummaryResourceTest.php
│   │   │   ├── Filters/
│   │   │   │   ├── CustomFieldFilterTest.php
│   │   │   │   └── CustomFieldSortTest.php
│   │   │   ├── McpToolFeaturesTest.php
│   │   │   ├── NoteToolsTest.php
│   │   │   ├── OpportunityToolsTest.php
│   │   │   ├── PeopleToolsTest.php
│   │   │   ├── RelaticleServerTest.php
│   │   │   ├── SchemaResourcesTest.php
│   │   │   ├── TaskToolsTest.php
│   │   │   ├── TokenAbilitiesMcpTest.php
│   │   │   └── WhoAmiToolTest.php
│   │   ├── Migrations/
│   │   │   └── UlidMigrationTest.php
│   │   ├── Models/
│   │   │   └── Scopes/
│   │   │       └── TeamScopeTest.php
│   │   ├── Onboarding/
│   │   │   └── CreateTeamOnboardingTest.php
│   │   ├── PersonalAccessToken/
│   │   │   └── TeamIdImmutabilityTest.php
│   │   ├── Profile/
│   │   │   ├── AvatarServiceTest.php
│   │   │   ├── BrowserSessionsTest.php
│   │   │   ├── DeleteAccountTest.php
│   │   │   ├── GitHubServiceTest.php
│   │   │   ├── UpdatePasswordTest.php
│   │   │   └── UpdateUserProfileInformationTest.php
│   │   ├── Public/
│   │   │   └── PublicPagesTest.php
│   │   ├── Routing/
│   │   │   ├── AppPanelRoutingTest.php
│   │   │   └── SubdomainRoutingTest.php
│   │   ├── SystemAdmin/
│   │   │   ├── ActivationRateWidgetTest.php
│   │   │   ├── SystemAdminResourceTest.php
│   │   │   ├── SystemAdminSecurityTest.php
│   │   │   └── UserRetentionChartWidgetTest.php
│   │   ├── Teams/
│   │   │   ├── AcceptTeamInvitationTest.php
│   │   │   ├── CreateTeamTest.php
│   │   │   ├── DeleteTeamTest.php
│   │   │   ├── InvitationUxTest.php
│   │   │   ├── InviteTeamMemberTest.php
│   │   │   ├── LeaveTeamTest.php
│   │   │   ├── ManageTeamInvitationsTest.php
│   │   │   ├── RemoveTeamMemberTest.php
│   │   │   ├── TeamModelTest.php
│   │   │   ├── UpdateTeamMemberRoleTest.php
│   │   │   └── UpdateTeamNameTest.php
│   │   └── ValidTeamSlugTest.php
│   ├── Pest.php
│   ├── Smoke/
│   │   └── RouteTest.php
│   ├── TestCase.php
│   └── fixtures/
│       └── imports/
│           ├── companies.csv
│           ├── companies.xlsx
│           └── people.xlsx
└── vite.config.js
Download .txt
Showing preview only (1,047K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (10898 symbols across 520 files)

FILE: app/Actions/Company/CreateCompany.php
  class CreateCompany (line 13) | final readonly class CreateCompany
    method execute (line 18) | public function execute(User $user, array $data, CreationSource $sourc...

FILE: app/Actions/Company/DeleteCompany.php
  class DeleteCompany (line 10) | final readonly class DeleteCompany
    method execute (line 12) | public function execute(User $user, Company $company): void

FILE: app/Actions/Company/ListCompanies.php
  class ListCompanies (line 18) | final readonly class ListCompanies
    method execute (line 24) | public function execute(

FILE: app/Actions/Company/UpdateCompany.php
  class UpdateCompany (line 13) | final readonly class UpdateCompany
    method execute (line 18) | public function execute(User $user, Company $company, array $data): Co...

FILE: app/Actions/Fortify/CreateNewSocialUser.php
  class CreateNewSocialUser (line 15) | final readonly class CreateNewSocialUser implements CreatesNewSocialUsers
    method create (line 24) | public function create(array $input): User

FILE: app/Actions/Fortify/PasswordValidationRules.php
  type PasswordValidationRules (line 10) | trait PasswordValidationRules
    method passwordRules (line 17) | protected function passwordRules(): array

FILE: app/Actions/Fortify/ResetUserPassword.php
  class ResetUserPassword (line 12) | final readonly class ResetUserPassword implements ResetsUserPasswords
    method reset (line 21) | public function reset(User $user, array $input): void

FILE: app/Actions/Fortify/UpdateUserPassword.php
  class UpdateUserPassword (line 12) | final readonly class UpdateUserPassword implements UpdatesUserPasswords
    method update (line 21) | public function update(User $user, array $input): void

FILE: app/Actions/Fortify/UpdateUserProfileInformation.php
  class UpdateUserProfileInformation (line 12) | final readonly class UpdateUserProfileInformation implements UpdatesUser...
    method update (line 19) | public function update(User $user, array $input): void
    method updateVerifiedUser (line 50) | private function updateVerifiedUser(User $user, array $input): void

FILE: app/Actions/Jetstream/AddTeamMember.php
  class AddTeamMember (line 19) | final readonly class AddTeamMember implements AddsTeamMembers
    method add (line 24) | public function add(User $user, Team $team, string $email, ?string $ro...
    method validate (line 44) | private function validate(Team $team, string $email, ?string $role): void
    method rules (line 61) | private function rules(): array
    method ensureUserIsNotAlreadyOnTeam (line 72) | private function ensureUserIsNotAlreadyOnTeam(Team $team, string $emai...

FILE: app/Actions/Jetstream/CreateTeam.php
  class CreateTeam (line 16) | final readonly class CreateTeam implements CreatesTeams
    method create (line 23) | public function create(User $user, array $input): Team

FILE: app/Actions/Jetstream/DeleteTeam.php
  class DeleteTeam (line 10) | final readonly class DeleteTeam implements DeletesTeams
    method delete (line 15) | public function delete(Team $team): void

FILE: app/Actions/Jetstream/DeleteUser.php
  class DeleteUser (line 14) | final readonly class DeleteUser implements DeletesUsers
    method __construct (line 19) | public function __construct(private DeletesTeams $deletesTeams) {}
    method delete (line 24) | public function delete(User $user): void
    method deleteTeams (line 37) | private function deleteTeams(User $user): void

FILE: app/Actions/Jetstream/InviteTeamMember.php
  class InviteTeamMember (line 23) | final readonly class InviteTeamMember implements InvitesTeamMembers
    method invite (line 28) | public function invite(User $user, Team $team, string $email, ?string ...
    method validate (line 51) | private function validate(Team $team, string $email, ?string $role): void
    method rules (line 68) | private function rules(Team $team): array
    method ensureUserIsNotAlreadyOnTeam (line 84) | private function ensureUserIsNotAlreadyOnTeam(Team $team, string $emai...

FILE: app/Actions/Jetstream/RemoveTeamMember.php
  class RemoveTeamMember (line 15) | final readonly class RemoveTeamMember implements RemovesTeamMembers
    method remove (line 20) | public function remove(User $user, Team $team, User $teamMember): void
    method authorize (line 34) | private function authorize(User $user, Team $team, User $teamMember): ...
    method ensureUserDoesNotOwnTeam (line 43) | private function ensureUserDoesNotOwnTeam(User $teamMember, Team $team...

FILE: app/Actions/Jetstream/UpdateTeamName.php
  class UpdateTeamName (line 14) | final readonly class UpdateTeamName implements UpdatesTeamNames
    method update (line 21) | public function update(User $user, Team $team, array $input): void

FILE: app/Actions/Note/CreateNote.php
  class CreateNote (line 13) | final readonly class CreateNote
    method execute (line 18) | public function execute(User $user, array $data, CreationSource $sourc...

FILE: app/Actions/Note/DeleteNote.php
  class DeleteNote (line 10) | final readonly class DeleteNote
    method execute (line 12) | public function execute(User $user, Note $note): void

FILE: app/Actions/Note/ListNotes.php
  class ListNotes (line 18) | final readonly class ListNotes
    method execute (line 24) | public function execute(

FILE: app/Actions/Note/UpdateNote.php
  class UpdateNote (line 13) | final readonly class UpdateNote
    method execute (line 18) | public function execute(User $user, Note $note, array $data): Note

FILE: app/Actions/Opportunity/CreateOpportunity.php
  class CreateOpportunity (line 13) | final readonly class CreateOpportunity
    method execute (line 18) | public function execute(User $user, array $data, CreationSource $sourc...

FILE: app/Actions/Opportunity/DeleteOpportunity.php
  class DeleteOpportunity (line 10) | final readonly class DeleteOpportunity
    method execute (line 12) | public function execute(User $user, Opportunity $opportunity): void

FILE: app/Actions/Opportunity/ListOpportunities.php
  class ListOpportunities (line 18) | final readonly class ListOpportunities
    method execute (line 24) | public function execute(

FILE: app/Actions/Opportunity/UpdateOpportunity.php
  class UpdateOpportunity (line 13) | final readonly class UpdateOpportunity
    method execute (line 18) | public function execute(User $user, Opportunity $opportunity, array $d...

FILE: app/Actions/People/CreatePeople.php
  class CreatePeople (line 13) | final readonly class CreatePeople
    method execute (line 18) | public function execute(User $user, array $data, CreationSource $sourc...

FILE: app/Actions/People/DeletePeople.php
  class DeletePeople (line 10) | final readonly class DeletePeople
    method execute (line 12) | public function execute(User $user, People $people): void

FILE: app/Actions/People/ListPeople.php
  class ListPeople (line 18) | final readonly class ListPeople
    method execute (line 24) | public function execute(

FILE: app/Actions/People/UpdatePeople.php
  class UpdatePeople (line 13) | final readonly class UpdatePeople
    method execute (line 18) | public function execute(User $user, People $people, array $data): People

FILE: app/Actions/Task/CreateTask.php
  class CreateTask (line 13) | final readonly class CreateTask
    method __construct (line 15) | public function __construct(
    method execute (line 22) | public function execute(User $user, array $data, CreationSource $sourc...

FILE: app/Actions/Task/DeleteTask.php
  class DeleteTask (line 10) | final readonly class DeleteTask
    method execute (line 12) | public function execute(User $user, Task $task): void

FILE: app/Actions/Task/ListTasks.php
  class ListTasks (line 19) | final readonly class ListTasks
    method execute (line 25) | public function execute(

FILE: app/Actions/Task/NotifyTaskAssignees.php
  class NotifyTaskAssignees (line 14) | final readonly class NotifyTaskAssignees
    method execute (line 19) | public function execute(Task $task, array $previousAssigneeIds = []): ...
    method resolveTaskUrl (line 54) | private function resolveTaskUrl(Task $task): string

FILE: app/Actions/Task/UpdateTask.php
  class UpdateTask (line 13) | final readonly class UpdateTask
    method __construct (line 15) | public function __construct(
    method execute (line 24) | public function execute(User $user, Task $task, array $data): Task

FILE: app/Concerns/DetectsTeamInvitation.php
  type DetectsTeamInvitation (line 11) | trait DetectsTeamInvitation
    method getTeamInvitationFromSession (line 13) | protected function getTeamInvitationFromSession(): ?TeamInvitation
    method getTeamInvitationSubheading (line 39) | protected function getTeamInvitationSubheading(): ?Htmlable
    method getInvitationContentHtml (line 54) | protected function getInvitationContentHtml(): string

FILE: app/Console/Commands/BackfillCustomFieldColorsCommand.php
  class BackfillCustomFieldColorsCommand (line 16) | final class BackfillCustomFieldColorsCommand extends Command
    method handle (line 37) | public function handle(): int
    method getColorMappingForField (line 137) | private function getColorMappingForField(CustomField $field): ?array

FILE: app/Console/Commands/CleanupExpiredInvitationsCommand.php
  class CleanupExpiredInvitationsCommand (line 11) | final class CleanupExpiredInvitationsCommand extends Command
    method handle (line 24) | public function handle(): void

FILE: app/Console/Commands/CreateSystemAdminCommand.php
  class CreateSystemAdminCommand (line 16) | final class CreateSystemAdminCommand extends Command
    method handle (line 38) | public function handle(): int

FILE: app/Console/Commands/GenerateSitemapCommand.php
  class GenerateSitemapCommand (line 10) | final class GenerateSitemapCommand extends Command
    method handle (line 29) | public function handle(): void

FILE: app/Console/Commands/InstallCommand.php
  class InstallCommand (line 21) | final class InstallCommand extends Command
    method handle (line 29) | public function handle(): int
    method displayWelcome (line 42) | private function displayWelcome(): void
    method shouldProceed (line 52) | private function shouldProceed(): bool
    method isAlreadyInstalled (line 67) | private function isAlreadyInstalled(): bool
    method getConfiguration (line 75) | private function getConfiguration(): array
    method runInstallation (line 109) | private function runInstallation(array $config): int
    method checkSystemRequirements (line 167) | private function checkSystemRequirements(): bool
    method commandExists (line 202) | private function commandExists(string $command): bool
    method setupEnvironment (line 208) | private function setupEnvironment(array $config): bool
    method configureDatabaseConnection (line 227) | private function configureDatabaseConnection(string $type): bool
    method installDependencies (line 264) | private function installDependencies(): bool
    method setupDatabase (line 285) | private function setupDatabase(): bool
    method buildAssets (line 299) | private function buildAssets(): bool
    method setupStorage (line 313) | private function setupStorage(): bool
    method seedDemoData (line 327) | private function seedDemoData(): bool
    method createSystemAdministrator (line 347) | private function createSystemAdministrator(): bool
    method displaySuccessMessage (line 414) | private function displaySuccessMessage(array $config): void
    method envPath (line 456) | private function envPath(): string

FILE: app/Contracts/User/CreatesNewSocialUsers.php
  type CreatesNewSocialUsers (line 9) | interface CreatesNewSocialUsers
    method create (line 16) | public function create(array $input): User;

FILE: app/Data/SubscriberData.php
  class SubscriberData (line 9) | final class SubscriberData extends Data
    method __construct (line 11) | public function __construct(

FILE: app/Enums/CreationSource.php
  method getColor (line 48) | public function getColor(): string
  method getLabel (line 59) | public function getLabel(): string

FILE: app/Enums/CustomFields/CompanyField.php
  method getDisplayName (line 28) | public function getDisplayName(): string
  method getFieldType (line 37) | public function getFieldType(): string
  method isSystemDefined (line 45) | public function isSystemDefined(): bool
  method isListToggleableHidden (line 53) | public function isListToggleableHidden(): bool
  method getDescription (line 61) | public function getDescription(): string
  method allowsMultipleValues (line 70) | public function allowsMultipleValues(): bool
  method isUniquePerEntityType (line 78) | public function isUniquePerEntityType(): bool

FILE: app/Enums/CustomFields/CustomFieldTrait.php
  type CustomFieldTrait (line 16) | trait CustomFieldTrait
    method getDisplayName (line 23) | public function getDisplayName(): string
    method getFieldType (line 33) | abstract public function getFieldType(): string;
    method isSystemDefined (line 42) | public function isSystemDefined(): bool
    method isListToggleableHidden (line 54) | public function isListToggleableHidden(): bool
    method getWidth (line 64) | public function getWidth(): CustomFieldWidth
    method getOptions (line 74) | public function getOptions(): ?array
    method getDescription (line 84) | public function getDescription(): ?string
    method getOptionColors (line 94) | public function getOptionColors(): ?array
    method hasColorOptions (line 104) | public function hasColorOptions(): bool
    method allowsMultipleValues (line 114) | public function allowsMultipleValues(): bool
    method getMaxValues (line 124) | public function getMaxValues(): int
    method isUniquePerEntityType (line 134) | public function isUniquePerEntityType(): bool
    method getConfiguration (line 155) | public function getConfiguration(): array

FILE: app/Enums/CustomFields/NoteField.php
  method getFieldType (line 18) | public function getFieldType(): string
  method getDisplayName (line 25) | public function getDisplayName(): string
  method isListToggleableHidden (line 32) | public function isListToggleableHidden(): bool

FILE: app/Enums/CustomFields/OpportunityField.php
  method getOptions (line 20) | public function getOptions(): ?array
  method getFieldType (line 39) | public function getFieldType(): string
  method getDisplayName (line 48) | public function getDisplayName(): string
  method isListToggleableHidden (line 57) | public function isListToggleableHidden(): bool
  method getOptionColors (line 72) | public function getOptionColors(): ?array

FILE: app/Enums/CustomFields/PeopleField.php
  method getFieldType (line 21) | public function getFieldType(): string
  method getDisplayName (line 31) | public function getDisplayName(): string
  method isListToggleableHidden (line 41) | public function isListToggleableHidden(): bool
  method isSystemDefined (line 49) | public function isSystemDefined(): bool
  method allowsMultipleValues (line 57) | public function allowsMultipleValues(): bool
  method isUniquePerEntityType (line 65) | public function isUniquePerEntityType(): bool

FILE: app/Enums/CustomFields/TaskField.php
  method getDisplayName (line 39) | public function getDisplayName(): string
  method getFieldType (line 54) | public function getFieldType(): string
  method isSystemDefined (line 68) | public function isSystemDefined(): bool
  method isListToggleableHidden (line 81) | public function isListToggleableHidden(): bool
  method getWidth (line 94) | public function getWidth(): CustomFieldWidth
  method getOptions (line 107) | public function getOptions(): ?array
  method getOptionColors (line 133) | public function getOptionColors(): ?array
  method getDescription (line 155) | public function getDescription(): string

FILE: app/Filament/Actions/GenerateRecordSummaryAction.php
  class GenerateRecordSummaryAction (line 16) | final class GenerateRecordSummaryAction extends Action
    method getDefaultName (line 18) | public static function getDefaultName(): string
    method setUp (line 23) | protected function setUp(): void
    method makeRegenerateAction (line 41) | private function makeRegenerateAction(): Action
    method makeCopyAction (line 50) | private function makeCopyAction(): Action
    method getSummaryView (line 66) | private function getSummaryView(Model $record): View
    method getCachedSummary (line 73) | private function getCachedSummary(Model $record): ?AiSummary
    method regenerateSummary (line 82) | private function regenerateSummary(Model $record): void
    method summaryService (line 100) | private function summaryService(): RecordSummaryService

FILE: app/Filament/Components/Infolists/AvatarName.php
  class AvatarName (line 10) | final class AvatarName extends Entry
    method avatar (line 24) | public function avatar(string $path): static
    method name (line 31) | public function name(string $path): static
    method avatarSize (line 38) | public function avatarSize(string $size): static
    method textSize (line 45) | public function textSize(string $size): static
    method square (line 52) | public function square(): static
    method circular (line 59) | public function circular(): static
    method getState (line 69) | public function getState(): array
    method resolvePath (line 95) | private function resolvePath(mixed $record, string $path): mixed

FILE: app/Filament/Exports/BaseExporter.php
  class BaseExporter (line 14) | abstract class BaseExporter extends Exporter
    method __construct (line 20) | public function __construct(
    method modifyQuery (line 41) | public static function modifyQuery(Builder $query): Builder

FILE: app/Filament/Exports/CompanyExporter.php
  class CompanyExporter (line 13) | final class CompanyExporter extends BaseExporter
    method getColumns (line 17) | public static function getColumns(): array
    method getCompletedNotificationBody (line 51) | public static function getCompletedNotificationBody(Export $export): s...

FILE: app/Filament/Exports/NoteExporter.php
  class NoteExporter (line 13) | final class NoteExporter extends BaseExporter
    method getColumns (line 17) | public static function getColumns(): array
    method getCompletedNotificationBody (line 35) | public static function getCompletedNotificationBody(Export $export): s...

FILE: app/Filament/Exports/OpportunityExporter.php
  class OpportunityExporter (line 13) | final class OpportunityExporter extends BaseExporter
    method getColumns (line 17) | public static function getColumns(): array
    method getCompletedNotificationBody (line 53) | public static function getCompletedNotificationBody(Export $export): s...

FILE: app/Filament/Exports/PeopleExporter.php
  class PeopleExporter (line 13) | final class PeopleExporter extends BaseExporter
    method getColumns (line 17) | public static function getColumns(): array
    method getCompletedNotificationBody (line 37) | public static function getCompletedNotificationBody(Export $export): s...

FILE: app/Filament/Exports/TaskExporter.php
  class TaskExporter (line 13) | final class TaskExporter extends BaseExporter
    method getColumns (line 17) | public static function getColumns(): array
    method getCompletedNotificationBody (line 34) | public static function getCompletedNotificationBody(Export $export): s...

FILE: app/Filament/Pages/AccessTokens.php
  class AccessTokens (line 14) | final class AccessTokens extends Page
    method shouldRegisterNavigation (line 20) | #[Override]
    method form (line 26) | public function form(Schema $schema): Schema
    method getLabel (line 34) | public static function getLabel(): string

FILE: app/Filament/Pages/Auth/Login.php
  class Login (line 15) | final class Login extends \Filament\Auth\Pages\Login
    method content (line 19) | public function content(Schema $schema): Schema
    method getAuthenticateFormAction (line 31) | protected function getAuthenticateFormAction(): Action

FILE: app/Filament/Pages/Auth/Register.php
  class Register (line 18) | final class Register extends BaseRegister
    method content (line 22) | public function content(Schema $schema): Schema
    method getEmailFormComponent (line 33) | protected function getEmailFormComponent(): TextInput
    method getRegisterFormAction (line 44) | public function getRegisterFormAction(): Action
    method handleRegistration (line 55) | protected function handleRegistration(array $data): Model

FILE: app/Filament/Pages/CreateTeam.php
  class CreateTeam (line 22) | final class CreateTeam extends RegisterTenant
    method getLabel (line 24) | #[Override]
    method getHeading (line 30) | #[Override]
    method getSubheading (line 36) | #[Override]
    method form (line 42) | #[Override]
    method getRedirectUrl (line 80) | #[Override]
    method handleRegistration (line 86) | #[Override]

FILE: app/Filament/Pages/EditProfile.php
  class EditProfile (line 15) | final class EditProfile extends Page
    method shouldRegisterNavigation (line 25) | public static function shouldRegisterNavigation(): bool
    method form (line 30) | public function form(Schema $schema): Schema
    method getLabel (line 40) | public static function getLabel(): string

FILE: app/Filament/Pages/EditTeam.php
  class EditTeam (line 17) | final class EditTeam extends EditTenantProfile
    method form (line 25) | public function form(Schema $schema): Schema
    method getLabel (line 45) | public static function getLabel(): string

FILE: app/Filament/Pages/OpportunitiesBoard.php
  class OpportunitiesBoard (line 40) | final class OpportunitiesBoard extends BoardPage
    method board (line 52) | public function board(Board $board): Board
    method moveCard (line 209) | public function moveCard(
    method getColumns (line 250) | private function getColumns(): array
    method formatCloseDateBadge (line 258) | private function formatCloseDateBadge(?string $state): string
    method stageCustomField (line 274) | private function stageCustomField(): ?CustomField
    method stages (line 286) | private function stages(): Collection
    method canAccess (line 304) | public static function canAccess(): bool

FILE: app/Filament/Pages/TasksBoard.php
  class TasksBoard (line 36) | final class TasksBoard extends BoardPage
    method board (line 51) | public function board(Board $board): Board
    method moveCard (line 188) | public function moveCard(
    method getColumns (line 232) | private function getColumns(): array
    method formatDueDateBadge (line 246) | private function formatDueDateBadge(?string $state): string
    method statusCustomField (line 262) | private function statusCustomField(): ?CustomField
    method statuses (line 274) | private function statuses(): Collection
    method canAccess (line 293) | public static function canAccess(): bool

FILE: app/Filament/Resources/CompanyResource.php
  class CompanyResource (line 35) | final class CompanyResource extends Resource
    method form (line 47) | public static function form(Schema $schema): Schema
    method table (line 64) | public static function table(Table $table): Table
    method getPages (line 130) | public static function getPages(): array
    method getGloballySearchableAttributes (line 138) | public static function getGloballySearchableAttributes(): array
    method getEloquentQuery (line 143) | public static function getEloquentQuery(): Builder

FILE: app/Filament/Resources/CompanyResource/Pages/ListCompanies.php
  class ListCompanies (line 20) | final class ListCompanies extends ListRecords
    method getHeaderActions (line 31) | #[Override]

FILE: app/Filament/Resources/CompanyResource/Pages/ViewCompany.php
  class ViewCompany (line 26) | final class ViewCompany extends ViewRecord
    method getHeaderActions (line 30) | protected function getHeaderActions(): array
    method infolist (line 71) | public function infolist(Schema $schema): Schema
    method getRelationManagers (line 116) | public function getRelationManagers(): array

FILE: app/Filament/Resources/CompanyResource/RelationManagers/NotesRelationManager.php
  class NotesRelationManager (line 23) | final class NotesRelationManager extends RelationManager
    method form (line 29) | public function form(Schema $schema): Schema
    method table (line 34) | public function table(Table $table): Table

FILE: app/Filament/Resources/CompanyResource/RelationManagers/PeopleRelationManager.php
  class PeopleRelationManager (line 21) | final class PeopleRelationManager extends RelationManager
    method form (line 29) | public function form(Schema $schema): Schema
    method table (line 43) | public function table(Table $table): Table

FILE: app/Filament/Resources/CompanyResource/RelationManagers/TasksRelationManager.php
  class TasksRelationManager (line 22) | final class TasksRelationManager extends RelationManager
    method form (line 28) | public function form(Schema $schema): Schema
    method table (line 33) | public function table(Table $table): Table

FILE: app/Filament/Resources/NoteResource.php
  class NoteResource (line 32) | final class NoteResource extends Resource
    method form (line 44) | public static function form(Schema $schema): Schema
    method table (line 49) | public static function table(Table $table): Table
    method getPages (line 111) | #[Override]
    method getEloquentQuery (line 119) | public static function getEloquentQuery(): Builder

FILE: app/Filament/Resources/NoteResource/Forms/NoteForm.php
  class NoteForm (line 12) | final class NoteForm
    method get (line 20) | public static function get(Schema $schema, array $excludeFields = []):...

FILE: app/Filament/Resources/NoteResource/Pages/ManageNotes.php
  class ManageNotes (line 20) | final class ManageNotes extends ManageRecords
    method getHeaderActions (line 27) | #[Override]

FILE: app/Filament/Resources/OpportunityResource.php
  class OpportunityResource (line 36) | final class OpportunityResource extends Resource
    method form (line 48) | public static function form(Schema $schema): Schema
    method table (line 53) | public static function table(Table $table): Table
    method getRelations (line 106) | public static function getRelations(): array
    method getPages (line 114) | #[Override]
    method getEloquentQuery (line 123) | public static function getEloquentQuery(): Builder

FILE: app/Filament/Resources/OpportunityResource/Forms/OpportunityForm.php
  class OpportunityForm (line 12) | final class OpportunityForm
    method get (line 14) | public static function get(Schema $schema): Schema

FILE: app/Filament/Resources/OpportunityResource/Pages/ListOpportunities.php
  class ListOpportunities (line 20) | final class ListOpportunities extends ListRecords
    method getHeaderActions (line 27) | #[Override]

FILE: app/Filament/Resources/OpportunityResource/Pages/ViewOpportunity.php
  class ViewOpportunity (line 24) | final class ViewOpportunity extends ViewRecord
    method getHeaderActions (line 28) | protected function getHeaderActions(): array
    method infolist (line 69) | public function infolist(Schema $schema): Schema

FILE: app/Filament/Resources/OpportunityResource/RelationManagers/NotesRelationManager.php
  class NotesRelationManager (line 24) | final class NotesRelationManager extends RelationManager
    method form (line 30) | public function form(Schema $schema): Schema
    method table (line 35) | public function table(Table $table): Table

FILE: app/Filament/Resources/OpportunityResource/RelationManagers/TasksRelationManager.php
  class TasksRelationManager (line 24) | final class TasksRelationManager extends RelationManager
    method form (line 30) | public function form(Schema $schema): Schema
    method table (line 35) | public function table(Table $table): Table

FILE: app/Filament/Resources/PeopleResource.php
  class PeopleResource (line 42) | final class PeopleResource extends Resource
    method form (line 56) | public static function form(Schema $schema): Schema
    method table (line 100) | public static function table(Table $table): Table
    method getRelations (line 162) | public static function getRelations(): array
    method getPages (line 170) | public static function getPages(): array
    method getEloquentQuery (line 178) | public static function getEloquentQuery(): Builder

FILE: app/Filament/Resources/PeopleResource/Pages/ListPeople.php
  class ListPeople (line 20) | final class ListPeople extends ListRecords
    method getHeaderActions (line 27) | #[Override]

FILE: app/Filament/Resources/PeopleResource/Pages/ViewPeople.php
  class ViewPeople (line 25) | final class ViewPeople extends ViewRecord
    method getHeaderActions (line 29) | protected function getHeaderActions(): array
    method infolist (line 70) | public function infolist(Schema $schema): Schema

FILE: app/Filament/Resources/PeopleResource/RelationManagers/NotesRelationManager.php
  class NotesRelationManager (line 20) | final class NotesRelationManager extends RelationManager
    method form (line 26) | public function form(Schema $schema): Schema
    method table (line 31) | public function table(Table $table): Table

FILE: app/Filament/Resources/PeopleResource/RelationManagers/TasksRelationManager.php
  class TasksRelationManager (line 20) | final class TasksRelationManager extends RelationManager
    method form (line 26) | public function form(Schema $schema): Schema
    method table (line 31) | public function table(Table $table): Table

FILE: app/Filament/Resources/TaskResource.php
  class TaskResource (line 36) | final class TaskResource extends Resource
    method form (line 50) | public static function form(Schema $schema): Schema
    method table (line 55) | public static function table(Table $table): Table
    method getPages (line 142) | public static function getPages(): array
    method makeCustomFieldGroup (line 152) | private static function makeCustomFieldGroup(string $fieldCode, Collec...
    method getEloquentQuery (line 192) | public static function getEloquentQuery(): Builder

FILE: app/Filament/Resources/TaskResource/Forms/TaskForm.php
  class TaskForm (line 12) | final class TaskForm
    method get (line 19) | public static function get(Schema $schema, array $excludeFields = []):...

FILE: app/Filament/Resources/TaskResource/Pages/ManageTasks.php
  class ManageTasks (line 22) | final class ManageTasks extends ManageRecords
    method getHeaderActions (line 29) | #[Override]

FILE: app/Health/AnthropicModelCheck.php
  class AnthropicModelCheck (line 13) | final class AnthropicModelCheck extends Check
    method run (line 15) | public function run(): Result

FILE: app/Http/Controllers/AcceptTeamInvitationController.php
  class AcceptTeamInvitationController (line 15) | final readonly class AcceptTeamInvitationController
    method __invoke (line 17) | public function __invoke(Request $request, string $invitationId): Redi...

FILE: app/Http/Controllers/Api/V1/CompaniesController.php
  class CompaniesController (line 31) | final readonly class CompaniesController
    method index (line 33) | #[ResponseFromApiResource(CompanyResource::class, Company::class, coll...
    method store (line 44) | #[ResponseFromApiResource(CompanyResource::class, Company::class, stat...
    method show (line 54) | #[ResponseFromApiResource(CompanyResource::class, Company::class)]
    method update (line 64) | #[ResponseFromApiResource(CompanyResource::class, Company::class)]
    method destroy (line 72) | #[Response(status: 204)]

FILE: app/Http/Controllers/Api/V1/CustomFieldsController.php
  class CustomFieldsController (line 20) | final readonly class CustomFieldsController
    method index (line 22) | #[ResponseFromApiResource(CustomFieldResource::class, CustomField::cla...

FILE: app/Http/Controllers/Api/V1/NotesController.php
  class NotesController (line 31) | final readonly class NotesController
    method index (line 33) | #[ResponseFromApiResource(NoteResource::class, Note::class, collection...
    method store (line 44) | #[ResponseFromApiResource(NoteResource::class, Note::class, status: 201)]
    method show (line 54) | #[ResponseFromApiResource(NoteResource::class, Note::class)]
    method update (line 64) | #[ResponseFromApiResource(NoteResource::class, Note::class)]
    method destroy (line 72) | #[Response(status: 204)]

FILE: app/Http/Controllers/Api/V1/OpportunitiesController.php
  class OpportunitiesController (line 32) | final readonly class OpportunitiesController
    method index (line 34) | #[ResponseFromApiResource(OpportunityResource::class, Opportunity::cla...
    method store (line 45) | #[ResponseFromApiResource(OpportunityResource::class, Opportunity::cla...
    method show (line 58) | #[ResponseFromApiResource(OpportunityResource::class, Opportunity::cla...
    method update (line 68) | #[ResponseFromApiResource(OpportunityResource::class, Opportunity::cla...
    method destroy (line 79) | #[Response(status: 204)]

FILE: app/Http/Controllers/Api/V1/PeopleController.php
  class PeopleController (line 32) | final readonly class PeopleController
    method index (line 34) | #[ResponseFromApiResource(PeopleResource::class, People::class, collec...
    method store (line 45) | #[ResponseFromApiResource(PeopleResource::class, People::class, status...
    method show (line 57) | #[ResponseFromApiResource(PeopleResource::class, People::class)]
    method update (line 67) | #[ResponseFromApiResource(PeopleResource::class, People::class)]
    method destroy (line 77) | #[Response(status: 204)]

FILE: app/Http/Controllers/Api/V1/TasksController.php
  class TasksController (line 31) | final readonly class TasksController
    method index (line 33) | #[ResponseFromApiResource(TaskResource::class, Task::class, collection...
    method store (line 44) | #[ResponseFromApiResource(TaskResource::class, Task::class, status: 201)]
    method show (line 54) | #[ResponseFromApiResource(TaskResource::class, Task::class)]
    method update (line 64) | #[ResponseFromApiResource(TaskResource::class, Task::class)]
    method destroy (line 72) | #[Response(status: 204)]

FILE: app/Http/Controllers/Auth/CallbackController.php
  class CallbackController (line 20) | final readonly class CallbackController
    method __invoke (line 22) | public function __invoke(
    method retrieveSocialUser (line 49) | private function retrieveSocialUser(string $provider): SocialiteUser
    method resolveUser (line 54) | private function resolveUser(
    method createUser (line 83) | private function createUser(
    method linkSocialAccount (line 95) | private function linkSocialAccount(User $user, string $provider, strin...
    method extractName (line 105) | private function extractName(SocialiteUser $socialUser): string
    method extractEmail (line 112) | private function extractEmail(SocialiteUser $socialUser, string $provi...
    method parseProviderError (line 118) | private function parseProviderError(string $exceptionMessage, string $...
    method handleError (line 134) | private function handleError(string $message): RedirectResponse
    method loginAndRedirect (line 148) | private function loginAndRedirect(User $user): RedirectResponse

FILE: app/Http/Controllers/Auth/RedirectController.php
  class RedirectController (line 12) | final readonly class RedirectController
    method __invoke (line 14) | public function __invoke(SocialiteProvider $provider): RedirectResponse

FILE: app/Http/Controllers/ContactController.php
  class ContactController (line 13) | final readonly class ContactController
    method show (line 15) | public function show(): View
    method store (line 20) | public function store(ContactRequest $request): RedirectResponse

FILE: app/Http/Controllers/HomeController.php
  class HomeController (line 9) | final readonly class HomeController
    method __invoke (line 11) | public function __invoke(): View

FILE: app/Http/Controllers/PrivacyPolicyController.php
  class PrivacyPolicyController (line 11) | final readonly class PrivacyPolicyController
    method __invoke (line 13) | public function __invoke(): View

FILE: app/Http/Controllers/TermsOfServiceController.php
  class TermsOfServiceController (line 11) | final readonly class TermsOfServiceController
    method __invoke (line 13) | public function __invoke(): View

FILE: app/Http/Middleware/ApplyTenantScopes.php
  class ApplyTenantScopes (line 19) | final readonly class ApplyTenantScopes
    method handle (line 21) | public function handle(Request $request, Closure $next): mixed

FILE: app/Http/Middleware/EnsureTokenHasAbility.php
  class EnsureTokenHasAbility (line 13) | final readonly class EnsureTokenHasAbility
    method handle (line 18) | public function handle(Request $request, Closure $next): Response
    method resolveAbility (line 36) | private function resolveAbility(string $method): string

FILE: app/Http/Middleware/ForceJsonResponse.php
  class ForceJsonResponse (line 11) | final readonly class ForceJsonResponse
    method handle (line 13) | public function handle(Request $request, Closure $next): Response

FILE: app/Http/Middleware/SetApiTeamContext.php
  class SetApiTeamContext (line 35) | final readonly class SetApiTeamContext
    method handle (line 47) | public function handle(Request $request, Closure $next): Response
    method terminate (line 81) | public function terminate(): void
    method resolveTeam (line 90) | private function resolveTeam(Request $request, User $user): ?Team
    method applyTenantScopes (line 107) | private function applyTenantScopes(Team $team): void

FILE: app/Http/Middleware/SubdomainRootResponse.php
  class SubdomainRootResponse (line 12) | final readonly class SubdomainRootResponse
    method handle (line 14) | public function handle(Request $request, Closure $next): Response

FILE: app/Http/Middleware/ValidateSignature.php
  class ValidateSignature (line 26) | final readonly class ValidateSignature
    method __construct (line 28) | public function __construct(
    method handle (line 33) | public function handle(Request $request, Closure $next, mixed ...$args...
    method hasValidNormalizedSignature (line 52) | private function hasValidNormalizedSignature(Request $request, array $...

FILE: app/Http/Requests/Api/V1/IndexCustomFieldsRequest.php
  class IndexCustomFieldsRequest (line 10) | final class IndexCustomFieldsRequest extends FormRequest
    method rules (line 19) | public function rules(): array

FILE: app/Http/Requests/Api/V1/IndexRequest.php
  class IndexRequest (line 9) | final class IndexRequest extends FormRequest
    method rules (line 14) | public function rules(): array

FILE: app/Http/Requests/Api/V1/StoreCompanyRequest.php
  class StoreCompanyRequest (line 11) | final class StoreCompanyRequest extends FormRequest
    method rules (line 16) | public function rules(): array

FILE: app/Http/Requests/Api/V1/StoreNoteRequest.php
  class StoreNoteRequest (line 12) | final class StoreNoteRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/StoreOpportunityRequest.php
  class StoreOpportunityRequest (line 12) | final class StoreOpportunityRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/StorePeopleRequest.php
  class StorePeopleRequest (line 12) | final class StorePeopleRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/StoreTaskRequest.php
  class StoreTaskRequest (line 12) | final class StoreTaskRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/UpdateCompanyRequest.php
  class UpdateCompanyRequest (line 11) | final class UpdateCompanyRequest extends FormRequest
    method rules (line 16) | public function rules(): array

FILE: app/Http/Requests/Api/V1/UpdateNoteRequest.php
  class UpdateNoteRequest (line 12) | final class UpdateNoteRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/UpdateOpportunityRequest.php
  class UpdateOpportunityRequest (line 12) | final class UpdateOpportunityRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/UpdatePeopleRequest.php
  class UpdatePeopleRequest (line 12) | final class UpdatePeopleRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/Api/V1/UpdateTaskRequest.php
  class UpdateTaskRequest (line 12) | final class UpdateTaskRequest extends FormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/ContactRequest.php
  class ContactRequest (line 11) | final class ContactRequest extends FormRequest
    method rules (line 14) | public function rules(): array

FILE: app/Http/Resources/V1/CompanyResource.php
  class CompanyResource (line 15) | final class CompanyResource extends JsonApiResource
    method toAttributes (line 22) | public function toAttributes(Request $request): array
    method toRelationships (line 40) | public function toRelationships(Request $request): array

FILE: app/Http/Resources/V1/Concerns/FormatsCustomFields.php
  type FormatsCustomFields (line 12) | trait FormatsCustomFields
    method formatCustomFields (line 14) | protected function formatCustomFields(Model $record): \stdClass
    method resolveFieldValue (line 31) | private function resolveFieldValue(CustomFieldValue $fieldValue): mixed
    method resolveSingleChoiceValue (line 50) | private function resolveSingleChoiceValue(CustomField $customField, mi...
    method resolveMultiChoiceValue (line 67) | private function resolveMultiChoiceValue(CustomField $customField, mix...

FILE: app/Http/Resources/V1/CustomFieldResource.php
  class CustomFieldResource (line 20) | final class CustomFieldResource extends JsonApiResource
    method toAttributes (line 25) | public function toAttributes(Request $request): array

FILE: app/Http/Resources/V1/NoteResource.php
  class NoteResource (line 15) | final class NoteResource extends JsonApiResource
    method toAttributes (line 22) | public function toAttributes(Request $request): array
    method toRelationships (line 39) | public function toRelationships(Request $request): array

FILE: app/Http/Resources/V1/OpportunityResource.php
  class OpportunityResource (line 15) | final class OpportunityResource extends JsonApiResource
    method toAttributes (line 22) | public function toAttributes(Request $request): array
    method toRelationships (line 40) | public function toRelationships(Request $request): array

FILE: app/Http/Resources/V1/PeopleResource.php
  class PeopleResource (line 15) | final class PeopleResource extends JsonApiResource
    method toAttributes (line 22) | public function toAttributes(Request $request): array
    method toRelationships (line 39) | public function toRelationships(Request $request): array

FILE: app/Http/Resources/V1/TaskResource.php
  class TaskResource (line 15) | final class TaskResource extends JsonApiResource
    method toAttributes (line 22) | public function toAttributes(Request $request): array
    method toRelationships (line 40) | public function toRelationships(Request $request): array

FILE: app/Http/Resources/V1/UserResource.php
  class UserResource (line 14) | final class UserResource extends JsonApiResource
    method toAttributes (line 19) | public function toAttributes(Request $request): array

FILE: app/Http/Responses/LoginResponse.php
  class LoginResponse (line 12) | final readonly class LoginResponse implements \Filament\Auth\Http\Respon...
    method toResponse (line 15) | public function toResponse($request): RedirectResponse|Redirector // @...

FILE: app/Jobs/Email/CreateSubscriberJob.php
  class CreateSubscriberJob (line 16) | final class CreateSubscriberJob implements ShouldQueue
    method __construct (line 20) | public function __construct(private readonly SubscriberData $data) {}
    method handle (line 25) | public function handle(): void

FILE: app/Jobs/Email/UpdateSubscriberJob.php
  class UpdateSubscriberJob (line 18) | final class UpdateSubscriberJob implements ShouldQueue
    method __construct (line 22) | public function __construct(private readonly SubscriberData $data) {}
    method handle (line 24) | public function handle(): void
    method uniqueId (line 42) | public function uniqueId(): string
    method middleware (line 52) | public function middleware(): array
    method retryUntil (line 60) | public function retryUntil(): \DateTime

FILE: app/Jobs/FetchFaviconForCompany.php
  class FetchFaviconForCompany (line 17) | final class FetchFaviconForCompany implements ShouldBeUnique, ShouldQueue
    method __construct (line 24) | public function __construct(public readonly Company $company) {}
    method handle (line 26) | public function handle(): void
    method uniqueId (line 78) | public function uniqueId(): string

FILE: app/Listeners/CreateTeamCustomFields.php
  class CreateTeamCustomFields (line 30) | final readonly class CreateTeamCustomFields
    method __construct (line 41) | public function __construct(
    method handle (line 46) | public function handle(TeamCreated $event): void
    method createCustomField (line 70) | private function createCustomField(string $model, CompanyCustomField|O...
    method applyColorsToOptions (line 107) | private function applyColorsToOptions(CustomField $customField, Compan...

FILE: app/Listeners/Email/NewSubscriberListener.php
  class NewSubscriberListener (line 20) | final class NewSubscriberListener implements ShouldHandleEventsAfterComm...
    method handle (line 28) | public function handle(Verified $event): void

FILE: app/Listeners/SwitchTeam.php
  class SwitchTeam (line 10) | final readonly class SwitchTeam
    method handle (line 15) | public function handle(TenantSet $event): void

FILE: app/Livewire/App/AccessTokens/CreateAccessToken.php
  class CreateAccessToken (line 23) | final class CreateAccessToken extends BaseLivewireComponent
    method mount (line 30) | public function mount(): void
    method form (line 38) | public function form(Schema $schema): Schema
    method showTokenAction (line 94) | public function showTokenAction(): Action
    method createToken (line 121) | public function createToken(): void
    method permissionsCheckboxList (line 173) | public static function permissionsCheckboxList(): CheckboxList
    method render (line 190) | public function render(): View

FILE: app/Livewire/App/AccessTokens/ManageAccessTokens.php
  class ManageAccessTokens (line 21) | final class ManageAccessTokens extends BaseLivewireComponent implements ...
    method refreshTokenList (line 25) | #[On('tokenCreated')]
    method table (line 31) | public function table(Table $table): Table
    method render (line 110) | public function render(): View

FILE: app/Livewire/App/Profile/DeleteAccount.php
  class DeleteAccount (line 24) | final class DeleteAccount extends BaseLivewireComponent
    method form (line 26) | public function form(Schema $schema): Schema
    method deleteAccount (line 67) | public function deleteAccount(?string $password = null): Redirector|Re...
    method render (line 101) | public function render(): View

FILE: app/Livewire/App/Profile/LogoutOtherBrowserSessions.php
  class LogoutOtherBrowserSessions (line 22) | final class LogoutOtherBrowserSessions extends BaseLivewireComponent
    method form (line 24) | public function form(Schema $schema): Schema
    method logoutOtherBrowserSessions (line 65) | public function logoutOtherBrowserSessions(?string $password): void
    method browserSessions (line 103) | public function browserSessions(): Collection
    method render (line 127) | public function render(): View

FILE: app/Livewire/App/Profile/UpdatePassword.php
  class UpdatePassword (line 20) | final class UpdatePassword extends BaseLivewireComponent
    method mount (line 25) | public function mount(): void
    method form (line 30) | public function form(Schema $schema): Schema
    method updatePassword (line 77) | public function updatePassword(): void
    method render (line 105) | public function render(): View

FILE: app/Livewire/App/Profile/UpdateProfileInformation.php
  class UpdateProfileInformation (line 24) | final class UpdateProfileInformation extends BaseLivewireComponent
    method mount (line 29) | public function mount(): void
    method form (line 36) | public function form(Schema $schema): Schema
    method updateProfile (line 73) | public function updateProfile(): void
    method sendEmailChangeVerification (line 99) | private function sendEmailChangeVerification(array $data): void
    method render (line 132) | public function render(): View

FILE: app/Livewire/App/Teams/AddTeamMember.php
  class AddTeamMember (line 26) | final class AddTeamMember extends BaseLivewireComponent
    method mount (line 33) | public function mount(Team $team): void
    method form (line 40) | public function form(Schema $schema): Schema
    method addTeamMember (line 82) | public function addTeamMember(Team $team): void
    method render (line 115) | public function render(): View

FILE: app/Livewire/App/Teams/DeleteTeam.php
  class DeleteTeam (line 20) | final class DeleteTeam extends BaseLivewireComponent
    method mount (line 24) | public function mount(Team $team): void
    method form (line 29) | public function form(Schema $schema): Schema
    method render (line 56) | public function render(): View
    method deleteTeam (line 61) | public function deleteTeam(Team $team): void

FILE: app/Livewire/App/Teams/PendingTeamInvitations.php
  class PendingTeamInvitations (line 22) | final class PendingTeamInvitations extends BaseLivewireComponent impleme...
    method mount (line 28) | public function mount(Team $team): void
    method table (line 33) | public function table(Table $table): Table
    method extendTeamInvitation (line 82) | public function extendTeamInvitation(Model $invitation): void
    method copyInviteLink (line 95) | public function copyInviteLink(Model $invitation): void
    method resendTeamInvitation (line 106) | public function resendTeamInvitation(Model $invitation): void
    method cancelTeamInvitation (line 128) | public function cancelTeamInvitation(Team $team, Model $invitation): void
    method render (line 137) | public function render(): View

FILE: app/Livewire/App/Teams/TeamMembers.php
  class TeamMembers (line 26) | final class TeamMembers extends BaseLivewireComponent implements Tables\...
    method mount (line 32) | public function mount(Team $team): void
    method table (line 37) | public function table(Table $table): Table
    method updateTeamRole (line 115) | public function updateTeamRole(Team $team, Membership $teamMember, arr...
    method removeTeamMember (line 135) | public function removeTeamMember(Team $team, Membership $teamMember): ...
    method leaveTeam (line 156) | public function leaveTeam(Team $team): void
    method render (line 179) | public function render(): View

FILE: app/Livewire/App/Teams/UpdateTeamName.php
  class UpdateTeamName (line 22) | final class UpdateTeamName extends BaseLivewireComponent
    method mount (line 31) | public function mount(Team $team): void
    method form (line 38) | public function form(Schema $schema): Schema
    method updateTeamName (line 82) | public function updateTeamName(Team $team): void
    method render (line 106) | public function render(): View

FILE: app/Livewire/BaseLivewireComponent.php
  class BaseLivewireComponent (line 22) | abstract class BaseLivewireComponent extends Component implements HasAct...
    method authUser (line 28) | public function authUser(): User
    method sendRateLimitedNotification (line 36) | protected function sendRateLimitedNotification(TooManyRequestsExceptio...
    method sendNotification (line 45) | protected function sendNotification(string $title = 'Saved', ?string $...

FILE: app/Livewire/UpdateProfileInformationForm.php
  class UpdateProfileInformationForm (line 15) | final class UpdateProfileInformationForm extends Component
    method mount (line 39) | public function mount(): void
    method updateProfileInformation (line 51) | public function updateProfileInformation(UpdatesUserProfileInformation...
    method deleteProfilePhoto (line 70) | public function deleteProfilePhoto(): void
    method sendEmailVerification (line 80) | public function sendEmailVerification(): void
    method user (line 90) | #[Computed]
    method render (line 99) | public function render(): View

FILE: app/Mail/NewContactSubmissionMail.php
  class NewContactSubmissionMail (line 14) | final class NewContactSubmissionMail extends Mailable implements ShouldQ...
    method __construct (line 19) | public function __construct(
    method envelope (line 23) | public function envelope(): Envelope
    method content (line 31) | public function content(): Content

FILE: app/Mcp/Filters/CustomFieldFilter.php
  class CustomFieldFilter (line 18) | final readonly class CustomFieldFilter implements Filter
    method __construct (line 30) | public function __construct(
    method __invoke (line 34) | public function __invoke(Builder $query, mixed $value, string $propert...
    method applyCondition (line 65) | private function applyCondition(
    method resolveFields (line 89) | private function resolveFields(array $fieldCodes): Collection

FILE: app/Mcp/Filters/CustomFieldSort.php
  class CustomFieldSort (line 16) | final readonly class CustomFieldSort implements Sort
    method __construct (line 18) | public function __construct(
    method __invoke (line 25) | public function __invoke(Builder $query, bool $descending, string $pro...
    method resolveField (line 47) | private function resolveField(string $code): ?CustomField
    method resolveAllFields (line 55) | private function resolveAllFields(): Collection

FILE: app/Mcp/Prompts/CrmOverviewPrompt.php
  class CrmOverviewPrompt (line 20) | #[Description('Get an overview of the CRM data for the current team, inc...
    method shouldRegister (line 25) | public function shouldRegister(): bool
    method handle (line 38) | public function handle(Request $request): Response

FILE: app/Mcp/Resources/CompanySchemaResource.php
  class CompanySchemaResource (line 17) | #[Description('Schema for companies including available custom fields. R...
    method shouldRegister (line 24) | public function shouldRegister(): bool
    method handle (line 37) | public function handle(Request $request): Response

FILE: app/Mcp/Resources/Concerns/ResolvesEntitySchema.php
  type ResolvesEntitySchema (line 14) | trait ResolvesEntitySchema
    method resolveCustomFields (line 19) | protected function resolveCustomFields(User $user, string $entityType)...
    method resolveFilterableFields (line 41) | protected function resolveFilterableFields(User $user, string $entityT...
    method formatCustomFields (line 52) | private function formatCustomFields(Collection $fields): array
    method fieldFormatHint (line 89) | private function fieldFormatHint(string $type): ?array

FILE: app/Mcp/Resources/CrmSummaryResource.php
  class CrmSummaryResource (line 26) | #[Description('CRM summary with record counts, pipeline breakdown by sta...
    method shouldRegister (line 31) | public function shouldRegister(): bool
    method handle (line 44) | public function handle(Request $request): Response
    method opportunitySummary (line 66) | private function opportunitySummary(mixed $teamId): array
    method taskSummary (line 126) | private function taskSummary(mixed $teamId): array
    method resolveFieldId (line 153) | private function resolveFieldId(mixed $teamId, string $entityType, str...

FILE: app/Mcp/Resources/NoteSchemaResource.php
  class NoteSchemaResource (line 17) | #[Description('Schema for notes including available custom fields. Read ...
    method shouldRegister (line 24) | public function shouldRegister(): bool
    method handle (line 37) | public function handle(Request $request): Response

FILE: app/Mcp/Resources/OpportunitySchemaResource.php
  class OpportunitySchemaResource (line 17) | #[Description('Schema for opportunities including available custom field...
    method shouldRegister (line 24) | public function shouldRegister(): bool
    method handle (line 37) | public function handle(Request $request): Response

FILE: app/Mcp/Resources/PeopleSchemaResource.php
  class PeopleSchemaResource (line 17) | #[Description('Schema for people (contacts) including available custom f...
    method shouldRegister (line 24) | public function shouldRegister(): bool
    method handle (line 37) | public function handle(Request $request): Response

FILE: app/Mcp/Resources/TaskSchemaResource.php
  class TaskSchemaResource (line 17) | #[Description('Schema for tasks including available custom fields. Read ...
    method shouldRegister (line 24) | public function shouldRegister(): bool
    method handle (line 37) | public function handle(Request $request): Response

FILE: app/Mcp/Schema/CustomFieldFilterSchema.php
  class CustomFieldFilterSchema (line 16) | final readonly class CustomFieldFilterSchema
    method build (line 42) | public function build(User $user, string $entityType): array
    method allowedSorts (line 67) | public function allowedSorts(User $user, string $entityType): array
    method operatorsForType (line 77) | private function operatorsForType(string $type): array
    method buildOperators (line 105) | private function buildOperators(array $operators, string $jsonType): a...
    method resolveFilterableFields (line 119) | private function resolveFilterableFields(User $user, string $entityTyp...

FILE: app/Mcp/Servers/RelaticleServer.php
  class RelaticleServer (line 51) | #[Name('Relaticle CRM')]

FILE: app/Mcp/Tools/BaseAttachTool.php
  class BaseAttachTool (line 17) | abstract class BaseAttachTool extends Tool
    method modelClass (line 23) | abstract protected function modelClass(): string;
    method entityLabel (line 25) | abstract protected function entityLabel(): string;
    method resourceClass (line 28) | abstract protected function resourceClass(): string;
    method relationshipSchema (line 31) | abstract protected function relationshipSchema(JsonSchema $schema): ar...
    method relationshipRules (line 34) | abstract protected function relationshipRules(User $user): array;
    method syncRelationships (line 37) | abstract protected function syncRelationships(Model $model, array $dat...
    method relationshipsToLoad (line 40) | protected function relationshipsToLoad(): array
    method schema (line 45) | public function schema(JsonSchema $schema): array
    method handle (line 55) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/BaseCreateTool.php
  class BaseCreateTool (line 17) | abstract class BaseCreateTool extends Tool
    method actionClass (line 22) | abstract protected function actionClass(): string;
    method resourceClass (line 25) | abstract protected function resourceClass(): string;
    method entityType (line 27) | abstract protected function entityType(): string;
    method entitySchema (line 32) | abstract protected function entitySchema(JsonSchema $schema): array;
    method entityRules (line 37) | abstract protected function entityRules(User $user): array;
    method schema (line 39) | public function schema(JsonSchema $schema): array
    method handle (line 49) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/BaseDeleteTool.php
  class BaseDeleteTool (line 15) | abstract class BaseDeleteTool extends Tool
    method modelClass (line 20) | abstract protected function modelClass(): string;
    method actionClass (line 23) | abstract protected function actionClass(): string;
    method entityLabel (line 25) | abstract protected function entityLabel(): string;
    method nameAttribute (line 27) | protected function nameAttribute(): string
    method schema (line 32) | public function schema(JsonSchema $schema): array
    method handle (line 41) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/BaseDetachTool.php
  class BaseDetachTool (line 17) | abstract class BaseDetachTool extends Tool
    method modelClass (line 23) | abstract protected function modelClass(): string;
    method entityLabel (line 25) | abstract protected function entityLabel(): string;
    method resourceClass (line 28) | abstract protected function resourceClass(): string;
    method relationshipSchema (line 31) | abstract protected function relationshipSchema(JsonSchema $schema): ar...
    method relationshipRules (line 34) | abstract protected function relationshipRules(User $user): array;
    method detachRelationships (line 37) | abstract protected function detachRelationships(Model $model, array $d...
    method relationshipsToLoad (line 40) | protected function relationshipsToLoad(): array
    method schema (line 45) | public function schema(JsonSchema $schema): array
    method handle (line 55) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/BaseListTool.php
  class BaseListTool (line 20) | abstract class BaseListTool extends Tool
    method actionClass (line 26) | abstract protected function actionClass(): string;
    method resourceClass (line 29) | abstract protected function resourceClass(): string;
    method searchFilterName (line 31) | abstract protected function searchFilterName(): string;
    method additionalSchema (line 36) | protected function additionalSchema(JsonSchema $schema): array
    method additionalFilters (line 44) | protected function additionalFilters(Request $request): array
    method schema (line 49) | public function schema(JsonSchema $schema): array
    method handle (line 64) | public function handle(Request $request): Response
    method buildHttpRequest (line 134) | private function buildHttpRequest(Request $mcpRequest): HttpRequest

FILE: app/Mcp/Tools/BaseShowTool.php
  class BaseShowTool (line 19) | #[IsReadOnly]
    method modelClass (line 27) | abstract protected function modelClass(): string;
    method resourceClass (line 30) | abstract protected function resourceClass(): string;
    method entityLabel (line 32) | abstract protected function entityLabel(): string;
    method allowedIncludes (line 37) | abstract protected function allowedIncludes(): array;
    method schema (line 39) | public function schema(JsonSchema $schema): array
    method handle (line 49) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/BaseUpdateTool.php
  class BaseUpdateTool (line 17) | abstract class BaseUpdateTool extends Tool
    method modelClass (line 22) | abstract protected function modelClass(): string;
    method actionClass (line 25) | abstract protected function actionClass(): string;
    method resourceClass (line 28) | abstract protected function resourceClass(): string;
    method entityType (line 30) | abstract protected function entityType(): string;
    method entityLabel (line 32) | abstract protected function entityLabel(): string;
    method entitySchema (line 37) | abstract protected function entitySchema(JsonSchema $schema): array;
    method entityRules (line 42) | abstract protected function entityRules(User $user): array;
    method schema (line 44) | public function schema(JsonSchema $schema): array
    method handle (line 57) | public function handle(Request $request): Response

FILE: app/Mcp/Tools/Company/CreateCompanyTool.php
  class CreateCompanyTool (line 14) | #[Description('Create a new company in the CRM. Use the crm-schema resou...
    method actionClass (line 17) | protected function actionClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityType (line 27) | protected function entityType(): string
    method entitySchema (line 32) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 39) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Company/DeleteCompanyTool.php
  class DeleteCompanyTool (line 13) | #[Description('Delete a company from the CRM (soft delete).')]
    method modelClass (line 17) | protected function modelClass(): string
    method actionClass (line 22) | protected function actionClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string

FILE: app/Mcp/Tools/Company/GetCompanyTool.php
  class GetCompanyTool (line 13) | #[Description('Get a single company by ID with full details and relation...
    method modelClass (line 16) | protected function modelClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method allowedIncludes (line 33) | protected function allowedIncludes(): array

FILE: app/Mcp/Tools/Company/ListCompaniesTool.php
  class ListCompaniesTool (line 14) | #[Description('List companies in the CRM with optional search and pagina...
    method actionClass (line 19) | protected function actionClass(): string
    method resourceClass (line 24) | protected function resourceClass(): string
    method searchFilterName (line 29) | protected function searchFilterName(): string

FILE: app/Mcp/Tools/Company/UpdateCompanyTool.php
  class UpdateCompanyTool (line 16) | #[Description('Update an existing company in the CRM. Use the crm-schema...
    method modelClass (line 20) | protected function modelClass(): string
    method actionClass (line 25) | protected function actionClass(): string
    method resourceClass (line 30) | protected function resourceClass(): string
    method entityType (line 35) | protected function entityType(): string
    method entityLabel (line 40) | protected function entityLabel(): string
    method entitySchema (line 45) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 52) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Concerns/BuildsRelationshipResponse.php
  type BuildsRelationshipResponse (line 12) | trait BuildsRelationshipResponse
    method buildRelationshipResponse (line 14) | protected function buildRelationshipResponse(Model $model): Response

FILE: app/Mcp/Tools/Concerns/ChecksTokenAbility.php
  type ChecksTokenAbility (line 10) | trait ChecksTokenAbility
    method ensureTokenCan (line 15) | protected function ensureTokenCan(string $ability): void

FILE: app/Mcp/Tools/Concerns/SerializesRelatedModels.php
  type SerializesRelatedModels (line 12) | trait SerializesRelatedModels
    method resolveRelationshipMap (line 20) | private function resolveRelationshipMap(string $resourceClass, Model $...
    method serializeRelatedModel (line 37) | private function serializeRelatedModel(Model $model, string $relation,...
    method serializeRelation (line 70) | private function serializeRelation(

FILE: app/Mcp/Tools/Note/AttachNoteToEntitiesTool.php
  class AttachNoteToEntitiesTool (line 16) | #[Description('Attach a note to companies, people, or opportunities. Add...
    method modelClass (line 19) | protected function modelClass(): string
    method entityLabel (line 24) | protected function entityLabel(): string
    method resourceClass (line 29) | protected function resourceClass(): string
    method relationshipsToLoad (line 35) | protected function relationshipsToLoad(): array
    method relationshipSchema (line 40) | public function relationshipSchema(JsonSchema $schema): array
    method relationshipRules (line 49) | public function relationshipRules(User $user): array
    method syncRelationships (line 63) | public function syncRelationships(Model $model, array $data): void

FILE: app/Mcp/Tools/Note/CreateNoteTool.php
  class CreateNoteTool (line 15) | #[Description('Create a new note in the CRM. Use the crm-schema resource...
    method actionClass (line 18) | protected function actionClass(): string
    method resourceClass (line 23) | protected function resourceClass(): string
    method entityType (line 28) | protected function entityType(): string
    method entitySchema (line 33) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 43) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Note/DeleteNoteTool.php
  class DeleteNoteTool (line 13) | #[Description('Delete a note from the CRM (soft delete).')]
    method modelClass (line 17) | protected function modelClass(): string
    method actionClass (line 22) | protected function actionClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method nameAttribute (line 32) | protected function nameAttribute(): string

FILE: app/Mcp/Tools/Note/DetachNoteFromEntitiesTool.php
  class DetachNoteFromEntitiesTool (line 16) | #[Description('Detach a note from companies, people, or opportunities. R...
    method modelClass (line 19) | protected function modelClass(): string
    method entityLabel (line 24) | protected function entityLabel(): string
    method resourceClass (line 29) | protected function resourceClass(): string
    method relationshipsToLoad (line 35) | protected function relationshipsToLoad(): array
    method relationshipSchema (line 40) | public function relationshipSchema(JsonSchema $schema): array
    method relationshipRules (line 49) | public function relationshipRules(User $user): array
    method detachRelationships (line 63) | public function detachRelationships(Model $model, array $data): void

FILE: app/Mcp/Tools/Note/GetNoteTool.php
  class GetNoteTool (line 13) | #[Description('Get a single note by ID with full details and relationshi...
    method modelClass (line 16) | protected function modelClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method allowedIncludes (line 33) | protected function allowedIncludes(): array

FILE: app/Mcp/Tools/Note/ListNotesTool.php
  class ListNotesTool (line 16) | #[Description('List notes in the CRM with optional search and pagination...
    method actionClass (line 21) | protected function actionClass(): string
    method resourceClass (line 26) | protected function resourceClass(): string
    method searchFilterName (line 31) | protected function searchFilterName(): string
    method additionalSchema (line 36) | protected function additionalSchema(JsonSchema $schema): array
    method additionalFilters (line 44) | protected function additionalFilters(Request $request): array

FILE: app/Mcp/Tools/Note/UpdateNoteTool.php
  class UpdateNoteTool (line 17) | #[Description('Update an existing note in the CRM. Use the crm-schema re...
    method modelClass (line 21) | protected function modelClass(): string
    method actionClass (line 26) | protected function actionClass(): string
    method resourceClass (line 31) | protected function resourceClass(): string
    method entityType (line 36) | protected function entityType(): string
    method entityLabel (line 41) | protected function entityLabel(): string
    method entitySchema (line 46) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 56) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Opportunity/CreateOpportunityTool.php
  class CreateOpportunityTool (line 15) | #[Description('Create a new opportunity (deal) in the CRM. Use the crm-s...
    method actionClass (line 18) | protected function actionClass(): string
    method resourceClass (line 23) | protected function resourceClass(): string
    method entityType (line 28) | protected function entityType(): string
    method entitySchema (line 33) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 42) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Opportunity/DeleteOpportunityTool.php
  class DeleteOpportunityTool (line 13) | #[Description('Delete an opportunity (deal) from the CRM (soft delete).')]
    method modelClass (line 17) | protected function modelClass(): string
    method actionClass (line 22) | protected function actionClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string

FILE: app/Mcp/Tools/Opportunity/GetOpportunityTool.php
  class GetOpportunityTool (line 13) | #[Description('Get a single opportunity by ID with full details and rela...
    method modelClass (line 16) | protected function modelClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method allowedIncludes (line 33) | protected function allowedIncludes(): array

FILE: app/Mcp/Tools/Opportunity/ListOpportunitiesTool.php
  class ListOpportunitiesTool (line 16) | #[Description('List opportunities (deals) in the CRM with optional searc...
    method actionClass (line 21) | protected function actionClass(): string
    method resourceClass (line 26) | protected function resourceClass(): string
    method searchFilterName (line 31) | protected function searchFilterName(): string
    method additionalSchema (line 36) | protected function additionalSchema(JsonSchema $schema): array
    method additionalFilters (line 44) | protected function additionalFilters(Request $request): array

FILE: app/Mcp/Tools/Opportunity/UpdateOpportunityTool.php
  class UpdateOpportunityTool (line 17) | #[Description('Update an existing opportunity (deal) in the CRM. Use the...
    method modelClass (line 21) | protected function modelClass(): string
    method actionClass (line 26) | protected function actionClass(): string
    method resourceClass (line 31) | protected function resourceClass(): string
    method entityType (line 36) | protected function entityType(): string
    method entityLabel (line 41) | protected function entityLabel(): string
    method entitySchema (line 46) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 55) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/People/CreatePeopleTool.php
  class CreatePeopleTool (line 15) | #[Description('Create a new person (contact) in the CRM. Use the crm-sch...
    method actionClass (line 18) | protected function actionClass(): string
    method resourceClass (line 23) | protected function resourceClass(): string
    method entityType (line 28) | protected function entityType(): string
    method entitySchema (line 33) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 41) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/People/DeletePeopleTool.php
  class DeletePeopleTool (line 13) | #[Description('Delete a person (contact) from the CRM (soft delete).')]
    method modelClass (line 17) | protected function modelClass(): string
    method actionClass (line 22) | protected function actionClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string

FILE: app/Mcp/Tools/People/GetPeopleTool.php
  class GetPeopleTool (line 13) | #[Description('Get a single person by ID with full details and relations...
    method modelClass (line 16) | protected function modelClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method allowedIncludes (line 33) | protected function allowedIncludes(): array

FILE: app/Mcp/Tools/People/ListPeopleTool.php
  class ListPeopleTool (line 16) | #[Description('List people (contacts) in the CRM with optional search an...
    method actionClass (line 21) | protected function actionClass(): string
    method resourceClass (line 26) | protected function resourceClass(): string
    method searchFilterName (line 31) | protected function searchFilterName(): string
    method additionalSchema (line 36) | protected function additionalSchema(JsonSchema $schema): array
    method additionalFilters (line 43) | protected function additionalFilters(Request $request): array

FILE: app/Mcp/Tools/People/UpdatePeopleTool.php
  class UpdatePeopleTool (line 17) | #[Description('Update an existing person (contact) in the CRM. Use the c...
    method modelClass (line 21) | protected function modelClass(): string
    method actionClass (line 26) | protected function actionClass(): string
    method resourceClass (line 31) | protected function resourceClass(): string
    method entityType (line 36) | protected function entityType(): string
    method entityLabel (line 41) | protected function entityLabel(): string
    method entitySchema (line 46) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 54) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Task/AttachTaskToEntitiesTool.php
  class AttachTaskToEntitiesTool (line 17) | #[Description('Attach a task to companies, people, opportunities, or ass...
    method modelClass (line 20) | protected function modelClass(): string
    method entityLabel (line 25) | protected function entityLabel(): string
    method resourceClass (line 30) | protected function resourceClass(): string
    method relationshipsToLoad (line 36) | protected function relationshipsToLoad(): array
    method relationshipSchema (line 41) | public function relationshipSchema(JsonSchema $schema): array
    method relationshipRules (line 51) | public function relationshipRules(User $user): array
    method syncRelationships (line 70) | public function syncRelationships(Model $model, array $data): void

FILE: app/Mcp/Tools/Task/CreateTaskTool.php
  class CreateTaskTool (line 16) | #[Description('Create a new task in the CRM. Use the crm-schema resource...
    method actionClass (line 19) | protected function actionClass(): string
    method resourceClass (line 24) | protected function resourceClass(): string
    method entityType (line 29) | protected function entityType(): string
    method entitySchema (line 34) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 45) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/Task/DeleteTaskTool.php
  class DeleteTaskTool (line 13) | #[Description('Delete a task from the CRM (soft delete).')]
    method modelClass (line 17) | protected function modelClass(): string
    method actionClass (line 22) | protected function actionClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method nameAttribute (line 32) | protected function nameAttribute(): string

FILE: app/Mcp/Tools/Task/DetachTaskFromEntitiesTool.php
  class DetachTaskFromEntitiesTool (line 17) | #[Description('Detach a task from companies, people, opportunities, or u...
    method modelClass (line 20) | protected function modelClass(): string
    method entityLabel (line 25) | protected function entityLabel(): string
    method resourceClass (line 30) | protected function resourceClass(): string
    method relationshipsToLoad (line 36) | protected function relationshipsToLoad(): array
    method relationshipSchema (line 41) | public function relationshipSchema(JsonSchema $schema): array
    method relationshipRules (line 51) | public function relationshipRules(User $user): array
    method detachRelationships (line 70) | public function detachRelationships(Model $model, array $data): void

FILE: app/Mcp/Tools/Task/GetTaskTool.php
  class GetTaskTool (line 13) | #[Description('Get a single task by ID with full details and relationshi...
    method modelClass (line 16) | protected function modelClass(): string
    method resourceClass (line 22) | protected function resourceClass(): string
    method entityLabel (line 27) | protected function entityLabel(): string
    method allowedIncludes (line 33) | protected function allowedIncludes(): array

FILE: app/Mcp/Tools/Task/ListTasksTool.php
  class ListTasksTool (line 16) | #[Description('List tasks in the CRM with optional search and pagination...
    method actionClass (line 21) | protected function actionClass(): string
    method resourceClass (line 26) | protected function resourceClass(): string
    method searchFilterName (line 31) | protected function searchFilterName(): string
    method additionalSchema (line 36) | protected function additionalSchema(JsonSchema $schema): array
    method additionalFilters (line 46) | protected function additionalFilters(Request $request): array

FILE: app/Mcp/Tools/Task/UpdateTaskTool.php
  class UpdateTaskTool (line 18) | #[Description('Update an existing task in the CRM. Use the crm-schema re...
    method modelClass (line 22) | protected function modelClass(): string
    method actionClass (line 27) | protected function actionClass(): string
    method resourceClass (line 32) | protected function resourceClass(): string
    method entityType (line 37) | protected function entityType(): string
    method entityLabel (line 42) | protected function entityLabel(): string
    method entitySchema (line 47) | protected function entitySchema(JsonSchema $schema): array
    method entityRules (line 58) | protected function entityRules(User $user): array

FILE: app/Mcp/Tools/WhoAmiTool.php
  class WhoAmiTool (line 19) | #[Description('Get information about the authenticated user, current tea...
    method schema (line 26) | public function schema(JsonSchema $schema): array
    method handle (line 31) | public function handle(Request $request): Response

FILE: app/Models/AiSummary.php
  class AiSummary (line 14) | final class AiSummary extends Model
    method casts (line 38) | protected function casts(): array
    method summarizable (line 49) | public function summarizable(): MorphTo

FILE: app/Models/Company.php
  class Company (line 36) | #[ObservedBy(CompanyObserver::class)]
    method casts (line 73) | protected function casts(): array
    method getLogoAttribute (line 80) | protected function getLogoAttribute(): string
    method accountOwner (line 92) | public function accountOwner(): BelongsTo
    method people (line 100) | public function people(): HasMany
    method opportunities (line 108) | public function opportunities(): HasMany
    method tasks (line 116) | public function tasks(): MorphToMany

FILE: app/Models/Concerns/BelongsToTeamCreator.php
  type BelongsToTeamCreator (line 16) | trait BelongsToTeamCreator
    method bootBelongsToTeamCreator (line 18) | public static function bootBelongsToTeamCreator(): void

FILE: app/Models/Concerns/HasAiSummary.php
  type HasAiSummary (line 13) | trait HasAiSummary
    method aiSummary (line 20) | public function aiSummary(): MorphOne
    method invalidateAiSummary (line 28) | public function invalidateAiSummary(): void

FILE: app/Models/Concerns/HasCreator.php
  type HasCreator (line 15) | trait HasCreator
    method creator (line 20) | public function creator(): BelongsTo
    method isSystemCreated (line 28) | public function isSystemCreated(): bool
    method createdBy (line 36) | protected function createdBy(): Attribute

FILE: app/Models/Concerns/HasNotes.php
  type HasNotes (line 10) | trait HasNotes
    method notes (line 15) | public function notes(): MorphToMany

FILE: app/Models/Concerns/HasProfilePhoto.php
  type HasProfilePhoto (line 11) | trait HasProfilePhoto
    method updateProfilePhoto (line 16) | public function updateProfilePhoto(string $photo): void
    method deleteProfilePhoto (line 30) | public function deleteProfilePhoto(): void
    method profilePhotoUrl (line 48) | protected function profilePhotoUrl(): Attribute
    method defaultProfilePhotoUrl (line 58) | protected function defaultProfilePhotoUrl(): string
    method profilePhotoDisk (line 70) | protected function profilePhotoDisk(): string
    method getAvatarAttribute (line 75) | protected function getAvatarAttribute(): string
    method getFilamentAvatarUrl (line 80) | public function getFilamentAvatarUrl(): string

FILE: app/Models/Concerns/HasTeam.php
  type HasTeam (line 10) | trait HasTeam
    method team (line 15) | public function team(): BelongsTo

FILE: app/Models/Concerns/InvalidatesRelatedAiSummaries.php
  type InvalidatesRelatedAiSummaries (line 11) | trait InvalidatesRelatedAiSummaries
    method invalidateRelatedSummaries (line 16) | public function invalidateRelatedSummaries(): void

FILE: app/Models/CustomField.php
  class CustomField (line 20) | #[ScopedBy([TenantScope::class, SortOrderScope::class])]
    method newFactory (line 27) | protected static function newFactory(): Factory

FILE: app/Models/CustomFieldOption.php
  class CustomFieldOption (line 13) | #[ScopedBy([TenantScope::class, SortOrderScope::class])]

FILE: app/Models/CustomFieldSection.php
  class CustomFieldSection (line 15) | #[ScopedBy([TenantScope::class, SortOrderScope::class])]

FILE: app/Models/CustomFieldValue.php
  class CustomFieldValue (line 12) | #[ScopedBy([TenantScope::class])]

FILE: app/Models/Export.php
  class Export (line 12) | final class Export extends FilamentExport

FILE: app/Models/Membership.php
  class Membership (line 13) | final class Membership extends JetstreamMembership
    method user (line 28) | public function user(): BelongsTo
    method team (line 36) | public function team(): BelongsTo
    method getRoleNameAttribute (line 41) | protected function getRoleNameAttribute(): string

FILE: app/Models/Note.php
  class Note (line 30) | #[ObservedBy(NoteObserver::class)]
    method casts (line 66) | protected function casts(): array
    method companies (line 76) | public function companies(): MorphToMany
    method people (line 84) | public function people(): MorphToMany
    method opportunities (line 92) | public function opportunities(): MorphToMany
    method forNotableType (line 98) | #[Scope]
    method forNotableId (line 115) | #[Scope]

FILE: app/Models/Opportunity.php
  class Opportunity (line 31) | #[ObservedBy(OpportunityObserver::class)]
    method casts (line 69) | protected function casts(): array
    method company (line 79) | public function company(): BelongsTo
    method contact (line 87) | public function contact(): BelongsTo
    method tasks (line 95) | public function tasks(): MorphToMany

FILE: app/Models/People.php
  class People (line 31) | #[ObservedBy(PeopleObserver::class)]
    method casts (line 69) | protected function casts(): array
    method getAvatarAttribute (line 76) | protected function getAvatarAttribute(): string
    method company (line 84) | public function company(): BelongsTo
    method tasks (line 92) | public function tasks(): MorphToMany

FILE: app/Models/PersonalAccessToken.php
  class PersonalAccessToken (line 12) | class PersonalAccessToken extends SanctumPersonalAccessToken
    method booted (line 22) | protected static function booted(): void
    method team (line 50) | public function team(): BelongsTo

FILE: app/Models/Scopes/TeamScope.php
  class TeamScope (line 15) | final class TeamScope implements Scope
    method apply (line 22) | public function apply(Builder $builder, Model $model): void

FILE: app/Models/Task.php
  class Task (line 36) | #[ObservedBy(TaskObserver::class)]
    method casts (line 70) | protected function casts(): array
    method assignees (line 88) | public function assignees(): BelongsToMany
    method companies (line 96) | public function companies(): MorphToMany
    method opportunities (line 104) | public function opportunities(): MorphToMany
    method people (line 112) | public function people(): MorphToMany
    method forCompany (line 118) | #[Scope]
    method forPerson (line 125) | #[Scope]
    method forOpportunity (line 132) | #[Scope]

FILE: app/Models/Team.php
  class Team (line 25) | final class Team extends JetstreamTeam implements HasAvatar
    method casts (line 119) | protected function casts(): array
    method getSlugOptions (line 126) | public function getSlugOptions(): SlugOptions
    method otherRecordExistsWithSlug (line 143) | protected function otherRecordExistsWithSlug(string $slug): bool
    method isPersonalTeam (line 159) | public function isPersonalTeam(): bool
    method getFilamentAvatarUrl (line 164) | public function getFilamentAvatarUrl(): string
    method people (line 172) | public function people(): HasMany
    method companies (line 180) | public function companies(): HasMany
    method tasks (line 188) | public function tasks(): HasMany
    method opportunities (line 196) | public function opportunities(): HasMany
    method notes (line 204) | public function notes(): HasMany

FILE: app/Models/TeamInvitation.php
  class TeamInvitation (line 14) | final class TeamInvitation extends JetstreamTeamInvitation
    method team (line 35) | public function team(): BelongsTo
    method isExpired (line 40) | public function isExpired(): bool
    method casts (line 55) | protected function casts(): array

FILE: app/Models/User.php
  class User (line 41) | final class User extends Authenticatable implements FilamentUser, HasAva...
    method casts (line 91) | protected function casts(): array
    method socialAccounts (line 102) | public function socialAccounts(): HasMany
    method hasPassword (line 107) | public function hasPassword(): bool
    method tasks (line 115) | public function tasks(): BelongsToMany
    method opportunities (line 123) | public function opportunities(): HasMany
    method getDefaultTenant (line 128) | public function getDefaultTenant(Panel $panel): ?Model
    method canAccessPanel (line 136) | public function canAccessPanel(Panel $panel): bool
    method getTenants (line 144) | public function getTenants(Panel $panel): Collection
    method canAccessTenant (line 149) | public function canAccessTenant(Model $tenant): bool

FILE: app/Models/UserSocialAccount.php
  class UserSocialAccount (line 13) | final class UserSocialAccount extends Model
    method user (line 23) | public function user(): BelongsTo

FILE: app/Observers/CompanyObserver.php
  class CompanyObserver (line 11) | final readonly class CompanyObserver
    method saved (line 13) | public function saved(Company $company): void
    method dispatchFaviconFetchIfNeeded (line 19) | private function dispatchFaviconFetchIfNeeded(Company $company): void

FILE: app/Observers/NoteObserver.php
  class NoteObserver (line 9) | final readonly class NoteObserver
    method saved (line 11) | public function saved(Note $note): void
    method deleted (line 16) | public function deleted(Note $note): void

FILE: app/Observers/OpportunityObserver.php
  class OpportunityObserver (line 9) | final readonly class OpportunityObserver
    method saved (line 15) | public function saved(Opportunity $opportunity): void

FILE: app/Observers/PeopleObserver.php
  class PeopleObserver (line 9) | final readonly class PeopleObserver
    method saved (line 15) | public function saved(People $people): void

FILE: app/Observers/TaskObserver.php
  class TaskObserver (line 9) | final readonly class TaskObserver
    method saved (line 11) | public function saved(Task $task): void
    method deleted (line 16) | public function deleted(Task $task): void

FILE: app/Policies/CompanyPolicy.php
  class CompanyPolicy (line 12) | final readonly class CompanyPolicy
    method viewAny (line 16) | public function viewAny(User $user): bool
    method view (line 21) | public function view(User $user, Company $company): bool
    method create (line 26) | public function create(User $user): bool
    method update (line 31) | public function update(User $user, Company $company): bool
    method delete (line 36) | public function delete(User $user, Company $company): bool
    method deleteAny (line 41) | public function deleteAny(User $user): bool
    method restore (line 46) | public function restore(User $user, Company $company): bool
    method restoreAny (line 51) | public function restoreAny(User $user): bool
    method forceDelete (line 56) | public function forceDelete(User $user): bool
    method forceDeleteAny (line 61) | public function forceDeleteAny(User $user): bool

FILE: app/Policies/NotePolicy.php
  class NotePolicy (line 12) | final readonly class NotePolicy
    method viewAny (line 16) | public function viewAny(User $user): bool
    method view (line 21) | public function view(User $user, Note $note): bool
    method create (line 26) | public function create(User $user): bool
    method update (line 31) | public function update(User $user, Note $note): bool
    method delete (line 36) | public function delete(User $user, Note $note): bool
    method deleteAny (line 41) | public function deleteAny(User $user): bool
    method restore (line 46) | public function restore(User $user, Note $note): bool
    method restoreAny (line 51) | public function restoreAny(User $user): bool
    method forceDelete (line 56) | public function forceDelete(User $user): bool
    method forceDeleteAny (line 61) | public function forceDeleteAny(User $user): bool

FILE: app/Policies/OpportunityPolicy.php
  class OpportunityPolicy (line 12) | final readonly class OpportunityPolicy
    method viewAny (line 16) | public function viewAny(User $user): bool
    method view (line 21) | public function view(User $user, Opportunity $opportunity): bool
    method create (line 26) | public function create(User $user): bool
    method update (line 31) | public function update(User $user, Opportunity $opportunity): bool
    method delete (line 36) | public function delete(User $user, Opportunity $opportunity): bool
    method deleteAny (line 41) | public function deleteAny(User $user): bool
    method restore (line 46) | public function restore(User $user, Opportunity $opportunity): bool
    method restoreAny (line 51) | public function restoreAny(User $user): bool
    method forceDelete (line 56) | public function forceDelete(User $user): bool
    method forceDeleteAny (line 61) | public function forceDeleteAny(User $user): bool

FILE: app/Policies/PeoplePolicy.php
  class PeoplePolicy (line 12) | final readonly class PeoplePolicy
    method viewAny (line 16) | public function viewAny(User $user): bool
    method view (line 21) | public function view(User $user, People $people): bool
    method create (line 26) | public function create(User $user): bool
    method update (line 31) | public function update(User $user, People $people): bool
    method delete (line 36) | public function delete(User $user, People $people): bool
    method deleteAny (line 41) | public function deleteAny(User $user): bool
    method restore (line 46) | public function restore(User $user, People $people): bool
    method restoreAny (line 51) | public function restoreAny(User $user): bool
    method forceDelete (line 56) | public function forceDelete(User $user, People $people): bool
    method forceDeleteAny (line 61) | public function forceDeleteAny(User $user): bool

FILE: app/Policies/TaskPolicy.php
  class TaskPolicy (line 12) | final readonly class TaskPolicy
    method viewAny (line 16) | public function viewAny(User $user): bool
    method view (line 21) | public function view(User $user, Task $task): bool
    method create (line 26) | public function create(User $user): bool
    method update (line 31) | public function update(User $user, Task $task): bool
    method delete (line 36) | public function delete(User $user, Task $task): bool
    method deleteAny (line 41) | public function deleteAny(User $user): bool
    method restore (line 46) | public function restore(User $user, Task $task): bool
    method restoreAny (line 51) | public function restoreAny(User $user): bool
    method forceDelete (line 56) | public function forceDelete(User $user, Task $task): bool
    method forceDeleteAny (line 61) | public function forceDeleteAny(User $user): bool

FILE: app/Policies/TeamPolicy.php
  class TeamPolicy (line 11) | final readonly class TeamPolicy
    method viewAny (line 18) | public function viewAny(User $user): bool
    method view (line 26) | public function view(User $user, Team $team): bool
    method create (line 34) | public function create(User $user): bool
    method update (line 42) | public function update(User $user, Team $team): bool
    method addTeamMember (line 50) | public function addTeamMember(User $user, Team $team): bool
    method updateTeamMember (line 58) | public function updateTeamMember(User $user, Team $team): bool
    method removeTeamMember (line 66) | public function removeTeamMember(User $user, Team $team): bool
    method delete (line 74) | public function delete(User $user, Team $team): bool
    method deleteAny (line 79) | public function deleteAny(): bool
    method restore (line 84) | public function restore(User $user, Team $team): bool
    method restoreAny (line 89) | public function restoreAny(): bool
    method forceDelete (line 94) | public function forceDelete(User $user, Team $team): bool
    method forceDeleteAny (line 99) | public function forceDeleteAny(): bool

FILE: app/Providers/AppServiceProvider.php
  class AppServiceProvider (line 39) | final class AppServiceProvider extends ServiceProvider
    method register (line 44) | public function register(): void
    method boot (line 53) | public function boot(): void
    method configurePolicies (line 66) | private function configurePolicies(): void
    method getDefaultLaravelPolicyName (line 90) | private function getDefaultLaravelPolicyName(string $modelClass): ?string
    method configureLivewire (line 122) | private function configureLivewire(): void
    method configureRateLimiting (line 127) | private function configureRateLimiting(): void
    method configureScribe (line 152) | private function configureScribe(): void
    method configureModels (line 190) | private function configureModels(): void
    method configureFilament (line 216) | private function configureFilament(): void
    method configureGitHubStars (line 232) | private function configureGitHubStars(): void

FILE: app/Providers/FaviconServiceProvider.php
  class FaviconServiceProvider (line 12) | final class FaviconServiceProvider extends ServiceProvider
    method boot (line 14) | public function boot(): void

FILE: app/Providers/Filament/AppPanelProvider.php
  class AppPanelProvider (line 51) | final class AppPanelProvider extends PanelProvider
    method boot (line 56) | public function boot(): void
    method panel (line 77) | public function panel(Panel $panel): Panel
    method shouldRegisterMenuItem (line 217) | public function shouldRegisterMenuItem(): bool

FILE: app/Providers/FortifyServiceProvider.php
  class FortifyServiceProvider (line 19) | final class FortifyServiceProvider extends ServiceProvider
    method register (line 24) | public function register(): void
    method boot (line 32) | public function boot(): void

FILE: app/Providers/HealthServiceProvider.php
  class HealthServiceProvider (line 26) | final class HealthServiceProvider extends ServiceProvider
    method boot (line 28) | public function boot(): void
    method isEnabled (line 93) | private function isEnabled(): bool

FILE: app/Providers/HorizonServiceProvider.php
  class HorizonServiceProvider (line 12) | final class HorizonServiceProvider extends HorizonApplicationServiceProv...
    method boot (line 17) | #[Override]
    method gate (line 32) | protected function gate(): void

FILE: app/Providers/JetstreamServiceProvider.php
  class JetstreamServiceProvider (line 19) | final class JetstreamServiceProvider extends ServiceProvider
    method register (line 24) | public function register(): void
    method boot (line 32) | public function boot(): void
    method configureModels (line 42) | private function configureModels(): void
    method configureActions (line 51) | private function configureActions(): void
    method configurePermissions (line 65) | private function configurePermissions(): void

FILE: app/Providers/MacroServiceProvider.php
  class MacroServiceProvider (line 10) | final class MacroServiceProvider extends ServiceProvider
    method boot (line 12) | public function boot(): void

FILE: app/Rules/ValidCustomFields.php
  class ValidCustomFields (line 18) | final readonly class ValidCustomFields implements ValidationRule
    method __construct (line 20) | public function __construct(
    method toRules (line 30) | public function toRules(mixed $submittedFields = null): array
    method validate (line 69) | public function validate(string $attribute, mixed $value, Closure $fai...
    method ensureNullableForDateFields (line 103) | private function ensureNullableForDateFields(string $fieldType, array ...
    method addChoiceFieldOptionRules (line 127) | private function addChoiceFieldOptionRules(BaseCustomField $customFiel...
    method resolveCustomFields (line 163) | private function resolveCustomFields(array $submittedCodes): EloquentC...

FILE: app/Rules/ValidTeamSlug.php
  class ValidTeamSlug (line 12) | final readonly class ValidTeamSlug implements ValidationRule
    method __construct (line 14) | public function __construct(
    method validate (line 21) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: app/Scribe/Strategies/GetFromSpatieQueryBuilder.php
  class GetFromSpatieQueryBuilder (line 20) | final class GetFromSpatieQueryBuilder extends Strategy
    method __invoke (line 26) | public function __invoke(ExtractedEndpointData $endpointData, array $r...
    method isIndexMethod (line 41) | private function isIndexMethod(ExtractedEndpointData $endpointData): bool
    method findActionClass (line 51) | private function findActionClass(ExtractedEndpointData $endpointData):...
    method extractQueryParams (line 78) | private function extractQueryParams(string $actionClass): array
    method getMethodSource (line 98) | private function getMethodSource(ReflectionMethod $method): string
    method extractFilters (line 121) | private function extractFilters(string $source, array &$params): void
    method extractSorts (line 138) | private function extractSorts(string $source, array &$params): void
    method extractIncludes (line 159) | private function extractIncludes(string $source, array &$params): void
    method addPaginationParams (line 180) | private function addPaginationParams(array &$params): void

FILE: app/Services/AI/RecordContextBuilder.php
  class RecordContextBuilder (line 25) | final readonly class RecordContextBuilder
    method buildContext (line 34) | public function buildContext(Model $record): array
    method buildCompanyContext (line 47) | private function buildCompanyContext(Company $company): array
    method buildPeopleContext (line 78) | private function buildPeopleContext(People $person): array
    method buildOpportunityContext (line 104) | private function buildOpportunityContext(Opportunity $opportunity): array
    method recentWithCustomFields (line 129) | private function recentWithCustomFields(string $table): Closure
    method getCompanyBasicInfo (line 140) | private function getCompanyBasicInfo(Company $company): array
    method getPeopleBasicInfo (line 154) | private function getPeopleBasicInfo(People $person): array
    method getOpportunityBasicInfo (line 167) | private function getOpportunityBasicInfo(Opportunity $opportunity): array
    method getOpportunityName (line 179) | private function getOpportunityName(Opportunity $opportunity): string
    method formatNotes (line 190) | private function formatNotes(Collection $notes, int $totalCount): array
    method formatTasks (line 205) | private function formatTasks(Collection $tasks, int $totalCount): array
    method formatOpportunities (line 221) | private function formatOpportunities(Collection $opportunities, int $t...
    method withPaginationInfo (line 239) | private function withPaginationInfo(array $items, int $totalCount): array
    method getCustomFieldValue (line 251) | private function getCustomFieldValue(Model $model, string $code): mixed
    method formatDate (line 269) | private function formatDate(mixed $date): ?string
    method stripHtml (line 280) | private function stripHtml(string $html): string

FILE: app/Services/AI/RecordSummaryService.php
  class RecordSummaryService (line 17) | final readonly class RecordSummaryService
    method __construct (line 19) | public function __construct(
    method model (line 23) | private function model(): string
    method getSummary (line 31) | public function getSummary(Model $record, bool $regenerate = false): A...
    method generateAndCacheSummary (line 44) | private function generateAndCacheSummary(Model $record): AiSummary
    method cacheSummary (line 58) | private function cacheSummary(Model $record, string $summary, Usage $u...
    method getSystemPrompt (line 79) | private function getSystemPrompt(): string
    method formatPrompt (line 99) | private function formatPrompt(array $context): string
    method addBasicInfo (line 121) | private function addBasicInfo(Collection $parts, array $context): void
    method addRelationships (line 146) | private function addRelationships(Collection $parts, array $context): ...
    method addOpportunities (line 162) | private function addOpportunities(Collection $parts, array $context): ...
    method addNotes (line 188) | private function addNotes(Collection $parts, array $context): void
    method addTasks (line 215) | private function addTasks(Collection $parts, array $context): void
    method formatTaskLine (line 238) | private function formatTaskLine(array $task): string
    method addTimestamps (line 259) | private function addTimestamps(Collection $parts, array $context): void
    method formatLabel (line 268) | private function formatLabel(string $key): string

FILE: app/Services/AvatarService.php
  class AvatarService (line 10) | final readonly class AvatarService
    method __construct (line 20) | public function __construct(
    method generate (line 38) | public function generate(
    method generateAuto (line 68) | public function generateAuto(string $name, int $size = 64, int $initia...
    method createSvgDataUrl (line 104) | private function createSvgDataUrl(
    method validateColor (line 128) | public function validateColor(?string $color): bool
    method getInitials (line 151) | private function getInitials(string $name, int $initialCount = 2): string
    method getBackgroundColor (line 222) | private function getBackgroundColor(string $name): string
    method generateSvg (line 244) | private function generateSvg(string $initials, string $bgColor, string...
    method getHueFromName (line 264) | private function getHueFromName(string $name): int
    method generateContrastingTextColor (line 282) | private function generateContrastingTextColor(string $bgColor): string
    method hslToHex (line 303) | private function hslToHex(int $h, float $s, float $l): string
    method hexToHsl (line 329) | private function hexToHsl(string $hexColor): array
    method hueToRgb (line 381) | private function hueToRgb(float $p, float $q, float $t): float
    method calculateContrastRatio (line 405) | private function calculateContrastRatio(string $color1, string $color2...
    method getRelativeLuminance (line 419) | private function getRelativeLuminance(string $hexColor): float
    method hasEnoughContrast (line 446) | private function hasEnoughContrast(string $color1, string $color2): bool
    method analyzeNameCharacteristics (line 454) | private function analyzeNameCharacteristics(string $name): array
    method calculateUniquenessScore (line 504) | private function calculateUniquenessScore(string $name): float

FILE: app/Services/Favicon/Drivers/GoogleHighResDriver.php
  class GoogleHighResDriver (line 15) | final class GoogleHighResDriver implements Fetcher
    method __construct (line 23) | public function __construct(private readonly int $size = 256) {}
    method fetch (line 25) | public function fetch(string $url): ?Favicon
    method fetchAll (line 45) | public function fetchAll(string $url): FaviconCollection

FILE: app/Services/Favicon/Drivers/HighQualityDriver.php
  class HighQualityDriver (line 16) | final class HighQualityDriver implements Fetcher
    method fetch (line 31) | public function fetch(string $url): ?Favicon
    method fetchAll (line 57) | public function fetchAll(string $url): FaviconCollection
    method tryAppleTouchIcon (line 62) | private function tryAppleTouchIcon(string $url): ?Favicon
    method tryHighResFavicon (line 106) | private function tryHighResFavicon(string $url): ?Favicon
    method tryGoogleHighRes (line 156) | private function tryGoogleHighRes(string $url): ?Favicon
    method tryDuckDuckGo (line 182) | private function tryDuckDuckGo(string $url): ?Favicon
    method faviconIsAccessible (line 207) | private function faviconIsAccessible(Favicon $favicon): bool
    method convertToAbsoluteUrl (line 219) | private function convertToAbsoluteUrl(string $baseUrl, string $path): ...
    method stripPathFromUrl (line 240) | private function stripPathFromUrl(string $url): string

FILE: app/Services/GitHubService.php
  class GitHubService (line 14) | final readonly class GitHubService
    method getStarsCount (line 23) | public function getStarsCount(string $owner = 'Relaticle', string $rep...
    method getFormattedStarsCount (line 56) | public function getFormattedStarsCount(string $owner = 'Relaticle', st...

FILE: app/Support/CustomFieldMerger.php
  class CustomFieldMerger (line 19) | final readonly class CustomFieldMerger
    method merge (line 25) | public static function merge(Model $model, array $attributes): array
    method normalizeValue (line 59) | private static function normalizeValue(mixed $value): mixed

FILE: app/View/Components/GuestLayout.php
  class GuestLayout (line 11) | final class GuestLayout extends Component
    method __construct (line 16) | public function __construct(
    method render (line 27) | #[Override]

FILE: database/factories/CompanyFactory.php
  class CompanyFactory (line 17) | final class CompanyFactory extends Factory
    method definition (line 26) | public function definition(): array
    method configure (line 35) | public function configure(): Factory

FILE: database/factories/CustomFieldFactory.php
  class CustomFieldFactory (line 14) | final class CustomFieldFactory extends Factory
    method definition (line 18) | public function definition(): array
    method configure (line 35) | public function configure(): static

FILE: database/factories/NoteFactory.php
  class NoteFactory (line 16) | final class NoteFactory extends Factory
    method definition (line 23) | public function definition(): array
    method configure (line 31) | public function configure(): Factory

FILE: database/factories/OpportunityFactory.php
  class OpportunityFactory (line 16) | final class OpportunityFactory extends Factory
    method definition (line 20) | public function definition(): array
    method configure (line 28) | public function configure(): Factory

FILE: database/factories/PeopleFactory.php
  class PeopleFactory (line 16) | final class PeopleFactory extends Factory
    method definition (line 23) | public function definition(): array
    method configure (line 31) | public function configure(): Factory

FILE: database/factories/SystemAdministratorFactory.php
  class SystemAdministratorFactory (line 17) | final class SystemAdministratorFactory extends Factory
    method definition (line 26) | public function definition(): array
    method unverified (line 41) | public function unverified(): static
    method configure (line 48) | public function configure(): Factory

FILE: database/factories/TaskFactory.php
  class TaskFactory (line 17) | final class TaskFactory extends Factory
    method definition (line 21) | public function definition(): array
    method configure (line 31) | public function configure(): Factory

FILE: database/factories/TeamFactory.php
  class TeamFactory (line 16) | final class TeamFactory extends Factory
    method definition (line 23) | public function definition(): array
    method configure (line 32) | public function configure(): static

FILE: database/factories/TeamInvitationFactory.php
  class TeamInvitationFactory (line 14) | final class TeamInvitationFactory extends Factory
    method definition (line 21) | public function definition(): array
    method expired (line 31) | public function expired(): static
    method expiresIn (line 38) | public function expiresIn(int $days): static
    method withoutExpiry (line 45) | public function withoutExpiry(): static

FILE: database/factories/UserFactory.php
  class UserFactory (line 17) | final class UserFactory extends Factory
    method definition (line 29) | #[\Override]
    method unverified (line 48) | public function unverified(): static
    method withPersonalTeam (line 58) | public function withPersonalTeam(?callable $callback = null): UserFactory
    method withTeam (line 79) | public function withTeam(?callable $callback = null): static
    method socialOnly (line 97) | public function socialOnly(): static
    method configure (line 104) | public function configure(): Factory

FILE: database/factories/UserSocialAccountFactory.php
  class UserSocialAccountFactory (line 15) | final class UserSocialAccountFactory extends Factory
    method definition (line 24) | public function definition(): array
    method configure (line 33) | public function configure(): Factory

FILE: database/migrations/0001_01_01_000000_create_users_table.php
  method up (line 14) | public function up(): void
  method down (line 47) | public function down(): void

FILE: database/migrations/0001_01_01_000001_create_cache_table.php
  method up (line 14) | public function up(): void
  method down (line 32) | public function down(): void

FILE: database/migrations/0001_01_01_000002_create_jobs_table.php
  method up (line 14) | public function up(): void
  method down (line 53) | public function down(): void

FILE: database/migrations/2024_08_23_110718_create_teams_table.php
  method up (line 14) | public function up(): void
  method down (line 28) | public function down(): void

FILE: database/migrations/2024_08_23_110719_create_team_user_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2024_08_23_110720_create_team_invitations_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2024_08_24_133803_create_companies_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2024_09_11_114549_create_tasks_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2024_09_22_084119_create_notes_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2024_09_22_091034_create_people_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2024_09_22_092300_create_task_user_table.php
  method up (line 14) | public function up(): void
  method down (line 29) | public function down(): void

FILE: database/migrations/2024_09_22_110651_add_two_factor_columns_to_users_table.php
  method up (line 15) | public function up(): void
  method down (line 37) | public function down(): void

FILE: database/migrations/2024_09_22_110718_create_personal_access_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2024_09_22_114735_create_opportunities_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2024_09_26_160649_create_user_social_accounts_table.php
  method up (line 14) | public function up(): void
  method down (line 35) | public function down(): void

FILE: database/migrations/2024_09_26_170133_create_notifications_table.php
  method up (line 14) | public function up(): void
  method down (line 29) | public function down(): void

FILE: database/migrations/2025_02_07_192236_create_custom_fields_table.php
  method up (line 13) | public function up(): void
  method down (line 159) | public function down(): void

FILE: database/migrations/2025_03_15_180559_create_taskables_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2025_03_15_192334_create_notables_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2025_03_17_180206_create_media_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2025_04_30_143551_add_creation_source_to_entity_tables.php
  method up (line 22) | public function up(): void

FILE: database/migrations/2025_05_08_112613_create_imports_table.php
  method up (line 14) | public function up(): void
  method down (line 36) | public function down(): void

FILE: database/migrations/2025_05_08_112614_create_exports_table.php
  method up (line 14) | public function up(): void
  method down (line 36) | public function down(): void

FILE: database/migrations/2025_05_08_112615_create_failed_import_rows_table.php
  method up (line 14) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2025_07_05_093310_update_opportunity_amount_field_type_to_currency.php
  method up (line 13) | public function up(): void
  method shouldRun (line 42) | public function shouldRun(): bool

FILE: database/migrations/2025_08_12_202409_add_settings_to_custom_field_options_table.php
  method up (line 14) | public function up(): void
  method shouldRun (line 24) | public function shouldRun(): bool
  method down (line 32) | public function down(): void

FILE: database/migrations/2025_08_25_173222_update_order_column_to_flowforge_position_for_tasks_and_opportunities.php
  method up (line 16) | public function up(): void
  method setTaskOrderColumns (line 46) | private function setTaskOrderColumns(): void
  method setOpportunityOrderColumns (line 83) | private function setOpportunityOrderColumns(): void
  method setPositionsForGroup (line 123) | private function setPositionsForGroup(array $records, string $table): void
  method down (line 168) | public function down(): void

FILE: database/migrations/2025_08_26_124042_create_system_administrators_table.php
  method up (line 14) | public function up(): void
  method down (line 36) | public function down(): void

FILE: database/migrations/2025_11_30_202612_create_ai_summaries_table.php
  method up (line 14) | public function up(): void
  method down (line 33) | public function down(): void

FILE: database/migrations/2025_12_10_191207_update_people_emails_field_type_to_email.php
  method up (line 19) | public function up(): void

FILE: database/migrations/2025_12_11_000001_update_company_domain_name_settings.php
  method up (line 20) | public function up(): void

FILE: database/migrations/2025_12_20_000000_migrate_to_ulid.php
  method up (line 107) | public function up(): void
  method migrateForRelationalDb (line 138) | private function migrateForRelationalDb(): void
  method phaseA_addUlidToCoreTables (line 223) | private function phaseA_addUlidToCoreTables(): void
  method phaseA_addForeignUlidsToCoreTablesAndPopulate (line 246) | private function phaseA_addForeignUlidsToCoreTablesAndPopulate(): void
  method phaseA_addUlidsToOtherEntityTables (line 282) | private function phaseA_addUlidsToOtherEntityTables(): void
  method phaseA_addUlidsToPivotTables (line 321) | private function phaseA_addUlidsToPivotTables(): void
  method phaseA_addUlidsToPolymorphicTables (line 344) | private function phaseA_addUlidsToPolymorphicTables(): void
  method phaseA_addUlidsToTenantScopedTables (line 365) | private function phaseA_addUlidsToTenantScopedTables(): void
  method phaseA_addUlidsToCustomFieldTables (line 386) | private function phaseA_addUlidsToCustomFieldTables(): void
  method phaseA7b_migrateOptionValueReferences (line 411) | private function phaseA7b_migrateOptionValueReferences(): void
  method phaseA8_migrateEmailFieldValues (line 457) | private function phaseA8_migrateEmailFieldValues(): void
  method phaseA9_migrateDomainFieldValues (line 509) | private function phaseA9_migrateDomainFieldValues(): void
  method phaseB_dropAllForeignKeyConstraints (line 574) | private function phaseB_dropAllForeignKeyConstraints(): void
  method phaseB_cutoverCorePrimaryKeys (line 646) | private function phaseB_cutoverCorePrimaryKeys(): void
  method phaseB_cutoverCoreForeignKeys (line 656) | private function phaseB_cutoverCoreForeignKeys(): void
  method phaseB_cutoverOtherEntityTables (line 692) | private function phaseB_cutoverOtherEntityTables(): void
  method phaseB_cutoverPivotTables (line 718) | private function phaseB_cutoverPivotTables(): void
  method phaseB_cutoverPolymorphicTables (line 740) | private function phaseB_cutoverPolymorphicTables(): void
  method phaseB_cutoverTenantScopedTables (line 752) | private function phaseB_cutoverTenantScopedTables(): void
  method phaseB_cutoverCustomFieldTables (line 764) | private function phaseB_cutoverCustomFieldTables(): void
  method phaseB_recreateUniqueIndexes (line 779) | private function phaseB_recreateUniqueIndexes(): void
  method phaseB9_recreateForeignKeyConstraints (line 823) | private function phaseB9_recreateForeignKeyConstraints(): void
  method addUlidPrimaryKeyColumn (line 945) | private function addUlidPrimaryKeyColumn(string $tableName): void
  method addAndPopulateForeignUlid (line 964) | private function addAndPopulateForeignUlid(string $tableName, string $fk...
  method addAndPopulateMorphUlid (line 988) | private function addAndPopulateMorphUlid(string $tableName, string $morp...
  method cutoverPrimaryKey (line 1058) | private function cutoverPrimaryKey(string $table): void
  method cutoverForeignKeyColumn (line 1088) | private function cutoverForeignKeyColumn(string $tableName, string $fkCo...
  method cutoverMorphColumn (line 1106) | private function cutoverMorphColumn(string $tableName, string $morphName...
  method migrateForSqlite (line 1145) | private function migrateForSqlite(): void
  method rebuildTableWithUlidPrimarySqlite (line 1188) | private function rebuildTableWithUlidPrimarySqlite(string $tableName): void
  method rebuildPivotTableSqlite (line 1238) | private function rebuildPivotTableSqlite(string $tableName, array $forei...
  method rebuildPivotWithMorphSqlite (line 1267) | private function rebuildPivotWithMorphSqlite(string $tableName, string $...
  method rebuildMorphTableSqlite (line 1291) | private function rebuildMorphTableSqlite(string $tableName, string $morp...
  method rebuildForeignKeysSqlite (line 1317) | private function rebuildForeignKeysSqlite(string $tableName, array $fore...
  method isAlreadyUlid (line 1345) | private function isAlreadyUlid(string $table, string $column): bool

FILE: database/migrations/2025_12_27_122241_convert_order_column_to_decimal_and_regenerate_positions.php
  method up (line 16) | public function up(): void
  method regenerateTaskPositions (line 46) | private function regenerateTaskPositions(): void
  method regenerateOpportunityPositions (line 84) | private function regenerateOpportunityPositions(): void
  method setPositionsForGroup (line 125) | private function setPositionsForGroup(array $records, string $table): void
  method down (line 147) | public function down(): void

FILE: database/migrations/2026_01_02_152157_update_phone_number_custom_fields_type.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2026_01_12_225824_upgrade_custom_fields_to_v3.php
  method up (line 10) | public function up(): void

FILE: database/migrations/2026_02_11_232804_add_slug_to_teams_table.php
  method up (line 13) | public function up(): void
  method backfillSlugs (line 26) | private function backfillSlugs(): void

FILE: database/migrations/2026_02_12_222910_expand_imports_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2026_02_13_002721_cleanup_imports_table.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2026_02_15_214730_drop_sessions_user_id_foreign_key.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2026_02_20_212853_add_team_id_to_personal_access_tokens_table.php
  method up (line 12) | public function up(): void
  method ensureTeamsPrimaryKey (line 25) | private function ensureTeamsPrimaryKey(): void

FILE: database/migrations/2026_02_25_124942_add_team_id_indexes_to_entity_tables.php
  method up (line 14) | public function up(): void

FILE: database/migrations/2026_03_15_201741_add_custom_field_value_filtering_indexes.php
  method up (line 11) | public function up(): void

FILE: database/migrations/2026_03_18_202956_add_expires_at_to_team_invitations_table.php
  method up (line 11) | public function up(): void

FILE: database/seeders/DatabaseSeeder.php
  class DatabaseSeeder (line 10) | final class DatabaseSeeder extends Seeder
    method run (line 15) | public function run(): void

FILE: database/seeders/LocalSeeder.php
  class LocalSeeder (line 17) | final class LocalSeeder extends Seeder
    method run (line 19) | public function run(): void

FILE: database/seeders/SystemAdministratorSeeder.php
  class SystemAdministratorSeeder (line 11) | final class SystemAdministratorSeeder extends Seeder
    method run (line 16) | public function run(): void

FILE: packages/Documentation/resources/js/documentation.js
  function addCopyButtons (line 2) | function addCopyButtons() {
  function adjustSidebarHeights (line 150) | function adjustSidebarHeights() {

FILE: packages/Documentation/src/Components/Card.php
  class Card (line 10) | final class Card extends Component
    method __construct (line 15) | public function __construct(
    method render (line 29) | public function render(): View

FILE: packages/Documentation/src/Data/DocumentData.php
  class DocumentData (line 11) | final class DocumentData extends Data
    method __construct (line 13) | public function __construct(
    method fromType (line 32) | public static function fromType(string $type): self
    method extractTableOfContents (line 75) | private static function extractTableOfContents(string $contents): array
    method getMarkdownPath (line 91) | private static function getMarkdownPath(string $file): string

FILE: packages/Documentation/src/Data/DocumentSearchRequest.php
  class DocumentSearchRequest (line 13) | final class DocumentSearchRequest extends Data
    method __construct (line 15) | public function __construct(
    method rules (line 27) | public static function rules(): array

FILE: packages/Documentation/src/Data/DocumentSearchResultData.php
  class DocumentSearchResultData (line 12) | final class DocumentSearchResultData extends Data
    method __construct (line 14) | public function __construct(
    method generateUrl (line 35) | public static function generateUrl(string $type): string

FILE: packages/Documentation/src/DocumentationServiceProvider.php
  class DocumentationServiceProvider (line 12) | final class DocumentationServiceProvider extends ServiceProvider
    method register (line 17) | public function register(): void
    method boot (line 27) | public function boot(): void
    method registerRoutes (line 38) | private function registerRoutes(): void
    method registerViews (line 49) | private function registerViews(): void
    method registerComponents (line 57) | private function registerComponents(): void
    method registerPublishing (line 69) | private function registerPublishing(): void

FILE: packages/Documentation/src/Http/Controllers/DocumentationController.php
  class DocumentationController (line 12) | final readonly class DocumentationController
    method __construct (line 14) | public function __construct(
    method index (line 21) | public function index(): View
    method show (line 31) | public function show(string $type = 'business'): View
    method search (line 48) | public function search(Request $request): View

FILE: packages/Documentation/src/Services/DocumentationService.php
  class DocumentationService (line 14) | final class DocumentationService
    method getDocument (line 19) | public function getDocument(string $type): DocumentData
    method getAllDocumentTypes (line 37) | public function getAllDocumentTypes(): array
    method search (line 47) | public function search(DocumentSearchRequest $searchRequest): Collection
    method generateExcerpt (line 108) | private function generateExcerpt(string $content, string $query): string
    method calculateRelevance (line 141) | private function calculateRelevance(string $content, string $query): f...
    method getMarkdownPath (line 165) | private function getMarkdownPath(string $file): string

FILE: packages/ImportWizard/src/Commands/CleanupImportsCommand.php
  class CleanupImportsCommand (line 13) | final class CleanupImportsCommand extends Command
    method handle (line 21) | public function handle(): void
    method cleanupTerminalImportFiles (line 34) | private function cleanupTerminalImportFiles(int $completedHours): int
    method cleanupAbandonedImports (line 58) | private function cleanupAbandonedImports(int $staleHours): int
    method cleanupOrphanedDirectories (line 77) | private function cleanupOrphanedDirectories(): int

FILE: packages/ImportWizard/src/Data/ColumnData.php
  class ColumnData (line 28) | final class ColumnData extends Data implements Wireable
    method __construct (line 38) | public function __construct(
    method toField (line 46) | public static function toField(string $source, string $target): self
    method toEntityLink (line 54) | public static function toEntityLink(
    method getType (line 66) | public function getType(): FieldDataType
    method isMultiChoicePredefined (line 77) | public function isMultiChoicePredefined(): bool
    method isSingleChoicePredefined (line 82) | public function isSingleChoicePredefined(): bool
    method isMultiChoiceArbitrary (line 87) | public function isMultiChoiceArbitrary(): bool
    method getRules (line 93) | public function getRules(): array
    method getLabel (line 98) | public function getLabel(): string
    method getIcon (line 107) | public function getIcon(): string
    method getMatcher (line 116) | public function getMatcher(): ?MatchableField
    method isFieldMapping (line 125) | public function isFieldMapping(): bool
    method isEntityLinkMapping (line 130) | public function isEntityLinkMapping(): bool
    method resolveEntityLinkContext (line 142) | public function resolveEntityLinkContext(BaseImporter $importer): ?array
    method toArray (line 165) | public function toArray(): array
    method withDateFormat (line 176) | public function withDateFormat(DateFormat $format): self
    method withNumberFormat (line 181) | public function withNumberFormat(NumberFormat $format): self
    method cloneWith (line 186) | private function cloneWith(?DateFormat $dateFormat = null, ?NumberForm...

FILE: packages/ImportWizard/src/Data/EntityLink.php
  class EntityLink (line 23) | final class EntityLink extends Data
    method __construct (line 40) | public function __construct(
    method cloneWith (line 61) | private function cloneWith(array $overrides): self
    method belongsTo (line 81) | public static function belongsTo(string $name, string $modelClass): self
    method morphToMany (line 94) | public static function morphToMany(string $name, string $modelClass): ...
    method fromCustomField (line 108) | public static function fromCustomField(CustomField $customField): self
    method company (line 135) | public static function company(): self
    method contact (line 150) | public static function contact(): self
    method polymorphicCompanies (line 166) | public static function polymorphicCompanies(): self
    method polymorphicPeople (line 179) | public static function polymorphicPeople(): self
    method polymorphicOpportunities (line 193) | public static function polymorphicOpportunities(): self
    method matchableFields (line 205) | public function matchableFields(array $matchableFields): self
    method foreignKey (line 210) | public function foreignKey(string $foreignKey): self
    method morphRelation (line 215) | public function morphRelation(string $relation): self
    method guess (line 221) | public function guess(array $guesses): self
    method label (line 226) | public function label(string $label): self
    method getHighestPriorityMatcher (line 231) | public function getHighestPriorityMatcher(): ?MatchableField
    method getMatcher (line 242) | public function getMatcher(string $field): ?MatchableField
    method matchesHeader (line 248) | public function matchesHeader(string $header): bool
    method normalizeHeader (line 257) | private function normalizeHeader(string $value): string
    method icon (line 262) | public function icon(): string
    method isForeignKey (line 267) | public function isForeignKey(): bool
    method isMorphToMany (line 272) | public function isMorphToMany(): bool
    method isCustomFieldValue (line 277) | public function isCustomFieldValue(): bool
    method isFromRelationship (line 282) | public function isFromRelationship(): bool
    method isFromCustomField (line 287) | public function isFromCustomField(): bool
    method getStorageStrategy (line 292) | public function getStorageStrategy(): EntityLinkStorageInterface
    method getEntityAliasForModel (line 302) | private static function getEntityAliasForModel(string $modelClass): st...
    method getUniqueMatchableFieldsForEntity (line 316) | private static function getUniqueMatchableFieldsForEntity(string $mode...

FILE: packages/ImportWizard/src/Data/ImportField.php
  class ImportField (line 15) | final class ImportField extends Data
    method __construct (line 31) | public function __construct(
    method make (line 49) | public static function make(string $key): self
    method id (line 60) | public static function id(): self
    method label (line 76) | public function label(string $label): self
    method required (line 84) | public function required(bool $required = true): self
    method rules (line 94) | public function rules(array $rules): self
    method guess (line 104) | public function guess(array $aliases): self
    method example (line 112) | public function example(string $example): self
    method asCustomField (line 120) | public function asCustomField(bool $isCustomField = true): self
    method type (line 128) | public function type(?FieldDataType $type): self
    method icon (line 136) | public function icon(?string $icon): self
    method sortOrder (line 144) | public function sortOrder(?int $sortOrder): self
    method acceptsArbitraryValues (line 152) | public function acceptsArbitraryValues(bool $accepts = true): self
    method options (line 162) | public function options(?array $options): self
    method cloneWith (line 172) | private function cloneWith(array $overrides): self
    method matchesHeader (line 195) | public function matchesHeader(string $header): bool
    method normalizeHeader (line 204) | private function normalizeHeader(string $value): string

FILE: packages/ImportWizard/src/Data/ImportFieldCollection.php
  class ImportFieldCollection (line 17) | final class ImportFieldCollection extends Collection
    method get (line 20) | public function get(mixed $key, mixed $default = null): ?ImportField
    method hasKey (line 28) | public function hasKey(string $key): bool
    method guessFor (line 41) | public function guessFor(string $header): ?ImportField
    method required (line 49) | public function required(): static
    method optional (line 57) | public function optional(): static
    method standard (line 65) | public function standard(): static
    method custom (line 73) | public function custom(): static

FILE: packages/ImportWizard/src/Data/InferenceResult.php
  class InferenceResult (line 12) | final class InferenceResult extends Data
    method __construct (line 19) | public function __construct(

FILE: packages/ImportWizard/src/Data/MatchableField.php
  class MatchableField (line 10) | final class MatchableField extends Data
    method __construct (line 12) | public function __construct(
    method id (line 20) | public static function id(): self
    method email (line 30) | public static function email(
    method domain (line 43) | public static function domain(
    method phone (line 56) | public static function phone(
    method name (line 69) | public static function name(): self
    method description (line 79) | public function description(): string
    method isCreate (line 84) | public function isCreate(): bool

FILE: packages/ImportWizard/src/Data/RelationshipMatch.php
  class RelationshipMatch (line 11) | final class RelationshipMatch extends Data
    method __construct (line 13) | public function __construct(
    method existing (line 22) | public static function existing(string $relationship, string $id, ?Mat...
    method create (line 33) | public static function create(string $relationship, string $name, ?Mat...
    method isExisting (line 44) | public function isExisting(): bool
    method isCreate (line 49) | public function isCreate(): bool

FILE: packages/ImportWizard/src/Enums/DateFormat.php
  method getLabel (line 23) | public function getLabel(): string
  method getExamples (line 37) | public function getExamples(bool $withTime = false): array
  method format (line 57) | public function format(Carbon $date, bool $withTime = false): string
  method toOptions (line 77) | public static function toOptions(bool $withTime = false): array
  method parse (line 97) | public function parse(string $value, bool $withTime = false): ?Carbon
  method toPickerValue (line 123) | public function toPickerValue(Carbon $date, bool $withTime = false): string
  method getParseFormats (line 133) | private function getParseFormats(bool $withTime): array

FILE: packages/ImportWizard/src/Enums/ImportEntityType.php
  method label (line 22) | public function label(): string
  method singular (line 33) | public function singular(): string
  method importerClass (line 49) | public function importerClass(): string
  method icon (line 60) | public function icon(): string
  method importer (line 71) | public function importer(string $teamId): BaseImporter

FILE: packages/ImportWizard/src/Enums/MatchBehavior.php
  method description (line 13) | public function description(): string
  method performsLookup (line 22) | public function performsLookup(): bool
  method createsOnNoMatch (line 27) | public function createsOnNoMatch(): bool

FILE: packages/ImportWizard/src/Enums/NumberFormat.php
  method getLabel (line 20) | public function getLabel(): string
  method getExample (line 31) | public function getExample(): string
  method parse (line 45) | public function parse(string $value): ?float
  method format (line 80) | public function format(float $value, int $decimals = 2): string
  method toOptions (line 93) | public static function toOptions(): array

FILE: packages/ImportWizard/src/Enums/ReviewFilter.php
  method getLabel (line 17) | public function getLabel(): string
  method getIcon (line 27) | public function getIcon(): ?string

FILE: packages/ImportWizard/src/Enums/RowMatchAction.php
  method icon (line 13) | public function icon(): string
  method color (line 22) | public function color(): string

FILE: packages/ImportWizard/src/Enums/SortDirection.php
  method getLabel (line 15) | public function getLabel(): string
  method getIcon (line 23) | public function getIcon(): string

FILE: packages/ImportWizard/src/Enums/SortField.php
  method getLabel (line 15) | public function getLabel(): string
  method getIcon (line 23) | public function getIcon(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportCompanies.php
  class ImportCompanies (line 13) | final class ImportCompanies extends ImportPage
    method getEntityType (line 17) | public static function getEntityType(): ImportEntityType
    method getResourceClass (line 22) | public static function getResourceClass(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportHistory.php
  class ImportHistory (line 21) | final class ImportHistory extends Page implements HasTable
    method table (line 37) | public function table(Table $table): Table

FILE: packages/ImportWizard/src/Filament/Pages/ImportNotes.php
  class ImportNotes (line 10) | final class ImportNotes extends ImportPage
    method getEntityType (line 14) | public static function getEntityType(): ImportEntityType
    method getResourceClass (line 19) | public static function getResourceClass(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportOpportunities.php
  class ImportOpportunities (line 10) | final class ImportOpportunities extends ImportPage
    method getEntityType (line 14) | public static function getEntityType(): ImportEntityType
    method getResourceClass (line 19) | public static function getResourceClass(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportPage.php
  class ImportPage (line 16) | abstract class ImportPage extends Page
    method canAccess (line 31) | public static function canAccess(): bool
    method getEntityType (line 45) | abstract public static function getEntityType(): ImportEntityType;
    method getResourceClass (line 52) | abstract public static function getResourceClass(): string;
    method getTitle (line 54) | #[Override]
    method getSubheading (line 60) | #[Override]
    method getBreadcrumbs (line 71) | public function getBreadcrumbs(): array
    method getReturnUrl (line 89) | public function getReturnUrl(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportPeople.php
  class ImportPeople (line 10) | final class ImportPeople extends ImportPage
    method getEntityType (line 14) | public static function getEntityType(): ImportEntityType
    method getResourceClass (line 19) | public static function getResourceClass(): string

FILE: packages/ImportWizard/src/Filament/Pages/ImportTasks.php
  class ImportTasks (line 13) | final class ImportTasks extends ImportPage
    method getEntityType (line 17) | public static function getEntityType(): ImportEntityType
    method getResourceClass (line 22) | public static function getResourceClass(): string

FILE: packages/ImportWizard/src/Http/Controllers/DownloadFailedRowsController.php
  class DownloadFailedRowsController (line 13) | final class DownloadFailedRowsController
    method __invoke (line 15) | public function __invoke(Request $request, Import $import): StreamedRe...

FILE: packages/ImportWizard/src/ImportWizardNewServiceProvider.php
  class ImportWizardNewServiceProvider (line 17) | final class ImportWizardNewServiceProvider extends ServiceProvider
    method register (line 19) | public function register(): void
    method boot (line 24) | public function boot(): void
    method registerCommands (line 33) | private function registerCommands(): void
    method registerRoutes (line 40) | private function registerRoutes(): void
    method registerViews (line 48) | private function registerViews(): void
    method registerTranslations (line 53) | private function registerTranslations(): void
    method registerLivewireComponents (line 58) | private function registerLivewireComponents(): void

FILE: packages/ImportWizard/src/Importers/BaseImporter.php
  class BaseImporter (line 28) | abstract class BaseImporter implements ImporterContract
    method __construct (line 37) | public function __construct(
    method getTeamId (line 41) | public function getTeamId(): string
    method getTeam (line 46) | public function getTeam(): ?Team
    method allFields (line 57) | public function allFields(): ImportFieldCollection
    method entityLinks (line 71) | public function entityLinks(): array
    method defineEntityLinks (line 94) | protected function defineEntityLinks(): array
    method getRecordCustomFields (line 100) | protected function getRecordCustomFields(): EloquentCollection
    method matchableFields (line 119) | public function matchableFields(): array
    method prepareForSave (line 136) | public function prepareForSave(array $data, ?Model $existing, array &$...
    method afterSave (line 150) | public function afterSave(Model $record, array $context): void
    method customFields (line 161) | protected function customFields(): ImportFieldCollection
    method shouldLoadOptions (line 209) | private function shouldLoadOptions(CustomField $customField): bool
    method buildCustomFieldGuesses (line 218) | private function buildCustomFieldGuesses(string $code, string $name): ...
    method initializeNewRecordData (line 243) | protected function initializeNewRecordData(array $data, ?string $creat...
    method saveCustomFieldValues (line 252) | protected function saveCustomFieldValues(Model $record): void
    method getMatchFieldForMappedColumns (line 266) | public function getMatchFieldForMappedColumns(array $mappedFields): ?M...

FILE: packages/ImportWizard/src/Importers/CompanyImporter.php
  class CompanyImporter (line 16) | final class CompanyImporter extends BaseImporter
    method modelClass (line 18) | public function modelClass(): string
    method entityName (line 23) | public function entityName(): string
    method fields (line 28) | public function fields(): ImportFieldCollection
    method defineEntityLinks (line 50) | protected function defineEntityLinks(): array
    method matchableFields (line 70) | public function matchableFields(): array
    method prepareForSave (line 83) | public function prepareForSave(array $data, ?Model $existing, array &$...

FILE: packages/ImportWizard/src/Importers/Contracts/ImporterContract.php
  type ImporterContract (line 18) | interface ImporterContract
    method getTeamId (line 23) | public function getTeamId(): string;
    method modelClass (line 30) | public function modelClass(): string;
    method entityName (line 35) | public function entityName(): string;
    method fields (line 40) | public function fields(): ImportFieldCollection;
    method allFields (line 45) | public function allFields(): ImportFieldCollection;
    method entityLinks (line 52) | public function entityLinks(): array;
    method matchableFields (line 59) | public function matchableFields(): array;
    method getMatchFieldForMappedColumns (line 66) | public function getMatchFieldForMappedColumns(array $mappedFields): ?M...
    method prepareForSave (line 79) | public function prepareForSave(array $data, ?Model $existing, array &$...
    method afterSave (line 90) | public function afterSave(Model $record, array $context): void;

FILE: packages/ImportWizard/src/Importers/NoteImporter.php
  class NoteImporter (line 20) | final class NoteImporter extends BaseImporter
    method modelClass (line 22) | public function modelClass(): string
    method entityName (line 27) | public function entityName(): string
    method fields (line 32) | public function fields(): ImportFieldCollection
    method defineEntityLinks (line 53) | protected function defineEntityLinks(): array
    method matchableFields (line 67) | public function matchableFields(): array
    method prepareForSave (line 77) | public function prepareForSave(array $data, ?Model $existing, array &$...

FILE: packages/ImportWizard/src/Importers/OpportunityImporter.php
  class OpportunityImporter (line 20) | final class OpportunityImporter extends BaseImporter
    method modelClass (line 22) | public function modelClass(): string
    method entityName (line 27) | public function entityName(): string
    method fields (line 32) | public function fields(): ImportFieldCollection
    method defineEntityLinks (line 54) | protected function defineEntityLinks(): array
    method matchableFields (line 65) | public function matchableFields(): array
    method prepareForSave (line 77) | public function prepareForSave(array $data, ?Model $existing, array &$...

FILE: packages/ImportWizard/src/Importers/PeopleImporter.php
  class PeopleImporter (line 19) | final class PeopleImporter extends BaseImporter
    method modelClass (line 21) | public function modelClass(): string
    method entityName (line 26) | public function entityName(): string
    method fields (line 31) | public function fields(): ImportFieldCollection
    method defineEntityLinks (line 54) | protected function defineEntityLinks(): array
    method matchableFields (line 64) | public function matchableFields(): array
    method prepareForSave (line 78) | public function prepareForSave(array $data, ?Model $existing, array &$...

FILE: packages/ImportWizard/src/Importers/TaskImporter.php
  class TaskImporter (line 22) | final class TaskImporter extends BaseImporter
    method modelClass (line 24) | public function modelClass(): string
    method entityName (line 29) | public function entityName(): string
    method fields (line 34) | public function fields(): ImportFieldCollection
    method defineEntityLinks (line 56) | protected function defineEntityLinks(): array
    method matchableFields (line 78) | public function matchableFields(): array
    method prepareForSave (line 90) | public function prepareForSave(array $data, ?Model $existing, array &$...

FILE: packages/ImportWizard/src/Jobs/ExecuteImportJob.php
  class ExecuteImportJob (line 46) | final class ExecuteImportJob implements ShouldQueue
    method __construct (line 81) | public function __construct(
    method handle (line 88) | public function handle(): void
    method failed (line 168) | public function failed(\Throwable $exception): void
    method processRow (line 202) | private function processRow(
    method loadCustomFieldDefinitions (line 306) | private function loadCustomFieldDefinitions(BaseImporter $importer): C...
    method collectCustomFieldValues (line 325) | private function collectCustomFieldValues(
    method mergeWithExistingMultiChoiceValues (line 382) | private function mergeWithExistingMultiChoiceValues(
    method flushCustomFieldValues (line 425) | private function flushCustomFieldValues(): void
    method markProcessed (line 453) | private function markProcessed(ImportRow $row): void
    method flushProcessedRows (line 458) | private function flushProcessedRows(ImportStore $store): void
    method preloadExistingRecords (line 483) | private function preloadExistingRecords(Collection $rows, BaseImporter...
    method recordFailedRow (line 506) | private function recordFailedRow(int $rowNumber, array $rawData, \Thro...
    method persistResults (line 516) | private function persistResults(Import $import, array $results): void
    method flushFailedRows (line 526) | private function flushFailedRows(Import $import): void
    method buildDataFromRow (line 555) | private function buildDataFromRow(ImportRow $row, Collection $fieldMap...
    method extractCustomFieldData (line 568) | private function extractCustomFieldData(array &$prepared): array
    method buildCustomFieldFormatMap (line 595) | private function buildCustomFieldFormatMap(Collection $fieldMappings):...
    method convertCustomFieldValue (line 608) | private function convertCustomFieldValue(mixed $value, CustomField $cf...
    method resolveChoiceValue (line 646) | private function resolveChoiceValue(CustomField $cf, string $value): i...
    method resolveMultiChoiceValue (line 674) | private function resolveMultiChoiceValue(CustomField $cf, string $valu...
    method allowedAttributeKeys (line 692) | private function allowedAttributeKeys(BaseImporter $importer): array
    method findExistingRecord (line 709) | private function findExistingRecord(BaseImporter $importer, ?string $m...
    method resolveMatchField (line 729) | private function resolveMatchField(BaseImporter $importer, Collection ...
    method findMatchSourceColumn (line 746) | private function findMatchSourceColumn(MatchableField $matchField, Col...
    method lookupMatchableValueCache (line 755) | private function lookupMatchableValueCache(ImportRow $row, MatchableFi...
    method registerInMatchableValueCache (line 766) | private function registerInMatchableValueCache(ImportRow $row, Matchab...
    method normalizeMatchableValues (line 781) | private function normalizeMatchableValues(ImportRow $row, MatchableFie...
    method resolveEntityLinkRelationships (line 804) | private function resolveEntityLinkRelationships(
    method resolveGroupedMatches (line 849) | private function resolveGroupedMatches(
    method resolveCreationMatch (line 901) | private function resolveCreationMatch(Collection $matches): ?Relations...
    method populateMatchingCustomField (line 913) | private function populateMatchingCustomField(
    method resolveRecordFieldByName (line 970) | private function resolveRecordFieldByName(
    method notifyUser (line 992) | private function notifyUser(Import $import, array $results, bool $fail...
    method storeEntityLinkRelationships (line 1018) | private function storeEntityLinkRelationships(

FILE: packages/ImportWizard/src/Jobs/ResolveMatchesJob.php
  class ResolveMatchesJob (line 17) | final class ResolveMatchesJob implements ShouldQueue
    method __construct (line 29) | public function __construct(
    method handle (line 35) | public function handle(): void

FILE: packages/ImportWizard/src/Jobs/ValidateColumnJob.php
  class ValidateColumnJob (line 23) | final class ValidateColumnJob implements ShouldQueue
    method __construct (line 35) | public function __construct(
    method handle (line 42) | public function handle(): void
    method validateEntityLink (line 77) | private function validateEntityLink(Import $import, ImportStore $store...
    method writeEntityLinkRelationships (line 104) | private function writeEntityLinkRelationships(
    method clearValidationForCorrectedDateFields (line 173) | private function clearValidationForCorrectedDateFields(
    method fetchUncorrectedUniqueValues (line 189) | private function fetchUncorrectedUniqueValues(ImportStore $store, stri...
    method validateValues (line 203) | private function validateValues(Import $import, array $uniqueValues): ...
    method hydrateColumnField (line 221) | private function hydrateColumnField(Import $import): void
    method updateValidationErrors (line 236) | private function updateValidationErrors(

FILE: packages/ImportWizard/src/Livewire/Concerns/WithImportStore.php
  type WithImportStore (line 13) | trait WithImportStore
    method mountWithImportStore (line 25) | public function mountWithImportStore(string $storeId, ImportEntityType...
    method import (line 31) | protected function import(): Import
    method refreshImport (line 42) | protected function refreshImport(): Import
    method store (line 49) | protected function store(): ImportStore
    method getCurrentTeamId (line 58) | private function getCurrentTeamId(): ?string
    method headers (line 66) | protected function headers(): array
    method rowCount (line 71) | protected function rowCount(): int

FILE: packages/ImportWizard/src/Livewire/ImportWizard.php
  class ImportWizard (line 24) | final class ImportWizard extends Component implements HasActions, HasForms
    method mount (line 54) | public function mount(ImportEntityType $entityType, ?string $returnUrl...
    method render (line 62) | public function render(): View
    method onUploadCompleted (line 67) | public function onUploadCompleted(string $storeId, int $rowCount, int ...
    method nextStep (line 75) | public function nextStep(): void
    method goBack (line 80) | public function goBack(): void
    method goToStep (line 90) | public function goToStep(int $step): void
    method getStepTitle (line 110) | public function getStepTitle(): string
    method getStepDescription (line 121) | public function getStepDescription(): string
    method cancelImport (line 135) | public function cancelImport(): void
    method onImportStarted (line 146) | #[On('import-started')]
    method startOverAction (line 152) | public function startOverAction(): Action
    method startOver (line 166) | public function startOver(): void
    method restoreFromStore (line 179) | private function restoreFromStore(): void
    method syncStepStatus (line 199) | private function syncStepStatus(): void
    method findCurrentImport (line 205) | private function findCurrentImport(): ?Import
    method statusForStep (line 224) | private function statusForStep(int $step): ImportStatus
    method stepFromStatus (line 234) | private function stepFromStatus(ImportStatus $status): int
    method destroyImportAndStore (line 244) | private function destroyImportAndStore(string $importId): void
    method sanitizeReturnUrl (line 260) | private function sanitizeReturnUrl(?string $url): ?string
    method getCurrentTeamId (line 273) | private function getCurrentTeamId(): ?string

FILE: packages/ImportWizard/src/Livewire/Steps/MappingStep.php
  class MappingStep (line 28) | final class MappingStep extends Component implements HasActions, HasForms
    method mount (line 39) | public function mount(string $storeId, ImportEntityType $entityType): ...
    method render (line 49) | public function render(): View
    method allFields (line 57) | #[Computed]
    method entityLinks (line 64) | #[Computed]
    method unmappedRequired (line 70) | #[Computed]
    method hasEntityLinks (line 80) | #[Computed]
    method mappedFieldKeys (line 87) | #[Computed]
    method isMapped (line 98) | public function isMapped(string $source): bool
    method isTargetMapped (line 103) | public function isTargetMapped(string $target): bool
    method getMapping (line 109) | public function getMapping(string $source): ?ColumnData
    method getSourceForTarget (line 118) | public function getSourceForTarget(string $target): ?string
    method getFieldForSource (line 126) | public function getFieldForSource(string $source): ?ImportField
    method getEntityLinkForSource (line 138) | public function getEntityLinkForSource(string $source): ?array
    method previewValues (line 156) | public function previewValues(string $column, int $limit = 5): array
    method canProceed (line 166) | public function canProceed(): bool
    method autoMap (line 171) | public function autoMap(): void
    method autoMapByHeaders (line 178) | private function autoMapByHeaders(): void
    method autoMapEntityLinks (line 195) | private function autoMapEntityLinks(): void
    method isEntityLinkMapped (line 225) | public function isEntityLinkMapped(string $linkKey): bool
    method getMappedEntityLinkMatchers (line 232) | public function getMappedEntityLinkMatchers(): array
    method inferDataTypes (line 242) | private function inferDataTypes(): void
    method mapToField (line 272) | public function mapToField(string $source, string $target): void
    method mapToEntityLink (line 285) | public function mapToEntityLink(string $source, string $matcherKey, st...
    method unmapColumn (line 290) | public function unmapColumn(string $source): void
    method continueAction (line 295) | public function continueAction(): Action
    method hasMatchableFieldMapped (line 324) | public function hasMatchableFieldMapped(): bool
    method buildMatchWarningDescription (line 339) | private function buildMatchWarningDescription(): string
    method saveMappings (line 356) | private function saveMappings(): void
    method loadMappings (line 365) | private function loadMappings(): void
    method getImporter (line 373) | private function getImporter(): BaseImporter

FILE: packages/ImportWizard/src/Livewire/Steps/PreviewStep.php
  class PreviewStep (line 32) | final class PreviewStep extends Component implements HasActions, HasForms
    method mount (line 47) | public function mount(string $storeId, ImportEntityType $entityType): ...
    method setActiveTab (line 54) | public function setActiveTab(string $tab): void
    method createCount (line 60) | #[Computed]
    method updateCount (line 66) | #[Computed]
    method skipCount (line 72) | #[Computed]
    method errorCount (line 78) | #[Computed]
    method isImporting (line 87) | #[Computed]
    method progressPercent (line 98) | #[Computed]
    method processedCount (line 115) | #[Computed]
    method matchField (line 121) | #[Computed]
    method totalRowCount (line 134) | #[Computed]
    method columns (line 141) | #[Computed]
    method previewRows (line 148) | #[Computed]
    method relationshipTabs (line 166) | #[Computed]
    method relationshipSummary (line 192) | #[Computed]
    method relationshipStats (line 240) | #[Computed]
    method results (line 271) | #[Computed]
    method startImportAction (line 284) | public function startImportAction(): Action
    method downloadFailedRowsAction (line 298) | public function downloadFailedRowsAction(): Action
    method downloadFailedRows (line 308) | public function downloadFailedRows(): StreamedResponse
    method checkMatchResolution (line 340) | public function checkMatchResolution(): void
    method startImport (line 349) | public function startImport(): void
    method checkImportProgress (line 371) | public function checkImportProgress(): void
    method render (line 383) | public function render(): View
    method syncCompletionState (line 388) | private function syncCompletionState(): void
    method syncMatchResolutionState (line 396) | private function syncMatchResolutionState(): void
    method relationshipGroupByClause (line 421) | private function relationshipGroupByClause(): string
    method uniqueRelationshipSubquery (line 429) | private function uniqueRelationshipSubquery(): string

FILE: packages/ImportWizard/src/Livewire/Steps/ReviewStep.php
  class ReviewStep (line 33) | final class ReviewStep extends Component
    method connection (line 54) | private function connection(): Connection
    method selectedColumnJsonPath (line 59) | private function selectedColumnJsonPath(): string
    method validateValue (line 64) | private function validateValue(ColumnData $column, string $value, bool...
    method validateEntityLinkValue (line 79) | private function validateEntityLinkValue(ColumnData $column, string $v...
    method updateValidationForRawValue (line 86) | private function updateValidationForRawValue(string $jsonPath, string ...
    method validateColumnAsync (line 105) | private function validateColumnAsync(ColumnData $column): string
    method clearRelationshipsForReentry (line 116) | private function clearRelationshipsForReentry(): void
    method dispatchMatchResolution (line 121) | private function dispatchMatchResolution(): string
    method mount (line 134) | public function mount(): void
    method hydrate (line 160) | public function hydrate(): void
    method render (line 166) | public function render(): View
    method selectedColumnRows (line 172) | #[Computed]
    method filterCounts (line 186) | #[Computed]
    method selectColumn (line 195) | public function selectColumn(string $columnSource): void
    method choiceOptions (line 202) | #[Computed]
    method setFilter (line 212) | public function setFilter(string $filter): void
    method setSortField (line 218) | public function setSortField(string $field): void
    method setSortDirection (line 224) | public function setSortDirection(string $direction): void
    method clearFilters (line 230) | public function clearFilters(): void
    method updatedSearch (line 237) | public function updatedSearch(): void
    method setColumnFormat (line 242) | public function setColumnFormat(string $type, string $value): void
    method updateMappedValue (line 279) | public function updateMappedValue(string $rawValue, string $newValue):...
    method undoCorrection (line 309) | public function undoCorrection(string $rawValue): void
    method skipValue (line 325) | public function skipValue(string $rawValue): void
    method unskipValue (line 342) | public function unskipValue(string $rawValue): void
    method checkProgress (line 355) | public function checkProgress(): void
    method isSelectedColumnValidating (line 377) | #[Computed]
    method isValidating (line 383) | #[Computed]
    method columnErrorStatuses (line 393) | #[Computed(persist: true, seconds: 60)]
    method continueToPreview (line 401) | public function continueToPreview(): void
    method currentMappingsHash (line 421) | private function currentMappingsHash(): string
    method validationCacheKey (line 428) | private function validationCacheKey(): string
    method cacheValidationState (line 433) | private function cacheValidationState(string $hash): void
    method filterRunningBatches (line 445) | private function filterRunningBatches(array $batchIds): array
    method cancelOldBatches (line 455) | private function cancelOldBatches(?array $cached): void

FILE: packages/ImportWizard/src/Livewire/Steps/UploadStep.php
  class UploadStep (line 23) | final class UploadStep extends Component implements HasForms
    method mount (line 48) | public function mount(ImportEntityType $entityType, ?string $storeId =...
    method getCurrentTeamId (line 70) | private function getCurrentTeamId(): ?string
    method render (line 77) | public function render(): View
    method updatedUploadedFile (line 82) | public function updatedUploadedFile(): void
    method validateFile (line 88) | private function validateFile(): void
    method continueToMapping (line 139) | public function continueToMapping(): void
    method processHeaders (line 227) | private function processHeaders(array $rawHeaders): ?array
    method normalizeRow (line 250) | private function normalizeRow(array $row): array
    method removeFile (line 258) | public function removeFile(): void
    method cleanupExisting (line 264) | private function cleanupExisting(): void
    method maxRows (line 277) | private function maxRows(): int
    method chunkSize (line 282) | private function chunkSize(): int

FILE: packages/ImportWizard/src/Models/FailedImportRow.php
  class FailedImportRow (line 20) | final class FailedImportRow extends Model
    method casts (line 33) | protected function casts(): array
    method import (line 41) | public function import(): BelongsTo
    method prunable (line 47) | public function prunable(): Builder

FILE: packages/ImportWizard/src/Models/Import.php
  class Import (line 39) | final class Import extends Model
    method casts (line 62) | protected function casts(): array
    method user (line 79) | public function user(): BelongsTo
    method team (line 85) | public function team(): BelongsTo
    method failedRows (line 91) | public function failedRows(): HasMany
    method completed (line 97) | #[Scope]
    method failed (line 104) | #[Scope]
    method forTeam (line 111) | #[Scope]
    method storagePath (line 117) | public function storagePath(): string
    method getImporter (line 122) | public function getImporter(): BaseImporter
    method columnMappings (line 130) | public function columnMappings(): Collection
    method setColumnMappings (line 151) | public function setColumnMappings(iterable $mappings): void
    method getColumnMapping (line 161) | public function getColumnMapping(string $source): ?ColumnData
    method updateColumnMapping (line 166) | public function updateColumnMapping(string $source, ColumnData $newMap...
    method transitionToImporting (line 174) | public function transitionToImporting(): bool

FILE: packages/ImportWizard/src/Rules/ImportChoiceRule.php
  class ImportChoiceRule (line 17) | final readonly class ImportChoiceRule implements ValidationRule
    method __construct (line 23) | public function __construct(
    method validate (line 35) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: packages/ImportWizard/src/Rules/ImportDateRule.php
  class ImportDateRule (line 20) | final readonly class ImportDateRule implements ValidationRule
    method __construct (line 22) | public function __construct(
    method validate (line 33) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: packages/ImportWizard/src/Rules/ImportNumberRule.php
  class ImportNumberRule (line 15) | final readonly class ImportNumberRule implements ValidationRule
    method __construct (line 17) | public function __construct(
    method validate (line 26) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: packages/ImportWizard/src/Store/ImportRow.php
  class ImportRow (line 46) | final class ImportRow extends Model
    method casts (line 75) | protected function casts(): array
    method withErrors (line 91) | #[Scope]
    method withCorrections (line 100) | #[Scope]
    method withSkipped (line 109) | #[Scope]
    method valid (line 118) | #[Scope]
    method toCreate (line 129) | #[Scope]
    method toUpdate (line 138) | #[Scope]
    method toSkip (line 147) | #[Scope]
    method uniqueValuesFor (line 156) | #[Scope]
    method searchValue (line 176) | #[Scope]
    method forFilter (line 186) | #[Scope]
    method countUniqueValuesByFilter (line 205) | public static function countUniqueValuesByFilter(Builder $query, strin...
    method getColumnErrorStatuses (line 242) | public static function getColumnErrorStatuses(Builder $query, array $c...
    method hasErrors (line 267) | public function hasErrors(): bool
    method hasCorrections (line 272) | public function hasCorrections(): bool
    method getFinalValue (line 277) | public function getFinalValue(string $column): mixed
    method isValueSkipped (line 294) | public function isValueSkipped(string $column): bool
    method hasValidationError (line 299) | public function hasValidationError(string $column): bool
    method getFinalData (line 305) | public function getFinalData(): array
    method isCreate (line 310) | public function isCreate(): bool
    method isUpdate (line 315) | public function isUpdate(): bool
    method isSkip (line 320) | public function isSkip(): bool

FILE: packages/ImportWizard/src/Store/ImportStore.php
  class ImportStore (line 16) | final class ImportStore
    method __construct (line 20) | public function __construct(
    method create (line 24) | public static function create(string $importId): self
    method load (line 35) | public static function load(string $importId): ?self
    method id (line 52) | public function id(): string
    method path (line 57) | public function path(): string
    method sqlitePath (line 62) | public function sqlitePath(): string
    method connectionName (line 67) | public function connectionName(): string
    method connection (line 72) | public function connection(): Connection
    method query (line 78) | public function query(): EloquentBuilder
    method ensureProcessedColumn (line 85) | public function ensureProcessedColumn(): void
    method bulkUpdateMatches (line 101) | public function bulkUpdateMatches(string $jsonPath, array $resolvedMap...
    method destroy (line 144) | public function destroy(): void
    method createConnection (line 150) | private function createConnection(): Connection
    method createTableSafely (line 164) | private function createTableSafely(): void

FILE: packages/ImportWizard/src/Support/DataTypeInferencer.php
  class DataTypeInferencer (line 20) | final class DataTypeInferencer
    method __construct (line 30) | public function __construct(
    method infer (line 40) | public function infer(array $values): InferenceResult
    method initialize (line 89) | private function initialize(): void
    method extractValidationKey (line 127) | private function extractValidationKey(string $rule): ?string
    method detectType (line 144) | private function detectType(string $value): string
    method passesValidation (line 174) | private function passesValidation(string $value, string $validationKey...
    method isCurrency (line 190) | private function isCurrency(string $value): bool
    method isNumber (line 195) | private function isNumber(string $value): bool
    method getSuggestedFieldsForType (line 207) | private function getSuggestedFieldsForType(string $fieldTypeKey): array

FILE: packages/ImportWizard/src/Support/EntityLinkResolver.php
  class EntityLinkResolver (line 14) | final class EntityLinkResolver
    method __construct (line 21) | public function __construct(
    method resolve (line 25) | public function resolve(EntityLink $link, MatchableField $matcher, mix...
    method resolveMany (line 48) | public function resolveMany(EntityLink $link, MatchableField $matcher,...
    method batchResolve (line 81) | public function batchResolve(EntityLink $link, MatchableField $matcher...
    method normalizeUniqueValues (line 116) | private function normalizeUniqueValues(array $values): array
    method isCustomField (line 126) | private function isCustomField(string $field): bool
    method getCustomFieldCode (line 131) | private function getCustomFieldCode(string $field): string
    method resolveViaColumn (line 140) | private function resolveViaColumn(EntityLink $link, string $field, arr...
    method resolveViaTeamMember (line 155) | private function resolveViaTeamMember(string $field, array $uniqueValu...
    method resolveViaCustomField (line 171) | private function resolveViaCustomField(EntityLink $link, string $field...
    method resolveViaJsonColumn (line 206) | private function resolveViaJsonColumn(string $entityType, int|string $...
    method preloadCache (line 275) | public function preloadCache(EntityLink $link, MatchableField $matcher...
    method getCachedId (line 286) | public function getCachedId(EntityLink $link, MatchableField $matcher,...
    method clearCache (line 294) | public function clearCache(): void
    method getCacheKey (line 299) | private function getCacheKey(EntityLink $link, MatchableField $matcher...
    method normalizeValue (line 304) | private function normalizeValue(mixed $value): ?string
    method normalizeForComparison (line 315) | private function normalizeForComparison(string $value): string

FILE: packages/ImportWizard/src/Support/EntityLinkStorage/CustomFieldValueStorage.php
  class CustomFieldValueStorage (line 16) | final class CustomFieldValueStorage implements EntityLinkStorageInterface
    method store (line 18) | public function store(Model $record, EntityLink $link, array $resolved...
    method prepareData (line 23) | public function prepareData(array $data, EntityLink $link, array $reso...

FILE: packages/ImportWizard/src/Support/EntityLinkStorage/EntityLinkStorageInterface.php
  type EntityLinkStorageInterface (line 16) | interface EntityLinkStorageInterface
    method store (line 28) | public function store(Model $record, EntityLink $link, array $resolved...
    method prepareData (line 40) | public function prepareData(array $data, EntityLink $link, array $reso...

FILE: packages/ImportWizard/src/Support/EntityLinkStorage/ForeignKeyStorage.php
  class ForeignKeyStorage (line 15) | final class ForeignKeyStorage implements EntityLinkStorageInterface
    method store (line 17) | public function store(Model $record, EntityLink $link, array $resolved...
    method prepareData (line 22) | public function prepareData(array $data, EntityLink $link, array $reso...

FILE: packages/ImportWizard/src/Support/EntityLinkStorage/MorphToManyStorage.php
  class MorphToManyStorage (line 15) | final class MorphToManyStorage implements EntityLinkStorageInterface
    method store (line 17) | public function store(Model $record, EntityLink $link, array $resolved...
    method prepareData (line 33) | public function prepareData(array $data, EntityLink $link, array $reso...

FILE: packages/ImportWizard/src/Support/EntityLinkValidator.php
  class EntityLinkValidator (line 16) | final class EntityLinkValidator
    method __construct (line 26) | public function __construct(private readonly string $teamId)
    method validate (line 31) | public function validate(EntityLink $link, MatchableField $matcher, mi...
    method batchValidate (line 54) | public function batchValidate(EntityLink $link, MatchableField $matche...
    method validateFromColumn (line 104) | public function validateFromColumn(ColumnData $column, BaseImporter $i...
    method batchValidateFromColumn (line 117) | public function batchValidateFromColumn(ColumnData $column, BaseImport...
    method preloadCache (line 127) | public function preloadCache(EntityLink $link, MatchableField $matcher...
    method getResolvedId (line 132) | public function getResolvedId(EntityLink $link, MatchableField $matche...
    method getResolver (line 144) | public function getResolver(): EntityLinkResolver
    method getLastFormatErrors (line 150) | public function getLastFormatErrors(): array
    method getMatchFieldFormatRules (line 158) | private function getMatchFieldFormatRules(EntityLink $link, MatchableF...
    method validateFormat (line 195) | private function validateFormat(string $value, MatchableField $matcher...
    method buildErrorMessage (line 216) | private function buildErrorMessage(EntityLink $link, MatchableField $m...

FILE: packages/ImportWizard/src/Support/MatchResolver.php
  class MatchResolver (line 19) | final readonly class MatchResolver
    method __construct (line 21) | public function __construct(
    method resolve (line 27) | public function resolve(): void
    method resetPreviousResolutions (line 45) | private function resetPreviousResolutions(): void
    method markRemainingAs (line 54) | private function markRemainingAs(RowMatchAction $action): void
    method resolveWithLookup (line 64) | private function resolveWithLookup(MatchableField $matchField, Collect...
    method findSourceColumn (line 89) | private function findSourceColumn(MatchableField $matchField, Collecti...
    method extractUniqueValues (line 97) | private function extractUniqueValues(string $jsonPath): array
    method resolveMatchIds (line 112) | private function resolveMatchIds(MatchableField $matchField, array $un...
    method resolveMultiValueField (line 131) | private function resolveMultiValueField(

FILE: packages/ImportWizard/src/Support/Validation/ColumnValidator.php
  class ColumnValidator (line 14) | final class ColumnValidator
    method validate (line 16) | public function validate(ColumnData $column, string $value): ?Validati...
    method validateDate (line 31) | private function validateDate(ColumnData $column, string $value): ?Val...
    method validateNumber (line 42) | private function validateNumber(ColumnData $column, string $value): ?V...
    method validateSingleChoice (line 53) | private function validateSingleChoice(ColumnData $column, string $valu...
    method validateMultiChoicePredefined (line 65) | private function validateMultiChoicePredefined(ColumnData $column, str...
    method validateMultiChoiceArbitrary (line 81) | private function validateMultiChoiceArbitrary(ColumnData $column, stri...
    method validateBoolean (line 101) | private function validateBoolean(string $value): ?ValidationError
    method validateText (line 112) | private function validateText(ColumnData $column, string $value): ?Val...
    method parseCommaSeparated (line 130) | private function parseCommaSeparated(string $value): Collection
    method getChoiceValues (line 140) | private function getChoiceValues(ColumnData $column): array
    method lowercaseValues (line 151) | private function lowercaseValues(array $values): array
    method formatInvalidChoiceMessage (line 157) | private function formatInvalidChoiceMessage(array $validValues): string
    method getPreviewRules (line 166) | private function getPreviewRules(ColumnData $column): array
    method runValidator (line 175) | private function runValidator(string $value, array $rules): ?string

FILE: packages/ImportWizard/src/Support/Validation/ValidationError.php
  class ValidationError (line 13) | final readonly class ValidationError
    method __construct (line 19) | private function __construct(
    method message (line 27) | public static function message(string $message): self
    method itemErrors (line 37) | public static function itemErrors(array $errors): self
    method fromStorageFormat (line 47) | public static function fromStorageFormat(?string $stored): ?self
    method toStorageFormat (line 67) | public function toStorageFormat(): string
    method hasItemErrors (line 76) | public function hasItemErrors(): bool
    method getMessage (line 81) | public function getMessage(): ?string
    method getItemErrors (line 89) | public function getItemErrors(): array

FILE: packages/OnboardSeed/src/Contracts/ModelSeederInterface.php
  type ModelSeederInterface (line 11) | interface ModelSeederInterface
    method seed (line 13) | public function seed(Team $team, Authenticatable $user): void;
    method customFields (line 20) | public function customFields(): Collection;
    method initialize (line 27) | public function initialize(): self;

FILE: packages/OnboardSeed/src/ModelSeeders/CompanySeeder.php
  class CompanySeeder (line 13) | final class CompanySeeder extends BaseModelSeeder
    method createEntitiesFromFixtures (line 25) | protected function createEntitiesFromFixtures(Team $team, Authenticata...
    method createCompanyFromFixture (line 39) | private function createCompanyFromFixture(Team $team, Authenticatable ...

FILE: packages/OnboardSeed/src/ModelSeeders/NoteSeeder.php
  class NoteSeeder (line 17) | final class NoteSeeder extends BaseModelSeeder
    method createEntitiesFromFixtures (line 38) | protected function createEntitiesFromFixtures(Team $team, Authenticata...
    method getPluralEntityType (line 65) | private function getPluralEntityType(string $singularType): string
    method createNoteFromFixture (line 71) | private function createNoteFromFixture(

FILE: packages/OnboardSeed/src/ModelSeeders/OpportunitySeeder.php
  class OpportunitySeeder (line 16) | final class OpportunitySeeder extends BaseModelSeeder
    method createEntitiesFromFixtures (line 28) | protected function createEntitiesFromFixtures(Team $team, Authenticata...
    method createOpportunityFromFixture (line 58) | private function createOpportunityFromFixture(

FILE: packages/OnboardSeed/src/ModelSeeders/PeopleSeeder.php
  class PeopleSeeder (line 16) | final class PeopleSeeder extends BaseModelSeeder
    method createEntitiesFromFixtures (line 29) | protected function createEntitiesFromFixtures(Team $team, Authenticata...
    method createPersonFromFixture (line 55) | private function createPersonFromFixture(Company $company, Team $team,...

FILE: packages/OnboardSeed/src/ModelSeeders/TaskSeeder.php
  class TaskSeeder (line 18) | final class TaskSeeder extends BaseModelSeeder
    method createEntitiesFromFixtures (line 31) | protected function createEntitiesFromFixtures(Team $team, Authenticata...
    method assignPeopleToTask (line 49) | private function assignPeopleToTask(Task $task, array $peopleKeys): void
    method createTaskFromFixture (line 73) | private function createTaskFromFixture(
    method formatDate (line 108) | private function formatDate(mixed $dateValue): string

FILE: packages/OnboardSeed/src/OnboardSeedManager.php
  class OnboardSeedManager (line 20) | final class OnboardSeedManager
    method generateFor (line 34) | public function generateFor(Authenticatable $user, ?Team $team = null)...
    method initializeSeeders (line 60) | private function initializeSeeders(): void

FILE: packages/OnboardSeed/src/OnboardSeeder.php
  class OnboardSeeder (line 11) | final class OnboardSeeder extends Seeder
    method __construct (line 13) | public function __construct(private readonly OnboardSeedManager $manag...
    method run (line 15) | public function run(Authenticatable $user, ?Team $team = null): void

FILE: packages/OnboardSeed/src/Support/BaseModelSeeder.php
  class BaseModelSeeder (line 20) | abstract class BaseModelSeeder implements ModelSeederInterface
    method initialize (line 38) | public function initialize(): self
    method setTeamId (line 48) | protected function setTeamId(string $teamId): void
    method customFields (line 54) | public function customFields(): Collection
    method prepareForSeed (line 69) | protected function prepareForSeed(Team $team): void
    method seed (line 76) | public function seed(Team $team, Authenticatable $user): void
    method createEntitiesFromFixtures (line 85) | abstract protected function createEntitiesFromFixtures(Team $team, Aut...
    method applyCustomFields (line 88) | protected function applyCustomFields(HasCustomFields&Model $model, arr...
    method getBulkWriter (line 107) | protected function getBulkWriter(): BulkCustomFieldValueWriter
    method flushCustomFieldValues (line 112) | protected function flushCustomFieldValues(): int
    method getOptionId (line 117) | protected function getOptionId(string $fieldCode, string $optionLabel)...
    method getGlobalAttributes (line 137) | protected function getGlobalAttributes(): array
    method loadEntityFixtures (line 145) | protected function loadEntityFixtures(): array
    method evaluateTemplateExpression (line 150) | protected function evaluateTemplateExpression(string $template): mixed
    method processCustomFieldValues (line 189) | protected function processCustomFieldValues(array $customFields, array...
    method registerEntityFromFixture (line 218) | protected function registerEntityFromFixture(string $key, array $attri...

FILE: packages/OnboardSeed/src/Support/BulkCustomFieldValueWriter.php
  class BulkCustomFieldValueWriter (line 13) | final class BulkCustomFieldValueWriter
    method queue (line 18) | public function queue(
    method flush (line 42) | public function flush(): int
    method pending (line 71) | public function pending(): int

FILE: packages/OnboardSeed/src/Support/FixtureLoader.php
  class FixtureLoader (line 11) | final class FixtureLoader
    method setBasePath (line 21) | public static function setBasePath(string $path): void
    method getBasePath (line 29) | public static function getBasePath(): string
    method load (line 46) | public static function load(string $type): array

FILE: packages/OnboardSeed/src/Support/FixtureRegistry.php
  class FixtureRegistry (line 9) | final class FixtureRegistry
    method register (line 25) | public static function register(string $type, string $key, Model $enti...
    method get (line 41) | public static function get(string $type, string $key): ?Model
    method clear (line 46) | public static function clear(): void

FILE: packages/SystemAdmin/src/Enums/SystemAdministratorRole.php
  method getLabel (line 11) | public function getLabel(): string

FILE: packages/SystemAdmin/src/Filament/Exports/CompanyExporter.php
  class CompanyExporter (line 15) | final class CompanyExporter extends Exporter
    method getColumns (line 23) | public static function getColumns(): array
    method getCompletedNotificationBody (line 42) | public static function getCompletedNotificationBody(Export $export): s...

FILE: packages/SystemAdmin/src/Filament/Pages/Dashboard.php
  class Dashboard (line 18) | final class Dashboard extends BaseDashboard
    method getWidgets (line 35) | public function getWidgets(): array
    method getColumns (line 45) | public function getColumns(): array
    method getHeaderActions (line 53) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Pages/EngagementDashboard.php
  class EngagementDashboard (line 15) | final class EngagementDashboard extends BaseDashboard
    method getWidgets (line 36) | public function getWidgets(): array
    method getColumns (line 44) | public function getColumns(): array
    method getHeaderActions (line 52) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/CompanyResource.php
  class CompanyResource (line 27) | final class CompanyResource extends Resource
    method getNavigationBadge (line 43) | public static function getNavigationBadge(): ?string
    method form (line 50) | #[Override]
    method table (line 71) | #[Override]
    method getRelations (line 129) | #[Override]
    method getPages (line 135) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/CompanyResource/Pages/CreateCompany.php
  class CreateCompany (line 10) | final class CreateCompany extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/CompanyResource/Pages/EditCompany.php
  class EditCompany (line 13) | final class EditCompany extends EditRecord
    method getHeaderActions (line 17) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/CompanyResource/Pages/ListCompanies.php
  class ListCompanies (line 12) | final class ListCompanies extends ListRecords
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/CompanyResource/Pages/ViewCompany.php
  class ViewCompany (line 12) | final class ViewCompany extends ViewRecord
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/ImportResource.php
  class ImportResource (line 23) | final class ImportResource extends Resource
    method getNavigationBadge (line 39) | public static function getNavigationBadge(): ?string
    method infolist (line 46) | #[Override]
    method table (line 74) | #[Override]
    method getRelations (line 132) | #[Override]
    method getPages (line 140) | #[Override]
    method statusColor (line 149) | private static function statusColor(ImportStatus $state): string

FILE: packages/SystemAdmin/src/Filament/Resources/ImportResource/Pages/ListImports.php
  class ListImports (line 10) | final class ListImports extends ListRecords

FILE: packages/SystemAdmin/src/Filament/Resources/ImportResource/Pages/ViewImport.php
  class ViewImport (line 10) | final class ViewImport extends ViewRecord

FILE: packages/SystemAdmin/src/Filament/Resources/ImportResource/RelationManagers/FailedRowsRelationManager.php
  class FailedRowsRelationManager (line 13) | final class FailedRowsRelationManager extends RelationManager
    method getBadge (line 19) | public static function getBadge(Model $ownerRecord, string $pageClass)...
    method table (line 26) | public function table(Table $table): Table

FILE: packages/SystemAdmin/src/Filament/Resources/NoteResource.php
  class NoteResource (line 27) | final class NoteResource extends Resource
    method getNavigationBadge (line 43) | public static function getNavigationBadge(): ?string
    method form (line 50) | #[Override]
    method table (line 67) | #[Override]
    method getRelations (line 122) | #[Override]
    method getPages (line 128) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/NoteResource/Pages/CreateNote.php
  class CreateNote (line 10) | final class CreateNote extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/NoteResource/Pages/EditNote.php
  class EditNote (line 13) | final class EditNote extends EditRecord
    method getHeaderActions (line 17) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/NoteResource/Pages/ListNotes.php
  class ListNotes (line 12) | final class ListNotes extends ListRecords
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/NoteResource/Pages/ViewNote.php
  class ViewNote (line 12) | final class ViewNote extends ViewRecord
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/OpportunityResource.php
  class OpportunityResource (line 27) | final class OpportunityResource extends Resource
    method getNavigationBadge (line 43) | public static function getNavigationBadge(): ?string
    method form (line 50) | #[Override]
    method table (line 74) | #[Override]
    method getRelations (line 139) | #[Override]
    method getPages (line 145) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/OpportunityResource/Pages/CreateOpportunity.php
  class CreateOpportunity (line 10) | final class CreateOpportunity extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/OpportunityResource/Pages/EditOpportunity.php
  class EditOpportunity (line 13) | final class EditOpportunity extends EditRecord
    method getHeaderActions (line 17) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/OpportunityResource/Pages/ListOpportunities.php
  class ListOpportunities (line 12) | final class ListOpportunities extends ListRecords
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/OpportunityResource/Pages/ViewOpportunity.php
  class ViewOpportunity (line 12) | final class ViewOpportunity extends ViewRecord
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/PeopleResource.php
  class PeopleResource (line 27) | final class PeopleResource extends Resource
    method getNavigationBadge (line 43) | public static function getNavigationBadge(): ?string
    method form (line 50) | #[Override]
    method table (line 71) | #[Override]
    method getRelations (line 133) | #[Override]
    method getPages (line 139) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/PeopleResource/Pages/CreatePeople.php
  class CreatePeople (line 10) | final class CreatePeople extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/PeopleResource/Pages/EditPeople.php
  class EditPeople (line 13) | final class EditPeople extends EditRecord
    method getHeaderActions (line 17) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/PeopleResource/Pages/ListPeople.php
  class ListPeople (line 12) | final class ListPeople extends ListRecords
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/PeopleResource/Pages/ViewPeople.php
  class ViewPeople (line 11) | final class ViewPeople extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Pages/CreateSystemAdministrator.php
  class CreateSystemAdministrator (line 11) | final class CreateSystemAdministrator extends CreateRecord
    method getFormActions (line 15) | protected function getFormActions(): array
    method getCancelAction (line 23) | private function getCancelAction(): Action

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Pages/EditSystemAdministrator.php
  class EditSystemAdministrator (line 12) | final class EditSystemAdministrator extends EditRecord
    method getHeaderActions (line 16) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Pages/ListSystemAdministrators.php
  class ListSystemAdministrators (line 11) | final class ListSystemAdministrators extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Pages/ViewSystemAdministrator.php
  class ViewSystemAdministrator (line 11) | final class ViewSystemAdministrator extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Schemas/SystemAdministratorForm.php
  class SystemAdministratorForm (line 16) | final class SystemAdministratorForm
    method configure (line 18) | public static function configure(Schema $schema): Schema

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Schemas/SystemAdministratorInfolist.php
  class SystemAdministratorInfolist (line 10) | final class SystemAdministratorInfolist
    method configure (line 12) | public static function configure(Schema $schema): Schema

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/SystemAdministratorResource.php
  class SystemAdministratorResource (line 23) | final class SystemAdministratorResource extends Resource
    method form (line 33) | public static function form(Schema $schema): Schema
    method infolist (line 38) | public static function infolist(Schema $schema): Schema
    method table (line 43) | public static function table(Table $table): Table
    method getRelations (line 48) | public static function getRelations(): array
    method getPages (line 55) | public static function getPages(): array
    method getEloquentQuery (line 65) | public static function getEloquentQuery(): Builder

FILE: packages/SystemAdmin/src/Filament/Resources/SystemAdministrators/Tables/SystemAdministratorsTable.php
  class SystemAdministratorsTable (line 18) | final class SystemAdministratorsTable
    method configure (line 20) | public static function configure(Table $table): Table

FILE: packages/SystemAdmin/src/Filament/Resources/TaskResource.php
  class TaskResource (line 27) | final class TaskResource extends Resource
    method getNavigationBadge (line 43) | public static function getNavigationBadge(): ?string
    method form (line 50) | #[Override]
    method table (line 68) | #[Override]
    method getRelations (line 122) | #[Override]
    method getPages (line 128) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TaskResource/Pages/CreateTask.php
  class CreateTask (line 10) | final class CreateTask extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/TaskResource/Pages/EditTask.php
  class EditTask (line 13) | final class EditTask extends EditRecord
    method getHeaderActions (line 17) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TaskResource/Pages/ListTasks.php
  class ListTasks (line 12) | final class ListTasks extends ListRecords
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TaskResource/Pages/ViewTask.php
  class ViewTask (line 12) | final class ViewTask extends ViewRecord
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource.php
  class TeamResource (line 37) | final class TeamResource extends Resource
    method getNavigationBadge (line 53) | public static function getNavigationBadge(): ?string
    method form (line 60) | #[Override]
    method infolist (line 83) | #[Override]
    method table (line 104) | #[Override]
    method getRelations (line 146) | #[Override]
    method getPages (line 159) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/Pages/CreateTeam.php
  class CreateTeam (line 10) | final class CreateTeam extends CreateRecord

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/Pages/EditTeam.php
  class EditTeam (line 11) | final class EditTeam extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/Pages/ListTeams.php
  class ListTeams (line 11) | final class ListTeams extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/Pages/ViewTeam.php
  class ViewTeam (line 12) | final class ViewTeam extends ViewRecord
    method getHeaderActions (line 16) | #[Override]

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/RelationManagers/CompaniesRelationManager.php
  class CompaniesRelationManager (line 12) | final class CompaniesRelationManager extends RelationManager
    method getBadge (line 18) | public static function getBadge(Model $ownerRecord, string $pageClass)...
    method table (line 25) | public function table(Table $table): Table

FILE: packages/SystemAdmin/src/Filament/Resources/TeamResource/RelationManagers/MembersRelationManager.php
  class MembersRelationManager (line 12) | final class MembersRelationM
Condensed preview — 911 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,895K chars).
[
  {
    "path": ".dockerignore",
    "chars": 967,
    "preview": "# Git\n.git\n.gitignore\n.gitattributes\n.githooks\n\n# IDE\n.idea\n.vscode\n*.swp\n*.swo\n\n# Dependencies (will be installed durin"
  },
  {
    "path": ".editorconfig",
    "chars": 261,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".gitattributes",
    "chars": 186,
    "preview": "* text=auto eol=lf\n\n*.blade.php diff=html\n*.css diff=css\n*.html diff=html\n*.md diff=markdown\n*.php diff=php\n\n/.github ex"
  },
  {
    "path": ".githooks/pre-commit",
    "chars": 38,
    "preview": "#!/bin/sh\ncomposer lint\ncomposer test\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1-bug_report.yml",
    "chars": 2648,
    "preview": "name: Bug report\ndescription: Report a problem you're experiencing with Relaticle\nlabels: [\"bug\", \"unconfirmed\"]\nproject"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 490,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Feature request or idea\n    url: https://github.com/Relaticle/relat"
  },
  {
    "path": ".github/copilot-instructions.md",
    "chars": 6337,
    "preview": "# Relaticle Code Review Guidelines\n\n## Repository Context\n\nMulti-tenant SaaS CRM with paying customers. Tenant isolation"
  },
  {
    "path": ".github/workflows/docker-publish.yml",
    "chars": 6114,
    "preview": "name: Build and Push Docker Image\n\non:\n  push:\n    branches: [main]\n    tags: ['v*']\n  pull_request:\n    branches: [main"
  },
  {
    "path": ".github/workflows/filament-view-monitor-simple.yml",
    "chars": 4541,
    "preview": "name: Monitor Filament View Updates (Simple)\n\non:\n  schedule:\n    # Run daily at 9 AM UTC\n    - cron: '0 9 * * *'\n  work"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 5863,
    "preview": "name: Tests\n\non: [push]\n\njobs:\n  lint-and-static-analysis:\n    runs-on: ubuntu-latest\n    name: Code Quality Checks\n\n   "
  },
  {
    "path": ".gitignore",
    "chars": 677,
    "preview": ".DS_Store\n.superpowers\n/.phpunit.cache\n.scribe\n/node_modules\n/public/build\n/public/hot\n/public/storage\n/public/sitemap.x"
  },
  {
    "path": "CLAUDE.md",
    "chars": 28619,
    "preview": "<laravel-boost-guidelines>\n=== .ai/core rules ===\n\n# Project\n\nThis is production code for a commercial SaaS product with"
  },
  {
    "path": "Dockerfile",
    "chars": 2668,
    "preview": "# syntax=docker/dockerfile:1\n\n###########################################\n# Stage 1: Composer dependencies\n#############"
  },
  {
    "path": "LICENSE",
    "chars": 34523,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "README.md",
    "chars": 4275,
    "preview": "<p align=\"center\">\n  <a href=\"https://relaticle.com\">\n    <img src=\"https://relaticle.com/brand/logomark.svg\" width=\"100"
  },
  {
    "path": "TODOS.md",
    "chars": 2013,
    "preview": "# TODOs\n\nDeferred work from plan reviews. Each item includes context and reasoning so it can be picked up without the or"
  },
  {
    "path": "app/Actions/Company/CreateCompany.php",
    "chars": 772,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Company;\n\nuse App\\Enums\\CreationSource;\nuse App\\Models\\Company;\nu"
  },
  {
    "path": "app/Actions/Company/DeleteCompany.php",
    "chars": 314,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Company;\n\nuse App\\Models\\Company;\nuse App\\Models\\User;\n\nfinal rea"
  },
  {
    "path": "app/Actions/Company/ListCompanies.php",
    "chars": 2203,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Company;\n\nuse App\\Mcp\\Filters\\CustomFieldFilter;\nuse App\\Mcp\\Sche"
  },
  {
    "path": "app/Actions/Company/UpdateCompany.php",
    "chars": 824,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Company;\n\nuse App\\Models\\Company;\nuse App\\Models\\User;\nuse App\\Su"
  },
  {
    "path": "app/Actions/Fortify/CreateNewSocialUser.php",
    "chars": 1123,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Contracts\\User\\CreatesNewSocialUsers;\nuse App\\M"
  },
  {
    "path": "app/Actions/Fortify/PasswordValidationRules.php",
    "chars": 450,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse Illuminate\\Contracts\\Validation\\Rule;\nuse Illuminat"
  },
  {
    "path": "app/Actions/Fortify/ResetUserPassword.php",
    "chars": 734,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Has"
  },
  {
    "path": "app/Actions/Fortify/UpdateUserPassword.php",
    "chars": 965,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Has"
  },
  {
    "path": "app/Actions/Fortify/UpdateUserProfileInformation.php",
    "chars": 1816,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Val"
  },
  {
    "path": "app/Actions/Jetstream/AddTeamMember.php",
    "chars": 2362,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse Closure"
  },
  {
    "path": "app/Actions/Jetstream/CreateTeam.php",
    "chars": 1254,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse App\\Rul"
  },
  {
    "path": "app/Actions/Jetstream/DeleteTeam.php",
    "chars": 322,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse Laravel\\Jetstream\\Contracts\\"
  },
  {
    "path": "app/Actions/Jetstream/DeleteUser.php",
    "chars": 1126,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse Illumin"
  },
  {
    "path": "app/Actions/Jetstream/InviteTeamMember.php",
    "chars": 2917,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse Closure"
  },
  {
    "path": "app/Actions/Jetstream/RemoveTeamMember.php",
    "chars": 1588,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse Illumin"
  },
  {
    "path": "app/Actions/Jetstream/UpdateTeamName.php",
    "chars": 982,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Team;\nuse App\\Models\\User;\nuse App\\Rul"
  },
  {
    "path": "app/Actions/Note/CreateNote.php",
    "chars": 1376,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Note;\n\nuse App\\Enums\\CreationSource;\nuse App\\Models\\Note;\nuse App"
  },
  {
    "path": "app/Actions/Note/DeleteNote.php",
    "chars": 293,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Note;\n\nuse App\\Models\\Note;\nuse App\\Models\\User;\n\nfinal readonly "
  },
  {
    "path": "app/Actions/Note/ListNotes.php",
    "chars": 2241,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Note;\n\nuse App\\Mcp\\Filters\\CustomFieldFilter;\nuse App\\Mcp\\Schema\\"
  },
  {
    "path": "app/Actions/Note/UpdateNote.php",
    "chars": 1212,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Note;\n\nuse App\\Models\\Note;\nuse App\\Models\\User;\nuse App\\Support\\"
  },
  {
    "path": "app/Actions/Opportunity/CreateOpportunity.php",
    "chars": 836,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Opportunity;\n\nuse App\\Enums\\CreationSource;\nuse App\\Models\\Opport"
  },
  {
    "path": "app/Actions/Opportunity/DeleteOpportunity.php",
    "chars": 342,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Opportunity;\n\nuse App\\Models\\Opportunity;\nuse App\\Models\\User;\n\nf"
  },
  {
    "path": "app/Actions/Opportunity/ListOpportunities.php",
    "chars": 2188,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Opportunity;\n\nuse App\\Mcp\\Filters\\CustomFieldFilter;\nuse App\\Mcp\\"
  },
  {
    "path": "app/Actions/Opportunity/UpdateOpportunity.php",
    "chars": 900,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Opportunity;\n\nuse App\\Models\\Opportunity;\nuse App\\Models\\User;\nus"
  },
  {
    "path": "app/Actions/People/CreatePeople.php",
    "chars": 777,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\People;\n\nuse App\\Enums\\CreationSource;\nuse App\\Models\\People;\nuse"
  },
  {
    "path": "app/Actions/People/DeletePeople.php",
    "chars": 307,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\People;\n\nuse App\\Models\\People;\nuse App\\Models\\User;\n\nfinal reado"
  },
  {
    "path": "app/Actions/People/ListPeople.php",
    "chars": 2064,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\People;\n\nuse App\\Mcp\\Filters\\CustomFieldFilter;\nuse App\\Mcp\\Schem"
  },
  {
    "path": "app/Actions/People/UpdatePeople.php",
    "chars": 826,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\People;\n\nuse App\\Models\\People;\nuse App\\Models\\User;\nuse App\\Supp"
  },
  {
    "path": "app/Actions/Task/CreateTask.php",
    "chars": 1704,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Task;\n\nuse App\\Enums\\CreationSource;\nuse App\\Models\\Task;\nuse App"
  },
  {
    "path": "app/Actions/Task/DeleteTask.php",
    "chars": 293,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Task;\n\nuse App\\Models\\Task;\nuse App\\Models\\User;\n\nfinal readonly "
  },
  {
    "path": "app/Actions/Task/ListTasks.php",
    "chars": 2775,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Task;\n\nuse App\\Mcp\\Filters\\CustomFieldFilter;\nuse App\\Mcp\\Schema\\"
  },
  {
    "path": "app/Actions/Task/NotifyTaskAssignees.php",
    "chars": 1921,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Task;\n\nuse App\\Filament\\Resources\\TaskResource\\Pages\\ManageTasks;"
  },
  {
    "path": "app/Actions/Task/UpdateTask.php",
    "chars": 1653,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Task;\n\nuse App\\Models\\Task;\nuse App\\Models\\User;\nuse App\\Support\\"
  },
  {
    "path": "app/Concerns/DetectsTeamInvitation.php",
    "chars": 1671,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Concerns;\n\nuse App\\Models\\TeamInvitation;\nuse Illuminate\\Contracts\\Suppor"
  },
  {
    "path": "app/Console/Commands/BackfillCustomFieldColorsCommand.php",
    "chars": 5436,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands;\n\nuse App\\Enums\\CustomFields\\OpportunityField as Opportu"
  },
  {
    "path": "app/Console/Commands/CleanupExpiredInvitationsCommand.php",
    "chars": 1206,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands;\n\nuse App\\Models\\TeamInvitation;\nuse Illuminate\\Console\\"
  },
  {
    "path": "app/Console/Commands/CreateSystemAdminCommand.php",
    "chars": 6043,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\nuse Relaticle\\SystemAd"
  },
  {
    "path": "app/Console/Commands/GenerateSitemapCommand.php",
    "chars": 681,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\nuse Spatie\\Sitemap\\Sit"
  },
  {
    "path": "app/Console/Commands/InstallCommand.php",
    "chars": 14702,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support"
  },
  {
    "path": "app/Contracts/User/CreatesNewSocialUsers.php",
    "chars": 271,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Contracts\\User;\n\nuse App\\Models\\User;\n\ninterface CreatesNewSocialUsers\n{\n"
  },
  {
    "path": "app/Data/SubscriberData.php",
    "chars": 396,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Data;\n\nuse Spatie\\LaravelData\\Data;\n\nfinal class SubscriberData extends D"
  },
  {
    "path": "app/Enums/CreationSource.php",
    "chars": 1960,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Filament\\Support\\Contracts\\HasColor;\nuse Filament\\Support\\Con"
  },
  {
    "path": "app/Enums/CustomFieldType.php",
    "chars": 981,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\n/**\n * ABOUTME: Maps to the field types available in the relaticl"
  },
  {
    "path": "app/Enums/CustomFields/CompanyField.php",
    "chars": 1981,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse App\\Enums\\CustomFieldType;\n\nenum CompanyField: s"
  },
  {
    "path": "app/Enums/CustomFields/CustomFieldTrait.php",
    "chars": 4430,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse Illuminate\\Support\\Str;\nuse Relaticle\\CustomFiel"
  },
  {
    "path": "app/Enums/CustomFields/NoteField.php",
    "chars": 646,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse App\\Enums\\CustomFieldType;\n\n/**\n * Note custom f"
  },
  {
    "path": "app/Enums/CustomFields/OpportunityField.php",
    "chars": 3041,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse App\\Enums\\CustomFieldType;\n\nenum OpportunityFiel"
  },
  {
    "path": "app/Enums/CustomFields/PeopleField.php",
    "chars": 1631,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse App\\Enums\\CustomFieldType;\n\n/**\n * People custom"
  },
  {
    "path": "app/Enums/CustomFields/TaskField.php",
    "chars": 4614,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums\\CustomFields;\n\nuse App\\Enums\\CustomFieldType;\nuse Relaticle\\CustomF"
  },
  {
    "path": "app/Enums/SocialiteProvider.php",
    "chars": 146,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nenum SocialiteProvider: string\n{\n    case GOOGLE = 'google';\n    "
  },
  {
    "path": "app/Enums/SubscriberTagEnum.php",
    "chars": 122,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nenum SubscriberTagEnum: string\n{\n    case VERIFIED = 'verified';\n"
  },
  {
    "path": "app/Filament/Actions/GenerateRecordSummaryAction.php",
    "chars": 3160,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Actions;\n\nuse App\\Models\\AiSummary;\nuse App\\Services\\AI\\RecordSu"
  },
  {
    "path": "app/Filament/Components/Infolists/AvatarName.php",
    "chars": 2557,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Components\\Infolists;\n\nuse Filament\\Infolists\\Components\\Entry;\n"
  },
  {
    "path": "app/Filament/Exports/BaseExporter.php",
    "chars": 1473,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\Team;\nuse Filament\\Actions\\Exports\\Expo"
  },
  {
    "path": "app/Filament/Exports/CompanyExporter.php",
    "chars": 2419,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\Company;\nuse Carbon\\Carbon;\nuse Filamen"
  },
  {
    "path": "app/Filament/Exports/NoteExporter.php",
    "chars": 1492,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\Note;\nuse Filament\\Actions\\Exports\\Expo"
  },
  {
    "path": "app/Filament/Exports/OpportunityExporter.php",
    "chars": 2515,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\Opportunity;\nuse Carbon\\Carbon;\nuse Fil"
  },
  {
    "path": "app/Filament/Exports/PeopleExporter.php",
    "chars": 1629,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\People;\nuse Filament\\Actions\\Exports\\Ex"
  },
  {
    "path": "app/Filament/Exports/TaskExporter.php",
    "chars": 1485,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Exports;\n\nuse App\\Models\\Task;\nuse Filament\\Actions\\Exports\\Expo"
  },
  {
    "path": "app/Filament/Pages/AccessTokens.php",
    "chars": 899,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Livewire\\App\\AccessTokens\\CreateAccessToken;\nuse"
  },
  {
    "path": "app/Filament/Pages/Auth/Login.php",
    "chars": 1169,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages\\Auth;\n\nuse App\\Concerns\\DetectsTeamInvitation;\nuse Filamen"
  },
  {
    "path": "app/Filament/Pages/Auth/Register.php",
    "chars": 1992,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages\\Auth;\n\nuse App\\Concerns\\DetectsTeamInvitation;\nuse Filamen"
  },
  {
    "path": "app/Filament/Pages/CreateTeam.php",
    "chars": 2858,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Actions\\Jetstream\\CreateTeam as CreateTeamAction"
  },
  {
    "path": "app/Filament/Pages/EditProfile.php",
    "chars": 1183,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Livewire\\App\\Profile\\DeleteAccount;\nuse App\\Live"
  },
  {
    "path": "app/Filament/Pages/EditTeam.php",
    "chars": 1448,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Livewire\\App\\Teams\\AddTeamMember;\nuse App\\Livewi"
  },
  {
    "path": "app/Filament/Pages/OpportunitiesBoard.php",
    "chars": 11963,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Enums\\CustomFields\\OpportunityField as Opportuni"
  },
  {
    "path": "app/Filament/Pages/TasksBoard.php",
    "chars": 11169,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Pages;\n\nuse App\\Enums\\CustomFields\\TaskField as TaskCustomField;"
  },
  {
    "path": "app/Filament/Resources/CompanyResource/Pages/ListCompanies.php",
    "chars": 1558,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\CompanyResource\\Pages;\n\nuse App\\Filament\\Exports\\Compa"
  },
  {
    "path": "app/Filament/Resources/CompanyResource/Pages/ViewCompany.php",
    "chars": 5150,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\CompanyResource\\Pages;\n\nuse App\\Filament\\Actions\\Gener"
  },
  {
    "path": "app/Filament/Resources/CompanyResource/RelationManagers/NotesRelationManager.php",
    "chars": 2175,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\CompanyResource\\RelationManagers;\n\nuse App\\Filament\\Re"
  },
  {
    "path": "app/Filament/Resources/CompanyResource/RelationManagers/PeopleRelationManager.php",
    "chars": 2042,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\CompanyResource\\RelationManagers;\n\nuse Filament\\Action"
  },
  {
    "path": "app/Filament/Resources/CompanyResource/RelationManagers/TasksRelationManager.php",
    "chars": 2326,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\CompanyResource\\RelationManagers;\n\nuse App\\Filament\\Re"
  },
  {
    "path": "app/Filament/Resources/CompanyResource.php",
    "chars": 5096,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\CreationSource;\nuse App\\Filament\\Expor"
  },
  {
    "path": "app/Filament/Resources/NoteResource/Forms/NoteForm.php",
    "chars": 1468,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\NoteResource\\Forms;\n\nuse Filament\\Forms\\Components\\Sel"
  },
  {
    "path": "app/Filament/Resources/NoteResource/Pages/ManageNotes.php",
    "chars": 1408,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\NoteResource\\Pages;\n\nuse App\\Filament\\Exports\\NoteExpo"
  },
  {
    "path": "app/Filament/Resources/NoteResource.php",
    "chars": 4210,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\CreationSource;\nuse App\\Filament\\Expor"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource/Forms/OpportunityForm.php",
    "chars": 1095,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OpportunityResource\\Forms;\n\nuse Filament\\Forms\\Compone"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource/Pages/ListOpportunities.php",
    "chars": 1469,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OpportunityResource\\Pages;\n\nuse App\\Filament\\Exports\\O"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource/Pages/ViewOpportunity.php",
    "chars": 3758,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OpportunityResource\\Pages;\n\nuse App\\Filament\\Actions\\G"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource/RelationManagers/NotesRelationManager.php",
    "chars": 1974,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OpportunityResource\\RelationManagers;\n\nuse App\\Filamen"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource/RelationManagers/TasksRelationManager.php",
    "chars": 1974,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OpportunityResource\\RelationManagers;\n\nuse App\\Filamen"
  },
  {
    "path": "app/Filament/Resources/OpportunityResource.php",
    "chars": 4465,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\CreationSource;\nuse App\\Filament\\Expor"
  },
  {
    "path": "app/Filament/Resources/PeopleResource/Pages/ListPeople.php",
    "chars": 1416,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\PeopleResource\\Pages;\n\nuse App\\Filament\\Exports\\People"
  },
  {
    "path": "app/Filament/Resources/PeopleResource/Pages/ViewPeople.php",
    "chars": 3635,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\PeopleResource\\Pages;\n\nuse App\\Filament\\Actions\\Genera"
  },
  {
    "path": "app/Filament/Resources/PeopleResource/RelationManagers/NotesRelationManager.php",
    "chars": 1629,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\PeopleResource\\RelationManagers;\n\nuse App\\Filament\\Res"
  },
  {
    "path": "app/Filament/Resources/PeopleResource/RelationManagers/TasksRelationManager.php",
    "chars": 1628,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\PeopleResource\\RelationManagers;\n\nuse App\\Filament\\Res"
  },
  {
    "path": "app/Filament/Resources/PeopleResource.php",
    "chars": 7199,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\CreationSource;\nuse App\\Filament\\Expor"
  },
  {
    "path": "app/Filament/Resources/TaskResource/Forms/TaskForm.php",
    "chars": 1506,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TaskResource\\Forms;\n\nuse Filament\\Forms\\Components\\Sel"
  },
  {
    "path": "app/Filament/Resources/TaskResource/Pages/ManageTasks.php",
    "chars": 1685,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TaskResource\\Pages;\n\nuse App\\Actions\\Task\\NotifyTaskAs"
  },
  {
    "path": "app/Filament/Resources/TaskResource.php",
    "chars": 7766,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Actions\\Task\\UpdateTask;\nuse App\\Enums\\Creat"
  },
  {
    "path": "app/Health/AnthropicModelCheck.php",
    "chars": 840,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Health;\n\nuse Prism\\Prism\\Enums\\Provider;\nuse Prism\\Prism\\Facades\\Prism;\nu"
  },
  {
    "path": "app/Http/Controllers/AcceptTeamInvitationController.php",
    "chars": 1798,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\TeamInvitation;\nuse App\\Models\\User;\nus"
  },
  {
    "path": "app/Http/Controllers/Api/V1/CompaniesController.php",
    "chars": 2734,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Actions\\Company\\CreateCompany;\nuse App\\"
  },
  {
    "path": "app/Http/Controllers/Api/V1/CustomFieldsController.php",
    "chars": 1325,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Requests\\Api\\V1\\IndexCustomFieldsR"
  },
  {
    "path": "app/Http/Controllers/Api/V1/NotesController.php",
    "chars": 2579,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Actions\\Note\\CreateNote;\nuse App\\Action"
  },
  {
    "path": "app/Http/Controllers/Api/V1/OpportunitiesController.php",
    "chars": 3433,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Actions\\Opportunity\\CreateOpportunity;\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/PeopleController.php",
    "chars": 3022,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Actions\\People\\CreatePeople;\nuse App\\Ac"
  },
  {
    "path": "app/Http/Controllers/Api/V1/TasksController.php",
    "chars": 2579,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Actions\\Task\\CreateTask;\nuse App\\Action"
  },
  {
    "path": "app/Http/Controllers/Auth/CallbackController.php",
    "chars": 4731,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Contracts\\User\\CreatesNewSocialUsers;\nuse"
  },
  {
    "path": "app/Http/Controllers/Auth/RedirectController.php",
    "chars": 514,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Enums\\SocialiteProvider;\nuse Laravel\\Soci"
  },
  {
    "path": "app/Http/Controllers/ContactController.php",
    "chars": 790,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Requests\\ContactRequest;\nuse App\\Mail\\New"
  },
  {
    "path": "app/Http/Controllers/HomeController.php",
    "chars": 217,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\View\\View;\n\nfinal readonly class HomeCo"
  },
  {
    "path": "app/Http/Controllers/PrivacyPolicyController.php",
    "chars": 443,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\View\\View;\n"
  },
  {
    "path": "app/Http/Controllers/TermsOfServiceController.php",
    "chars": 439,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\View\\View;\n"
  },
  {
    "path": "app/Http/Middleware/ApplyTenantScopes.php",
    "chars": 1130,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\Company;\nuse App\\Models\\Note;\nuse App\\Mo"
  },
  {
    "path": "app/Http/Middleware/EnsureTokenHasAbility.php",
    "chars": 1277,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\PersonalAccessToken;\nuse Closure;\nuse Il"
  },
  {
    "path": "app/Http/Middleware/ForceJsonResponse.php",
    "chars": 375,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Symfony\\C"
  },
  {
    "path": "app/Http/Middleware/SetApiTeamContext.php",
    "chars": 4147,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\Company;\nuse App\\Models\\Note;\nuse App\\Mo"
  },
  {
    "path": "app/Http/Middleware/SubdomainRootResponse.php",
    "chars": 959,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\JsonResponse;\nuse Illu"
  },
  {
    "path": "app/Http/Middleware/ValidateSignature.php",
    "chars": 2917,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminat"
  },
  {
    "path": "app/Http/Requests/Api/V1/IndexCustomFieldsRequest.php",
    "chars": 656,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\nuse Il"
  },
  {
    "path": "app/Http/Requests/Api/V1/IndexRequest.php",
    "chars": 481,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nfinal"
  },
  {
    "path": "app/Http/Requests/Api/V1/StoreCompanyRequest.php",
    "chars": 628,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/StoreNoteRequest.php",
    "chars": 1127,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/StoreOpportunityRequest.php",
    "chars": 889,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/StorePeopleRequest.php",
    "chars": 770,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/StoreTaskRequest.php",
    "chars": 1372,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/UpdateCompanyRequest.php",
    "chars": 658,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/UpdateNoteRequest.php",
    "chars": 1157,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/UpdateOpportunityRequest.php",
    "chars": 919,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/UpdatePeopleRequest.php",
    "chars": 800,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/Api/V1/UpdateTaskRequest.php",
    "chars": 1402,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests\\Api\\V1;\n\nuse App\\Models\\User;\nuse App\\Rules\\ValidCustomFiel"
  },
  {
    "path": "app/Http/Requests/ContactRequest.php",
    "chars": 736,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Contracts\\Validation\\ValidationRule;\nuse I"
  },
  {
    "path": "app/Http/Resources/V1/CompanyResource.php",
    "chars": 1394,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Http\\Resources\\V1\\Concerns\\FormatsCustomField"
  },
  {
    "path": "app/Http/Resources/V1/Concerns/FormatsCustomFields.php",
    "chars": 2787,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse "
  },
  {
    "path": "app/Http/Resources/V1/CustomFieldResource.php",
    "chars": 1237,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Models\\CustomField;\nuse App\\Models\\CustomFiel"
  },
  {
    "path": "app/Http/Resources/V1/NoteResource.php",
    "chars": 1335,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Http\\Resources\\V1\\Concerns\\FormatsCustomField"
  },
  {
    "path": "app/Http/Resources/V1/OpportunityResource.php",
    "chars": 1302,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Http\\Resources\\V1\\Concerns\\FormatsCustomField"
  },
  {
    "path": "app/Http/Resources/V1/PeopleResource.php",
    "chars": 1192,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Http\\Resources\\V1\\Concerns\\FormatsCustomField"
  },
  {
    "path": "app/Http/Resources/V1/TaskResource.php",
    "chars": 1451,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Http\\Resources\\V1\\Concerns\\FormatsCustomField"
  },
  {
    "path": "app/Http/Resources/V1/UserResource.php",
    "chars": 471,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Resources\\V1;\n\nuse App\\Models\\User;\nuse Illuminate\\Http\\Request;\nuse"
  },
  {
    "path": "app/Http/Responses/LoginResponse.php",
    "chars": 1039,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Responses;\n\nuse App\\Filament\\Resources\\CompanyResource;\nuse Filament"
  },
  {
    "path": "app/Jobs/Email/CreateSubscriberJob.php",
    "chars": 862,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Jobs\\Email;\n\nuse App\\Data\\SubscriberData;\nuse Illuminate\\Bus\\Queueable;\nu"
  },
  {
    "path": "app/Jobs/Email/UpdateSubscriberJob.php",
    "chars": 1856,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Jobs\\Email;\n\nuse App\\Data\\SubscriberData;\nuse Illuminate\\Bus\\Queueable;\nu"
  },
  {
    "path": "app/Jobs/FetchFaviconForCompany.php",
    "chars": 2535,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Jobs;\n\nuse App\\Enums\\CustomFields\\CompanyField;\nuse App\\Models\\Company;\nu"
  },
  {
    "path": "app/Listeners/CreateTeamCustomFields.php",
    "chars": 5334,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Listeners;\n\nuse App\\Enums\\CustomFields\\CompanyField as CompanyCustomField"
  },
  {
    "path": "app/Listeners/Email/NewSubscriberListener.php",
    "chars": 1685,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Listeners\\Email;\n\nuse App\\Data\\SubscriberData;\nuse App\\Enums\\SubscriberTa"
  },
  {
    "path": "app/Listeners/SwitchTeam.php",
    "chars": 410,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Listeners;\n\nuse App\\Models\\User;\nuse Filament\\Events\\TenantSet;\n\nfinal re"
  },
  {
    "path": "app/Livewire/App/AccessTokens/CreateAccessToken.php",
    "chars": 6881,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\AccessTokens;\n\nuse App\\Livewire\\BaseLivewireComponent;\nuse D"
  },
  {
    "path": "app/Livewire/App/AccessTokens/ManageAccessTokens.php",
    "chars": 4165,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\AccessTokens;\n\nuse App\\Livewire\\BaseLivewireComponent;\nuse A"
  },
  {
    "path": "app/Livewire/App/Profile/DeleteAccount.php",
    "chars": 4042,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Profile;\n\nuse App\\Actions\\Jetstream\\DeleteTeam;\nuse App\\Live"
  },
  {
    "path": "app/Livewire/App/Profile/LogoutOtherBrowserSessions.php",
    "chars": 5275,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Profile;\n\nuse App\\Livewire\\BaseLivewireComponent;\nuse Filame"
  },
  {
    "path": "app/Livewire/App/Profile/UpdatePassword.php",
    "chars": 4032,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Profile;\n\nuse App\\Livewire\\BaseLivewireComponent;\nuse DanHar"
  },
  {
    "path": "app/Livewire/App/Profile/UpdateProfileInformation.php",
    "chars": 4983,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Profile;\n\nuse App\\Actions\\Fortify\\UpdateUserProfileInformati"
  },
  {
    "path": "app/Livewire/App/Teams/AddTeamMember.php",
    "chars": 4042,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Teams;\n\nuse App\\Actions\\Jetstream\\InviteTeamMember;\nuse App\\"
  },
  {
    "path": "app/Livewire/App/Teams/DeleteTeam.php",
    "chars": 2444,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Teams;\n\nuse App\\Actions\\Jetstream\\DeleteTeam as DeleteTeamAc"
  },
  {
    "path": "app/Livewire/App/Teams/PendingTeamInvitations.php",
    "chars": 5129,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Teams;\n\nuse App\\Livewire\\BaseLivewireComponent;\nuse App\\Mode"
  },
  {
    "path": "app/Livewire/App/Teams/TeamMembers.php",
    "chars": 6977,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Teams;\n\nuse App\\Actions\\Jetstream\\RemoveTeamMember as Remove"
  },
  {
    "path": "app/Livewire/App/Teams/UpdateTeamName.php",
    "chars": 3802,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire\\App\\Teams;\n\nuse App\\Actions\\Jetstream\\UpdateTeamName as UpdateTe"
  },
  {
    "path": "app/Livewire/BaseLivewireComponent.php",
    "chars": 1463,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire;\n\nuse App\\Models\\User;\nuse DanHarrin\\LivewireRateLimiting\\Except"
  },
  {
    "path": "app/Livewire/UpdateProfileInformationForm.php",
    "chars": 2271,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Livewire;\n\nuse Illuminate\\Contracts\\Auth\\Authenticatable;\nuse Illuminate\\"
  },
  {
    "path": "app/Mail/NewContactSubmissionMail.php",
    "chars": 902,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mail;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\Shoul"
  },
  {
    "path": "app/Mcp/Filters/CustomFieldFilter.php",
    "chars": 3143,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Filters;\n\nuse App\\Models\\CustomField;\nuse App\\Models\\User;\nuse Illumi"
  },
  {
    "path": "app/Mcp/Filters/CustomFieldSort.php",
    "chars": 2070,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Filters;\n\nuse App\\Models\\CustomField;\nuse App\\Models\\User;\nuse Illumi"
  },
  {
    "path": "app/Mcp/Prompts/CrmOverviewPrompt.php",
    "chars": 2383,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Prompts;\n\nuse App\\Models\\Company;\nuse App\\Models\\Note;\nuse App\\Models"
  },
  {
    "path": "app/Mcp/Resources/CompanySchemaResource.php",
    "chars": 2304,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Mcp\\Resources\\Concerns\\ResolvesEntitySchema;\nuse "
  },
  {
    "path": "app/Mcp/Resources/Concerns/ResolvesEntitySchema.php",
    "chars": 3750,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources\\Concerns;\n\nuse App\\Mcp\\Schema\\CustomFieldFilterSchema;\nuse "
  },
  {
    "path": "app/Mcp/Resources/CrmSummaryResource.php",
    "chars": 5855,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Enums\\CustomFields\\OpportunityField;\nuse App\\Enum"
  },
  {
    "path": "app/Mcp/Resources/NoteSchemaResource.php",
    "chars": 2942,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Mcp\\Resources\\Concerns\\ResolvesEntitySchema;\nuse "
  },
  {
    "path": "app/Mcp/Resources/OpportunitySchemaResource.php",
    "chars": 2297,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Mcp\\Resources\\Concerns\\ResolvesEntitySchema;\nuse "
  },
  {
    "path": "app/Mcp/Resources/PeopleSchemaResource.php",
    "chars": 2146,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Mcp\\Resources\\Concerns\\ResolvesEntitySchema;\nuse "
  },
  {
    "path": "app/Mcp/Resources/TaskSchemaResource.php",
    "chars": 3308,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Resources;\n\nuse App\\Mcp\\Resources\\Concerns\\ResolvesEntitySchema;\nuse "
  },
  {
    "path": "app/Mcp/Schema/CustomFieldFilterSchema.php",
    "chars": 4694,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Schema;\n\nuse App\\Enums\\CustomFieldType;\nuse App\\Mcp\\Filters\\CustomFie"
  },
  {
    "path": "app/Mcp/Servers/RelaticleServer.php",
    "chars": 3768,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Servers;\n\nuse App\\Mcp\\Prompts\\CrmOverviewPrompt;\nuse App\\Mcp\\Resource"
  },
  {
    "path": "app/Mcp/Tools/BaseAttachTool.php",
    "chars": 2698,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\BuildsRelationshipResponse;\nuse Ap"
  },
  {
    "path": "app/Mcp/Tools/BaseCreateTool.php",
    "chars": 2286,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Enums\\CreationSource;\nuse App\\Mcp\\Tools\\Concerns\\Chec"
  },
  {
    "path": "app/Mcp/Tools/BaseDeleteTool.php",
    "chars": 1898,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\ChecksTokenAbility;\nuse App\\Models"
  },
  {
    "path": "app/Mcp/Tools/BaseDetachTool.php",
    "chars": 2702,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\BuildsRelationshipResponse;\nuse Ap"
  },
  {
    "path": "app/Mcp/Tools/BaseListTool.php",
    "chars": 5525,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\ChecksTokenAbility;\nuse App\\Mcp\\To"
  },
  {
    "path": "app/Mcp/Tools/BaseShowTool.php",
    "chars": 3635,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\ChecksTokenAbility;\nuse App\\Mcp\\To"
  },
  {
    "path": "app/Mcp/Tools/BaseUpdateTool.php",
    "chars": 3101,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools;\n\nuse App\\Mcp\\Tools\\Concerns\\ChecksTokenAbility;\nuse App\\Models"
  },
  {
    "path": "app/Mcp/Tools/Company/CreateCompanyTool.php",
    "chars": 1092,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Company;\n\nuse App\\Actions\\Company\\CreateCompany;\nuse App\\Http\\R"
  },
  {
    "path": "app/Mcp/Tools/Company/DeleteCompanyTool.php",
    "chars": 671,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Company;\n\nuse App\\Actions\\Company\\DeleteCompany;\nuse App\\Mcp\\To"
  },
  {
    "path": "app/Mcp/Tools/Company/GetCompanyTool.php",
    "chars": 948,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Company;\n\nuse App\\Http\\Resources\\V1\\CompanyResource;\nuse App\\Mc"
  },
  {
    "path": "app/Mcp/Tools/Company/ListCompaniesTool.php",
    "chars": 782,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Company;\n\nuse App\\Actions\\Company\\ListCompanies;\nuse App\\Http\\R"
  },
  {
    "path": "app/Mcp/Tools/Company/UpdateCompanyTool.php",
    "chars": 1354,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Company;\n\nuse App\\Actions\\Company\\UpdateCompany;\nuse App\\Http\\R"
  },
  {
    "path": "app/Mcp/Tools/Concerns/BuildsRelationshipResponse.php",
    "chars": 1360,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illumina"
  },
  {
    "path": "app/Mcp/Tools/Concerns/ChecksTokenAbility.php",
    "chars": 595,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Concerns;\n\nuse App\\Models\\PersonalAccessToken;\nuse Laravel\\Sanc"
  },
  {
    "path": "app/Mcp/Tools/Concerns/SerializesRelatedModels.php",
    "chars": 3016,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Collection as Eloqu"
  },
  {
    "path": "app/Mcp/Tools/Note/AttachNoteToEntitiesTool.php",
    "chars": 2495,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Note;\n\nuse App\\Http\\Resources\\V1\\NoteResource;\nuse App\\Mcp\\Tool"
  },
  {
    "path": "app/Mcp/Tools/Note/CreateNoteTool.php",
    "chars": 1918,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Note;\n\nuse App\\Actions\\Note\\CreateNote;\nuse App\\Http\\Resources\\"
  },
  {
    "path": "app/Mcp/Tools/Note/DeleteNoteTool.php",
    "chars": 728,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Note;\n\nuse App\\Actions\\Note\\DeleteNote;\nuse App\\Mcp\\Tools\\BaseD"
  },
  {
    "path": "app/Mcp/Tools/Note/DetachNoteFromEntitiesTool.php",
    "chars": 2447,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Note;\n\nuse App\\Http\\Resources\\V1\\NoteResource;\nuse App\\Mcp\\Tool"
  },
  {
    "path": "app/Mcp/Tools/Note/GetNoteTool.php",
    "chars": 911,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Mcp\\Tools\\Note;\n\nuse App\\Http\\Resources\\V1\\NoteResource;\nuse App\\Mcp\\Tool"
  }
]

// ... and 711 more files (download for full content)

About this extraction

This page contains the full source code of the Relaticle/relaticle GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 911 files (7.3 MB), approximately 2.0M tokens, and a symbol index with 10898 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!