Architecture diagrams
Twenty Mermaid diagrams show how the kit works today: architecture, role-based access, authentication, AI, infrastructure, the data model and the kit’s own lifecycle. Each one is guarded by an automated test (tests/Kit/DiagramasDaArquiteturaTest.php, tests/Kit/GuardasDosDiagramasTest.php and, under multi-tenancy, tests/Tenancy/DiagramasDaArquiteturaTenancyTest.php) that fails the moment the code stops matching what the diagram describes — none of them describes planned functionality.
DG-01 — Layered architecture
From the browser to the three Filament panels (app/Providers/Filament/AppPanelProvider.php:id:79, app/Providers/Filament/AdminPanelProvider.php:id:69, app/Providers/Filament/InfraPanelProvider.php:id:90), through role-based access, down to the database, queue, cache and the optional services. It is the same block as the README — a single source.
flowchart TD
%% DG-01
accTitle: Layered architecture
accDescr: From the browser to the three Filament panels, through role-based access, down to the database, queue, cache and the optional services.
navegador[Browser] --> rota_publica["Public / route"]
navegador --> painel_app
navegador --> painel_admin
navegador --> painel_infra
subgraph camada_paineis ["Panels (Filament)"]
painel_app["/app (default)"]
painel_admin["/admin"]
painel_infra["/infra"]
end
painel_app --> acesso_por_papel[Role-based access]
painel_admin --> acesso_por_papel
painel_infra --> acesso_por_papel
acesso_por_papel --> configuracoes[Settings]
acesso_por_papel --> agentes_ia[AI agents]
subgraph camada_infra ["Infrastructure"]
banco[("Database")]
fila[Queue]
cache[("Cache")]
worker["Worker (optional)"]
agendador["Scheduler (optional)"]
reverb["Reverb (optional)"]
pulse["Pulse (pulse:check)"]
end
configuracoes --> banco
configuracoes --> cache
agentes_ia -->|"writes ai_runs"| banco
agentes_ia --> fila
fila --> worker
agendador --> fila
reverb --> camada_paineis
painel_infra --> pulse
pulse --> banco
agentes_ia -.->|"optional"| ia_externa["Local or SaaS AI"]
camada_paineis -.-> oauth["OAuth"]
configuracoes -.-> email_externo["Mail"]
painel_infra -.-> packagist["Packagist"]
DG-02 — Use cases by role
The kit’s eight actors (visitor, panel_user, admin_app, admin, infra, master_global, the scheduler and the CLI) and the use cases each role reaches. admin_app only exists when KIT_TENANCY is on (database/seeders/PapeisSeeder.php:papel:80); the other roles are always seeded (database/seeders/PapeisSeeder.php:papel:58, :papel:61, :papel:101). Every edge ties the role to the permission entity it actually holds in the database (Shield) — or, for master_global, to the code that lets them through without Shield: Gate::before (cu_tudo) and, for “Impersonate user”, User::canImpersonate() (app/Models/User.php:canImpersonate:882), which only accepts master_global — never to a guess.
flowchart LR
%% DG-02
accTitle: Use cases by role
accDescr: The kit's eight actors and the use cases each role reaches, inside the Starter Kit Easy boundary.
ator_visitante["Visitor"]
ator_panel_user["Panel user (panel_user)"]
ator_admin_app["Organization admin (admin_app; requires KIT_TENANCY)"]
ator_admin["Administrator (admin)"]
ator_infra["Infrastructure (infra)"]
ator_master_global["Super admin (master_global)"]
ator_agendador["Scheduler"]
ator_cli["CLI operator"]
subgraph fronteira ["Starter Kit Easy"]
cu_login["Log in"]
cu_login_social["Log in with social login (optional)"]
cu_recuperar_senha["Reset password"]
cu_cadastro["Sign up (optional)"]
cu_aceitar_convite["Accept/decline received invite (declining requires KIT_TENANCY)"]
cu_trocar_painel["Switch panel"]
cu_2fa["Confirm 2FA"]
cu_bloqueio["Lock/unlock session"]
cu_operar_negocio["Operate the business in /app"]
cu_convidar["Invite user (manage invites)"]
cu_gerir_usuarios["Manage users"]
cu_gerir_usuarios_org["Manage organization users (optional)"]
cu_aprovar_cadastro["Approve sign-up (KIT_REGISTRO_APROVACAO_MANUAL)"]
cu_gerir_papeis["Manage roles and permissions"]
cu_configuracoes["Configure the application"]
cu_ver_logs["View the logs"]
cu_ver_saude["View installation health"]
cu_lixeira["Use the Recycle Bin"]
cu_personificar["Impersonate user"]
cu_lembrar_convites["Remind pending invites"]
cu_tenancy["Enable multi-tenancy"]
cu_tudo["Everything, via Gate::before"]
end
ator_visitante --> cu_login
ator_visitante --> cu_login_social
ator_visitante --> cu_recuperar_senha
ator_visitante --> cu_cadastro
ator_panel_user --> cu_login
ator_panel_user --> cu_2fa
ator_panel_user --> cu_bloqueio
ator_panel_user --> cu_trocar_painel
ator_panel_user --> cu_aceitar_convite
ator_panel_user --> cu_operar_negocio
ator_admin_app --> cu_convidar
ator_admin_app --> cu_gerir_usuarios_org
ator_admin --> cu_gerir_usuarios
ator_admin --> cu_convidar
ator_admin --> cu_gerir_papeis
ator_admin --> cu_configuracoes
ator_admin --> cu_aprovar_cadastro
ator_infra --> cu_ver_logs
ator_infra --> cu_ver_saude
ator_infra --> cu_lixeira
ator_master_global --> cu_tudo
ator_master_global --> cu_personificar
ator_agendador --> cu_lembrar_convites
ator_cli --> cu_tenancy
DG-03 — Panel access rule
The exact order of User::canAccessPanel() (app/Models/User.php:canAccessPanel:157): account unavailability (:166), pending approval (:193), master_global (:206), the role’s context — any tenant with tenancy on, only the global context without it (:217) — and finally the panel role (:219). Once allowed, the User::canAccessTenant() extension (:789) decides the tenant, and the ORDER matters: an inactive organization denies first, for everyone — including master_global (:813) —; only then does master_global always get in (:826), and no link denies (:830).
flowchart TD
%% DG-03
accTitle: Panel access rule
accDescr: The decision order of canAccessPanel, from account unavailability to the role check, and the canAccessTenant extension when the panel uses multi-tenancy under KIT_TENANCY.
inicio(["Start"]) --> checa_indisponivel{"Account unavailable?"}
checa_indisponivel -->|"Yes"| nega_403["Deny (403)"]
checa_indisponivel -->|"No"| checa_pendente{"Approval pending?"}
checa_pendente -->|"Yes"| nega_403
checa_pendente -->|"No"| checa_master{"Is master_global?"}
checa_master -->|"Yes"| permite["Allow"]
checa_master -->|"No"| checa_contexto{"Panel with tenancy?"}
checa_contexto -->|"Yes"| papel_em_alguma["Role in any tenant"]
checa_contexto -->|"No"| papel_global["Role in the global context"]
papel_em_alguma --> checa_papel{"Has panel role?"}
papel_global --> checa_papel
checa_papel -->|"Yes"| permite
checa_papel -->|"No"| nega_403
permite --> checa_tenant{"Tenant accessed: is it inactive?"}
checa_tenant -->|"Yes"| nega_404["Deny (404)"]
checa_tenant -->|"No"| checa_vinculo{"master_global or linked to the tenant?"}
checa_vinculo -->|"Yes"| permite_tenant["Enter the tenant"]
checa_vinculo -->|"No"| nega_404
DG-13 — Core entity-relationship diagram
The central entities and how they reference each other: the account (users) to a tenant via tenant_user (app/Models/User.php:tenants:778, app/Models/Tenant.php:users:118), to a role via model_has_roles (Shield), the social link (app/Models/User.php:vinculosSociais:788), the invite — with a nullable convidado_por_id (database/migrations/2026_08_13_000002_create_convites_table.php:convidado_por_id:42) — via papel(), tenant() and convidadoPor() (app/Models/Convite.php:papel:116, :tenant:122, :convidadoPor:128) and the AI agent catalog — with no relation at all to projetos, the demo table (app/Traits/BelongsToTenant.php:tenant:82). ai_runs and agent_conversations are left out of this ER: they store identifiers as loose text (subject_type/subject_id, participant_type/participant_id), with no real foreign key, and drawing a relation for them would invent an FK the schema doesn’t have. passkeys is left out for the opposite reason: the table exists (vendor), but no feature in the kit uses it — passkeys are disabled (enablePasskeys() is never called).
erDiagram
%% DG-13
accTitle: Core entity-relationship diagram
accDescr: The kit's central entities and how they reference each other - the user's tie to a tenant and a role, invites, social login links and the AI agent catalog.
users ||--o{ tenant_user : belongs
tenants ||--o{ tenant_user : gathers
users ||--o{ model_has_roles : receives
roles ||--o{ model_has_roles : grants
users ||--o{ vinculos_sociais : authenticates
users |o--o{ convites : invited
roles ||--o{ convites : "invite role"
tenants |o--o{ convites : "tenant, with KIT_TENANCY (optional)"
tenants ||--o{ projetos : "has, demo scenario (KIT_DEMO)"
agentes_ia {
string slug
boolean ativo
string provider
text instrucoes
}
convites {
string email
string token
timestamp expira_em
timestamp aceito_em
timestamp recusado_em
string token_lembrete
timestamp enviado_em
int lembretes_enviados
}
About where these diagrams come from
GitDiagram generated a first, AI read of this repository — an AI-generated view, not verified. The official diagram is this page, which corrects and expands it: GitDiagram presented what is optional (organizations, tenancy) as always-present and left out the kit’s central rule (role-based access).
Index of the 20 diagrams
| DG | Diagram | Page |
|---|---|---|
| DG-01 | Layered architecture | This page |
| DG-02 | Use cases by role | This page |
| DG-03 | Panel access rule | This page |
| DG-04 | Password login and second factor | Authentication |
| DG-05 | Unified login - destination by 0, 1 or N panels | Unified login |
| DG-06 | Social login return | Social login |
| DG-07 | Invitation, from send to acceptance | Invites |
| DG-08 | User account states | User states |
| DG-09 | Invitation states | Invites |
| DG-10 | Authenticated session | Authentication |
| DG-11 | Assistant sequence | Feature roadmap |
| DG-12 | Map of /infra: screen, source and who writes it | Infrastructure trails |
| DG-13 | Core entity-relationship diagram | This page |
| DG-14 | Where configuration comes from | Kit settings |
| DG-15 | Installation sequence | Advanced installation |
| DG-16 | The kit:update flow | Updating the project |
| DG-17 | The two delivery routes | Updating the project |
| DG-18 | Containers by Docker profile | Advanced installation |
| DG-19 | Background - composer dev x Docker Compose x scheduler | Developing the kit |
| DG-20 | Request to /app/{tenant} | Multi-tenancy |