Status: Approved · v2 · SPEC-DOMAIN-TEAM-001
depends_on: SPEC-DOMAIN-AUTH-001, SPEC-DOMAIN-TERRITORY-001
used_by: IS-MVP-01.1, IS-MVP-04.1, IS-MVP-04.2, IS-MVP-04.3
Times
Entidade central do ecossistema, com identidade pública, gestão, elenco, jogos, torcidas e carteira.
Objetivo e limites
Esta especificação define o comportamento canônico do domínio Times no RaizFC. Ela deve ser consultada antes de alterar contratos, mocks, endpoints, telas, permissões ou Increment Specifications relacionados.
Incluído no MVP
- Criação por usuário autenticado.
- Página pública completa.
- Categorias como tags do mesmo time.
- Vínculos de jogadores ativos, convidados e ex-atletas.
- Múltiplas torcidas aprovadas pelo time.
- Carteira, apoio e até três patrocinadores ativos.
- Identidade visual básica e posts oficiais.
Fora do MVP
- Subtimes independentes por categoria.
- Reserva de campo.
- Loja integrada.
- Aceitar amistosos com agenda automática.
- Gestão profissional de contratos.
Atores e responsabilidades
| Ator | Responsabilidade |
|---|---|
| Visitante | Lê página, jogos, elenco público e patrocinadores. |
| Torcedor | Segue, torce, apoia e compartilha. |
| Jogador | Aceita convite e aparece conforme privacidade. |
| Gestor esportivo | Administra categorias, elenco e partidas. |
| Gestor de mídia | Administra identidade e posts. |
| Gestor financeiro | Vê carteira, patrocínios e transferências. |
| Responsável principal | Controla todas as permissões e propriedade. |
Conceitos canônicos
Team
Agregado que concentra identidade e relações esportivas.
TeamCategory
Tag/categoria no mesmo time; jogador pode atuar em várias.
TeamPlayerLink
Vínculo entre time e jogador cadastrado ou convidado.
Cheer
Apoio público; cria follow.
Loyal Supporter
Usuário que torce para apenas um time de várzea.
Invariantes
- Time possui um único primary_owner no MVP.
- Time possui districtId obrigatório e neighborhood compatível quando informado.
- Slug público é único e preserva redirects após alteração.
- Categorias não criam outra torcida, carteira ou página principal.
- Jogador cadastrado só vira active após aceite, salvo se já ativo e regra de campeonato permitir escalação.
- Convidado não confirmado não alimenta histórico público pessoal.
- Torcer sempre cria follow; deixar de seguir não remove cheer sem confirmação explícita.
- Time tem no máximo três patrocínios ativos/reservados simultaneamente.
- Carteira nunca é sacável.
Estados
| Estado | Significado | Visibilidade/efeito |
|---|---|---|
| active | Time operacional | Página e gestão normais. |
| inactive | Sem atividade atual | Página preservada com aviso. |
| abandoned | Sem gestão reconhecida | Página pode ser reivindicada. |
| closed | Atividades encerradas | Histórico preservado, gestão limitada. |
| under_review | Em análise | Pode exibir aviso; ações sensíveis limitadas. |
| suspended | Bloqueado | Página limitada/indisponível conforme gravidade. |
| duplicated_merged | Unificado a outro | Rota redireciona ao time canônico. |
Transições permitidas
| Origem | Ação | Destino | Autoridade | Efeitos |
|---|---|---|---|---|
| — | create | active | Usuário autenticado | Cria primary_owner, página e wallet. |
| active | mark_inactive | inactive | Primary owner/operação | Mantém histórico. |
| active/inactive | mark_abandoned | abandoned | Operação | Abre reivindicação. |
| abandoned | approve_claim | active | Operação | Transfere primary_owner. |
| active/inactive | close | closed | Primary owner/operação | Bloqueia novas partidas/vínculos. |
| any | suspend | suspended | Operação | Suspende ações e registra motivo. |
| active/inactive/abandoned | merge | duplicated_merged | Operação | Migra referências e redirects. |
Permissões
| Permission key | Quem recebe por padrão | Ação protegida | Auditoria |
|---|---|---|---|
| team.viewManagement | Viewer e gestores | Abrir painel | Não |
| team.editProfile | Admin/Media | Editar identidade e dados públicos | Sim |
| team.manageCategories | Sports/Admin | Criar e ordenar categorias | Sim |
| team.manageSquad | Squad/Sports/Admin | Convidar, encerrar e gerir vínculos | Sim |
| team.manageMatches | Sports/Admin | Criar e administrar partidas | Sim |
| team.managePosts | Media/Admin | Publicar e aprovar sugestões | Sim |
| team.manageWallet | Financial/Admin | Ver extrato e usar créditos | Sim |
| team.manageSponsors | Financial/Admin | Contratar/editar patrocinadores | Sim |
| team.manageManagers | Admin/Primary owner | Gerir acessos | Sim |
| team.transferOwnership | Primary owner | Transferir responsabilidade | Sim |
Fluxos funcionais
Criação do time
- Usuário autenticado informa nome, distrito, slug sugerido e categorias iniciais.
- Backend valida duplicidade por slug/nome/território.
- Time é criado active.
- Criador recebe membership primary_owner.
- Wallet vazia é criada.
- Página pública fica disponível imediatamente e pode ser denunciada.
Convite de jogador cadastrado
- Gestor com team.manageSquad busca jogador.
- Cria TeamPlayerLink invited com categorias propostas.
- Jogador recebe notificação.
- Ao aceitar, link vira active e passa a aparecer conforme privacidade.
- Ao rejeitar, link vira rejected e não entra no elenco.
Adição de convidado não cadastrado
- Gestor registra nome de exibição e dados privados mínimos.
- Link guest é criado.
- Convidado pode ser relacionado em amistosos/festivais/desafios.
- Se futuramente reivindicado e confirmado, histórico elegível é associado.
Encerramento de vínculo
- Jogador ou gestor solicita encerramento.
- Sistema verifica partidas/campeonatos em andamento sem bloquear histórico.
- Link vira former com endedAt.
- Perfil público pode ocultar ex-times conforme privacidade do jogador.
Torcer
- Usuário autenticado confirma apoio público.
- Cheer é criado e follow garantido.
- Métricas do time e status de loyal supporter são recalculados.
Aprovação de torcida
- Torcida criada fica pending_team_approval.
- Gestor do time recebe pendência.
- Ao aprovar, torcida pode operar publicamente e trocar créditos com o time.
Casos-limite e erros
| Cenário | Comportamento esperado | Código/estado |
|---|---|---|
| Slug em uso | Sugerir alternativa e impedir criação | TEAM_SLUG_TAKEN |
| Time duplicado | Orientar reivindicação ou denúncia | TEAM_POSSIBLE_DUPLICATE |
| Neighborhood incompatível | Rejeitar | NEIGHBORHOOD_DISTRICT_MISMATCH |
| Último primary owner tenta sair | Bloquear até transferir | PRIMARY_OWNER_REQUIRED |
| Jogador já ativo | Não duplicar vínculo; permitir atualização de categorias | PLAYER_ALREADY_ACTIVE |
| Patrocínio lotado | Não criar checkout enquanto três slots ativos/reservados | SPONSOR_LIMIT_REACHED |
| Time suspenso | Bloquear gestão e ações financeiras | TEAM_SUSPENDED |
Privacidade e exposição pública
- Página pública nunca mostra saldo, extrato, permissões ou dados privados de convidados.
- Contatos do time possuem configuração de visibilidade.
- Elenco respeita privacidade de cada jogador.
- Apoiadores públicos aparecem sem valor e até o limite configurado.
- Patrocinadores exibem apenas conteúdo aprovado.
Notificações e auditoria
- Convites e respostas de jogadores.
- Pedidos e aprovação de torcidas.
- Resultados aguardando validação.
- Contestações e retificações.
- Entradas/expirações/transferências de créditos para gestores financeiros.
- Mudanças de gestores e ownership.
- Audit log para identidade, vínculos, jogos, financeiro e permissões.
API relacionada
| Método | Rota | Acesso | Finalidade |
|---|---|---|---|
| POST | /api/v1/teams | Autenticado | Criar time |
| GET | /api/v1/teams/:slug | Público | Página pública |
| PATCH | /api/v1/teams/:id | team.editProfile | Editar |
| GET | /api/v1/teams/:id/management-summary | Gestão | Resumo |
| POST | /api/v1/teams/:id/categories | team.manageCategories | Criar categoria |
| POST | /api/v1/teams/:id/player-invites | team.manageSquad | Convidar jogador |
| POST | /api/v1/teams/:id/guest-players | team.manageSquad | Adicionar convidado |
| PATCH | /api/v1/teams/:id/player-links/:linkId | team.manageSquad | Alterar/encerrar vínculo |
| POST | /api/v1/teams/:id/cheer | Autenticado | Torcer |
| POST | /api/v1/follows | Autenticado | Seguir |
| GET | /api/v1/teams/:id/torcidas | Público | Listar torcidas |
| POST | /api/v1/teams/:id/torcidas/:torcidaId/approve | team.manageTorcidas | Aprovar torcida |
Contratos compartilhados
- TeamEntity
- PublicTeamDto
- TeamManagementDto
- TeamSummaryDto
- CreateTeamRequest/Response
- UpdateTeamRequest
- TeamCategoryDto
- TeamPlayerLinkDto
- InvitePlayerRequest
- CreateGuestPlayerRequest
- CheerTeamResponse
Requisitos de UX
- Página pública detalhada com identidade, ações, jogos, ranking, stats, categorias, elenco, torcidas, apoiadores, sponsors e feed.
- Painel de gestão separado em seções: dashboard, elenco, jogos, súmulas, publicações, torcidas, carteira, patrocínios, identidade, permissões e configurações.
- Ações sem permissão aparecem desabilitadas com explicação.
- Time abandoned/inactive/closed exibe aviso e ações compatíveis.
- Mobile prioriza ações e jogos; desktop amplia navegação e informações laterais.
Comportamento dos mocks
- Times em estados active, inactive, abandoned, suspended e merged.
- Elenco com active, invited, guest e former.
- Mutations de cheer/follow, convite, aceite, categorias e identidade alteram banco em memória.
- Cenários de wallet vazia, sponsor lotado e permissões insuficientes.
Critérios de aceite
- Criação gera owner, wallet e página pública.
- Categorias permanecem no mesmo time.
- Vínculo cadastrado exige aceite.
- Guest não aparece como histórico público confirmado.
- Torcer gera follow.
- Gestão respeita permissions e status.
- DTO público não vaza financeiro ou acessos.
Testes obrigatórios
- Criação e duplicidade.
- Membership primary_owner.
- Categorias e validação territorial.
- Convite/aceite/rejeição/encerramento.
- Guest confirmation.
- Cheer/follow/loyal supporter.
- Status abandoned/closed/suspended/merged.
- Limite de patrocinadores.
Pós-MVP
- Agenda “aceita amistosos”.
- Subpáginas independentes por categoria se evidência justificar.
- Loja e produtos.
- Gestão de contratos e mensalidades.
Decisões registradas
- Time é entidade central do MVP.
- Categorias são tags do mesmo time.
- Qualquer autenticado pode criar; criador vira primary_owner.
- Time possui wallet e sponsors; campeonato, campo e serviço não.
- Página pública é imediata e moderada por denúncia.
Machine summary
spec: SPEC-DOMAIN-TEAM-001
domain: Times
must_preserve:
- Time possui um único primary_owner no MVP.
- Time possui districtId obrigatório e neighborhood compatível quando informado.
- Slug público é único e preserva redirects após alteração.
- Categorias não criam outra torcida, carteira ou página principal.
- Jogador cadastrado só vira active após aceite, salvo se já ativo e regra de campeonato permitir escalação.
- Convidado não confirmado não alimenta histórico público pessoal.
- Torcer sempre cria follow; deixar de seguir não remove cheer sem confirmação explícita.
- Time tem no máximo três patrocínios ativos/reservados simultaneamente.
touches:
- contracts
- mocks
- api
- frontend
- backend
- tests
- documentation