Status: Approved · v2 · SPEC-DOMAIN-TERRITORY-001
depends_on: SPEC-DOMAIN-BASE-001
used_by: IS-MVP-02.2, IS-MVP-03.3, IS-MVP-04.1
Território e vocabulário regional
Hierarquia territorial oficial e adaptação de termos sem fragmentar o modelo técnico.
Objetivo e limites
Esta especificação define o comportamento canônico do domínio Território e vocabulário regional no RaizFC. Ela deve ser consultada antes de alterar contratos, mocks, endpoints, telas, permissões ou Increment Specifications relacionados.
Incluído no MVP
- Hierarquia Estado → Município → Distrito → Bairro/Quebrada.
- Distrito obrigatório para usuários e entidades.
- Neighborhood opcional e subordinado ao distrito.
- Vocabulário regional resolvido por prioridade.
- Páginas públicas agregadoras de distrito e bairro.
Fora do MVP
- Geofencing.
- Mapas e raio por coordenadas.
- Gestão autônoma de bairro.
- Carteira e patrocínio de bairro.
Atores e responsabilidades
| Ator | Responsabilidade |
|---|---|
| Usuário | Escolhe distrito e opcionalmente bairro/quebrada. |
| Gestor | Define território das entidades que cria. |
| Operação | Mantém cadastros oficiais e resolve duplicidades. |
| Visitante | Descobre entidades e rankings por território. |
Conceitos canônicos
District
Base oficial do produto; exemplo São Mateus.
Neighborhood
Bairro, quebrada ou comunidade conforme UI regional.
Vocabulary Profile
Conjunto de labels aplicável por usuário, distrito, município, estado ou padrão.
Territory Reference
Resumo com state, city, district e neighborhood usado em DTOs públicos.
Invariantes
- Todo usuário ativo possui districtId.
- Toda entidade pública do MVP possui districtId.
- Neighborhood sempre pertence a exatamente um distrito.
- Time só pode se associar a neighborhoods do próprio distrito.
- Vocabulário altera labels, nunca IDs ou entidades técnicas.
- Neighborhood não possui gestores, carteira nem patrocinadores no MVP.
Estados
| Estado | Significado | Visibilidade/efeito |
|---|---|---|
| active | Território utilizável | Aparece em seleção e busca. |
| inactive | Não aceita novas associações | Histórico continua visível. |
| merged | Duplicado incorporado a outro | Rotas redirecionam para destino. |
Transições permitidas
| Origem | Ação | Destino | Autoridade | Efeitos |
|---|---|---|---|---|
| active | deactivate | inactive | Operação | Impede novos vínculos. |
| active/inactive | merge | merged | Operação | Reatribui referências e mantém alias. |
Permissões
| Permission key | Quem recebe por padrão | Ação protegida | Auditoria |
|---|---|---|---|
| territory.read | Público | Listar e descobrir | Não |
| territory.manageCatalog | Operação | Criar/editar/mesclar territórios | Sim |
Fluxos funcionais
Seleção de distrito
- Cliente lista estados e municípios.
- Usuário busca ou navega até distrito.
- Backend valida distrito ativo.
- Preferências e entidades usam o ID canônico.
Resolução de vocabulário
- Cliente informa contexto autenticado ou localização da página.
- Servidor resolve override do usuário.
- Se ausente, aplica distrito, município, estado e padrão nessa ordem.
- Retorna labels como Bairro, Quebrada ou Comunidade sem mudar Neighborhood.
Criação de neighborhood
- Operação ou fluxo moderado propõe nome dentro de distrito.
- Sistema normaliza slug e detecta similaridade.
- Se aprovado, cria página agregadora pública.
Casos-limite e erros
| Cenário | Comportamento esperado | Código/estado |
|---|---|---|
| Neighborhood de outro distrito em time | Rejeitar atualização | NEIGHBORHOOD_DISTRICT_MISMATCH |
| Distrito inativo | Impedir novas associações | DISTRICT_INACTIVE |
| Território duplicado | Redirecionar e usar ID canônico | TERRITORY_MERGED |
| Vocabulário ausente | Usar labels padrão | — |
Privacidade e exposição pública
- Distrito é público em perfis e entidades conforme regras do domínio.
- Endereço detalhado é opcional e possui visibilidade própria.
- Neighborhood não deve inferir endereço exato de usuário.
Notificações e auditoria
- Mesclagem territorial pode gerar aviso a gestores afetados.
- Mudança de distrito de entidade crítica deve entrar em audit log.
API relacionada
| Método | Rota | Acesso | Finalidade |
|---|---|---|---|
| GET | /api/v1/territory/states | Público | Listar estados |
| GET | /api/v1/territory/cities | Público | Listar municípios |
| GET | /api/v1/territory/districts | Público | Listar/buscar distritos |
| GET | /api/v1/territory/neighborhoods | Público | Listar bairros/quebradas |
| GET | /api/v1/territory/vocabulary/resolve | Público/opcional | Resolver labels |
| GET | /api/v1/districts/:slug | Público | Página/dados de distrito |
| GET | /api/v1/neighborhoods/:slug | Público | Página/dados de bairro |
Contratos compartilhados
- StateDto
- CityDto
- DistrictDto
- NeighborhoodDto
- TerritoryReferenceDto
- VocabularyDto
- ResolveVocabularyResponse
Requisitos de UX
- Seletores suportam busca textual.
- UI exibe label regional, mas rotas e código mantêm district/neighborhood.
- Páginas territoriais destacam times, jogos, campeonatos, torcidas, ranking e serviços locais.
- Mudança de distrito em entidade existente exige confirmação por impacto.
Comportamento dos mocks
- Seed principal em São Paulo → São Paulo → São Mateus, com neighborhoods previsíveis.
- Cenário de território inativo e merged.
- Vocabulary scenario com label Quebrada.
Critérios de aceite
- Distrito obrigatório em onboarding e criação de entidades.
- Neighborhood incompatível é rejeitado.
- Vocabulário regional não altera contratos.
- Páginas territoriais funcionam sem login.
Testes obrigatórios
- Hierarquia e filtros.
- Validação de mesmo distrito.
- Resolução de vocabulário por prioridade.
- Redirecionamento de merged.
Pós-MVP
- Busca por raio.
- Mapas.
- Sugestão por GPS.
- Governança comunitária avançada.
Decisões registradas
- Antigo conceito de comunidade/quebrada é Neighborhood.
- Distrito é a base oficial e obrigatória.
- Neighborhood não é entidade gerenciável no MVP.
Machine summary
spec: SPEC-DOMAIN-TERRITORY-001
domain: Território e vocabulário regional
must_preserve:
- Todo usuário ativo possui districtId.
- Toda entidade pública do MVP possui districtId.
- Neighborhood sempre pertence a exatamente um distrito.
- Time só pode se associar a neighborhoods do próprio distrito.
- Vocabulário altera labels, nunca IDs ou entidades técnicas.
- Neighborhood não possui gestores, carteira nem patrocinadores no MVP.
touches:
- contracts
- mocks
- api
- frontend
- backend
- tests
- documentation