| Nome completo | RM |
|---|---|
| Weslley Cardoso | 557927 |
| Fernando Navajas Moraes | 555080 |
| Gabriel Terra Lilla dos Santos | 554575 |
| José Guilherme Sipaúba Costa | 557274 |
| Bruna da Costa Candeias | 558938 |
App mobile e API REST para proprietários de veículos Ford. Permite ao usuário acompanhar a saúde do veículo, o histórico de manutenções, as recomendações de revisão e agendar serviço na rede oficial.
Desenvolvido como parte do Ford FIAP Challenge 2026 — atacando o desafio de retenção de clientes na rede oficial Ford através de visibilidade proativa sobre o veículo e sua manutenção.
- Sobre o projeto
- Funcionalidades
- Demonstração visual
- Stack
- Estrutura de pastas
- Decisões técnicas
- Pré-requisitos
- Quickstart
- Como o app encontra o backend
- Desenvolvimento local
- Cenários avançados
- Variáveis de ambiente
- API
- Testes
- Comandos úteis
- Documentação
- Próximos passos
- Números do projeto
- Highlights técnicos
A Ford trouxe dois desafios para times de estudantes da FIAP em 2026. Este projeto resolve o Desafio 2 — VIN Share / Retenção de Clientes: identificar e engajar proprietários com risco de não retornar para manutenção paga na rede oficial Ford.
A abordagem do app:
- Dar visibilidade ao dono do carro sobre seu veículo, histórico de serviços e recomendações de manutenção
- Reduzir atrito de informação que hoje leva clientes a buscar oficinas independentes
- Servir como camada de relacionamento entre o cliente final e a rede de concessionárias
A Sprint 1 entrega um MVP com dados mockados via seed — sem integração real com sistemas Ford.
Funcionalidades implementadas na Sprint 1:
Autenticação e perfil
- Login com email e senha, autenticação via JWT
- Tela de perfil do usuário
Saúde e manutenção do veículo — núcleo da solução
- Score de saúde do veículo com indicador visual
- Recomendações de manutenção com prazo, faixa de custo e prioridade
- Cartão de garantia com alerta de risco quando há revisão obrigatória atrasada
- Texto educativo "por que isso é importante" em cada recomendação
- Agendamento de serviço na concessionária — seleção de serviços, concessionária, data e período
- Confirmação visual do agendamento e lembrete na tela inicial
- Histórico de manutenções realizadas
- Lista de concessionárias ordenada por proximidade
Visão e controle do veículo
- Painel de vitais com semáforo de alertas — status do veículo, combustível e autonomia, pressão individual dos quatro pneus, vida útil do óleo, voltagem da bateria, fluido do limpador, pastilhas de freio, correia dentada e temperatura do motor
- Pull-to-refresh no painel para atualização sob demanda
- Climatização — ligar/desligar, modo, velocidade do ventilador e zonas de temperatura
- Partida remota do motor, travar/destravar e localização
- Rotinas recorrentes — partida programada, climatização e lembretes
- Central de notificações
Todos os dados da Sprint 1 são mockados via seed do banco — não há integração real com sistemas Ford.
Navegação na tela inicial · Agendamento de revisão na concessionária
- Java 21 + Spring Boot 3.3.5
- Spring Security com autenticação JWT (jjwt)
- Spring Data JPA + Hibernate
- PostgreSQL 16 rodando em container Docker (banco efêmero, recriado a cada
docker-compose up) - Flyway para migrations versionadas
- springdoc-openapi para documentação Swagger
- JUnit 5 + Mockito para testes
- Maven para build
- React Native com Expo SDK 54
- Expo Router (file-based routing)
- TypeScript em modo strict
- expo-secure-store para armazenamento do JWT
- axios com interceptor para autenticação automática
- Jest + @testing-library/react-native para testes
- Docker + Docker Compose para ambiente local — sobe banco + backend com um comando
- GitHub Actions para CI (testes backend + Jest + TypeScript no mobile)
.
├── backend/ Java Spring Boot
│ ├── src/main/java/br/com/fordapp/
│ │ ├── controller/ endpoints REST
│ │ ├── service/ regras de negócio
│ │ ├── repository/ acesso ao banco
│ │ ├── model/ entidades JPA
│ │ ├── dto/ contratos de entrada e saída
│ │ ├── security/ configuração de JWT e Spring Security
│ │ └── exception/ tratamento global de erros
│ ├── src/main/resources/
│ │ ├── application.yml config principal
│ │ ├── application-test.yml config para testes (H2)
│ │ └── db/migration/ scripts Flyway versionados
│ ├── pom.xml
│ └── Dockerfile
│
├── mobile/ React Native + Expo
│ ├── app/ rotas (Expo Router)
│ │ ├── (tabs)/ navegação principal
│ │ ├── _layout.tsx layout raiz com proteção de rotas
│ │ └── login.tsx tela de login
│ ├── components/ componentes reutilizáveis
│ ├── contexts/ estado global (autenticação)
│ ├── hooks/ hooks customizados
│ ├── services/ chamadas à API
│ ├── constants/ design tokens
│ ├── types/ tipos TypeScript compartilhados
│ └── __tests__/ testes Jest
│
├── docs/
│ ├── adr/ Architecture Decision Records
│ └── screenshots/ imagens usadas no README
│
├── .github/workflows/ci.yml pipeline de CI
├── docker-compose.yml orquestração local
└── .env.example modelo de variáveis (apenas JWT_SECRET)
| Decisão | Justificativa |
|---|---|
| Java 21 + Spring Boot 3 | Exigência da disciplina de Java/Web Services; Java 21 é a versão LTS atual |
| React Native + Expo | Exigência da disciplina de Mobile; Expo simplifica build e execução |
| PostgreSQL 16 | Banco relacional maduro, com suporte sólido a JDBC e Spring Boot |
| Flyway | Versionamento de schema e seed, exigido pela disciplina |
| Autenticação JWT | Token stateless, adequado a app mobile; parte da nota de Cybersecurity |
| Monorepo | Backend e mobile na mesma raiz — facilita o desenvolvimento integrado |
| Sem Lombok | Construtores e getters/setters explícitos, por preferência da equipe |
| Dados mockados via seed | Não há dataset real disponível na Sprint 1 |
Monorepo com backend/ (Spring Boot) e mobile/ (React Native) independentes — comunicam-se apenas pelo contrato REST, sem acoplamento de código. Detalhe em Estrutura de pastas.
O backend segue arquitetura em camadas: controller → service → repository, com DTOs no contrato externo e entidades nunca expostas. O mobile usa Expo Router (rotas por arquivo), com services/ isolando as chamadas à API.
Na Sprint 1 não há integração com sistemas externos. O app mobile consome a API REST do próprio projeto via HTTP/JSON, autenticando com JWT. Todos os dados vêm do seed do Flyway. Integrações reais com sistemas Ford ficam para sprints futuras.
Os diagramas de componentes, camadas e fluxo de requisição estão em docs/arquitetura.md. Cada decisão arquitetural relevante está registrada como ADR em docs/adr/ — entre elas a autenticação JWT, a escolha do PostgreSQL, o uso de Flyway e a organização em monorepo.
- Git
- Docker Desktop — usado tanto no caminho rápido quanto para subir o banco em desenvolvimento
- Node.js 20+ com npm (para o mobile)
- Expo Go instalado no celular (Android ou iOS) ou simulador iOS / emulador Android configurado
Apenas se for rodar o backend fora do Docker:
- Java 21 (Temurin recomendado —
sdk install java 21-temse usar SDKMAN) - O Maven já vem incluído via wrapper
./mvnw, não precisa instalar
Roda o projeto inteiro (backend + mobile). Vale para qualquer rede Wi-Fi, em qualquer máquina — não há IP para configurar manualmente.
Descompacte e entre na pasta:
unzip ford-connect-completo-*.zip
cd ford-connect-completo-*O .env já vem pronto dentro do zip. Pule para o passo 2.
git clone https://github.com/Carti011/Ford-Connect.git
cd Ford-Connect
# crie o .env a partir do exemplo
cp .env.example .env
# preencha o JWT_SECRET (qualquer string com 64+ caracteres)
# em macOS / Linux:
echo "JWT_SECRET=$(openssl rand -hex 64)" >> .env
echo "JWT_EXPIRATION_MS=86400000" >> .envdocker-compose up -dSobe PostgreSQL e o backend Java de uma vez. Na primeira execução o build da imagem do backend leva alguns minutos. Quando terminar, o Swagger fica em http://localhost:8080/swagger-ui.html.
Em outro terminal, ainda na raiz do projeto:
cd mobile
npm install
npx expo start --clearEscaneie o QR code com o Expo Go no celular (mesma rede Wi-Fi do computador) ou aperte i para simulador iOS / a para emulador Android.
O app descobre automaticamente o endereço do backend a partir do servidor de dev do Expo. Sem precisar de IP, sem precisar de
.env.local. Basta o celular e o computador estarem na mesma rede.
O Flyway popula o banco com dados mockados na primeira execução. Para autenticar via app ou Swagger:
- email:
joao@fordconnect.com - senha:
ford@123
Outros usuários estão em backend/src/main/resources/db/migration/V2__seed_dados_mockados.sql.
Pra evitar o problema clássico de "funciona na minha máquina mas não na sua", a baseURL da API é resolvida em três níveis, nesta ordem:
EXPO_PUBLIC_API_URLdefinido emmobile/.env.local— tem prioridade absoluta. Use quando quiser apontar para um backend remoto, um deploy de produção, um túnel ngrok, etc.- Servidor de dev do Expo — quando você roda
npx expo start, o Expo já sabe o IP da máquina na rede. O app extrai esse IP e montahttp://<ip>:8080. Funciona em qualquer rede, sem configuração. - Fallback local —
http://localhost:8080no simulador iOS / web ehttp://10.0.2.2:8080no emulador Android.
Lógica implementada em mobile/services/api.ts. Existe um mobile/.env.local.example no repositório para referência.
Cenário para quem vai modificar código. Backend pelo Maven com hot reload, banco em Docker.
# subir só o banco
docker-compose up -d postgres
# em outro terminal: rodar o backend
cd backend
./mvnw spring-boot:runComo atalho, existe um script backend/dev.sh que exporta as variáveis de ambiente e sobe o backend de uma vez. O arquivo é gitignored — cada dev mantém o seu localmente. Para criar o seu na primeira vez:
cp backend/dev.sh.example backend/dev.sh
chmod +x backend/dev.sh
bash backend/dev.shcd mobile
npm install
npx expo start --clearPronto. Não precisa criar .env.local, não precisa configurar IP. O QR code aparece no terminal; escaneie no celular com o Expo Go ou pressione i / a para simulador / emulador.
Se em algum cenário você precisar forçar uma URL específica (apontar para um backend remoto, etc.), copie o exemplo e edite:
cp mobile/.env.local.example mobile/.env.local
# edite mobile/.env.local definindo EXPO_PUBLIC_API_URLO fluxo padrão do projeto é rodar tudo localmente em Docker — banco, backend e mobile, todos em uma única máquina. Essa é a configuração suportada e a que a documentação principal cobre. Para casos específicos onde alguém quer ir além disso, esta seção descreve o que é possível.
Útil para times que queiram compartilhar uma base de dados ou para integrar com um banco já existente.
Em vez de usar docker-compose up -d, rode o backend direto via Maven com variáveis apontando para o seu banco:
cd backend
export PGHOST=seu-host.exemplo.com
export PGDATABASE=seu_banco
export PGUSER=seu_usuario
export PGPASSWORD=sua_senha
export PGSSLMODE=require # use 'disable' se o banco não tiver SSL
export JWT_SECRET=$(openssl rand -hex 64)
export JWT_EXPIRATION_MS=86400000
./mvnw spring-boot:runA migração de schema é feita pelo Flyway automaticamente na primeira inicialização — o banco precisa existir mas pode estar vazio. As tabelas e os dados de seed serão criados a partir dos scripts em backend/src/main/resources/db/migration/.
Para tornar isso recorrente, copie o backend/dev.sh.example para backend/dev.sh (gitignored) e ajuste os valores:
cp backend/dev.sh.example backend/dev.sh
chmod +x backend/dev.sh
# edite backend/dev.sh com os valores do seu banco
bash backend/dev.shPor padrão, o app descobre o backend automaticamente na rede local. Para apontar para um backend específico (deploy em produção, túnel ngrok, backend em outra máquina), defina a URL no mobile/.env.local:
cp mobile/.env.local.example mobile/.env.localEdite mobile/.env.local:
EXPO_PUBLIC_API_URL=https://seu-backend.exemplo.comReinicie o Expo (Ctrl+C e npx expo start --clear) para o app pegar a nova URL.
O backend/Dockerfile é multi-stage e está pronto para deploy em qualquer plataforma que aceite Docker.
Roteiro geral:
- Conecte o repositório no painel da plataforma escolhida
- Aponte o build context para
/backend - Configure as variáveis de ambiente exigidas (mesmas do dev.sh):
PGHOST,PGDATABASE,PGUSER,PGPASSWORD,PGSSLMODEJWT_SECRET(gere comopenssl rand -hex 64),JWT_EXPIRATION_MS
- O banco precisa estar acessível pela URL pública da plataforma — use Neon, Supabase, RDS ou outro PostgreSQL gerenciado
- Depois do deploy, aponte o app para a URL gerada usando
EXPO_PUBLIC_API_URL(ver seção anterior)
A configuração CORS em backend/src/main/java/br/com/fordapp/security/SecurityConfig.java precisa receber a origem do front se o app for acessado via navegador (expo start --web). Para uso nativo no celular (Expo Go ou build nativo), CORS é irrelevante.
As credenciais do banco são fixas dentro do docker-compose.yml — banco local efêmero, sem segredos. O único valor que precisa vir do .env é o JWT_SECRET.
| Variável | Obrigatória | Descrição |
|---|---|---|
JWT_SECRET |
sim | Segredo HS256 do JWT — mínimo 64 caracteres. Gere com openssl rand -hex 64 |
JWT_EXPIRATION_MS |
não | Expiração do token em ms. Default: 86400000 (24h) |
Se você roda o backend fora do Docker (apontando para um banco arbitrário — postgres local em outra máquina, Neon, RDS), passa as variáveis exportadas no dev.sh antes de chamar ./mvnw:
| Variável | Obrigatória | Descrição |
|---|---|---|
PGHOST |
sim | Host do PostgreSQL |
PGDATABASE |
sim | Nome do banco |
PGUSER |
sim | Usuário do banco |
PGPASSWORD |
sim | Senha do banco |
PGSSLMODE |
não | disable em local, require para Neon. Default: disable |
JWT_SECRET |
sim | Mesmo significado da tabela acima |
JWT_EXPIRATION_MS |
não | Idem |
| Variável | Obrigatória | Descrição |
|---|---|---|
EXPO_PUBLIC_API_URL |
não | URL base da API. Quando ausente, o app descobre o endereço do backend automaticamente. Defina apenas para forçar uma URL específica (deploy remoto, túnel ngrok, etc.) |
O prefixo EXPO_PUBLIC_ é necessário para que a variável seja exposta ao bundle do app.
Base URL local: http://localhost:8080
Todas as rotas exigem Authorization: Bearer <token>, exceto as marcadas como Pública.
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| POST | /api/autenticacao/login |
Pública | Autentica com email e senha → JWT + veículo |
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| GET | /api/veiculos/{id} |
JWT | Dados do veículo, vitais (pneus, óleo, bateria, freios, correia, motor), score de saúde e garantia |
| PATCH | /api/veiculos/{id}/preferencias |
JWT | Atualiza preferências do veículo (parcial) |
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| GET | /api/veiculos/{id}/recomendacoes |
JWT | Recomendações de manutenção pendentes |
| GET | /api/veiculos/{id}/manutencoes |
JWT | Histórico de manutenções |
| GET | /api/concessionarias |
JWT | Concessionárias ordenadas por distância |
| POST | /api/veiculos/{id}/agendamentos-servico |
JWT | Cria solicitação de agendamento de revisão |
| GET | /api/veiculos/{id}/agendamentos-servico |
JWT | Lista agendamentos de serviço do veículo |
Partida do motor, climatização programada e lembretes recorrentes.
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| GET | /api/veiculos/{id}/agendamentos |
JWT | Lista rotinas recorrentes |
| POST | /api/veiculos/{id}/agendamentos |
JWT | Cria uma rotina |
| PATCH | /api/agendamentos/{id} |
JWT | Atualiza uma rotina (parcial) |
| PATCH | /api/agendamentos/{id}/ativo |
JWT | Liga/desliga uma rotina |
| DELETE | /api/agendamentos/{id} |
JWT | Remove uma rotina |
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| GET | /api/veiculos/{id}/climatizacao |
JWT | Estado atual da climatização |
| PATCH | /api/veiculos/{id}/climatizacao |
JWT | Atualiza o estado da climatização |
| PATCH | /api/veiculos/{id}/climatizacao/zonas/{idZona} |
JWT | Atualiza uma zona de temperatura |
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| POST | /api/demo/resetar |
Pública | Reseta os agendamentos de serviço ao estado da seed |
Com o backend rodando, a documentação Swagger fica em:
- Swagger UI: http://localhost:8080/swagger-ui.html
- OpenAPI JSON: http://localhost:8080/api-docs
cd backend
./mvnw test -Dspring.profiles.active=testO perfil test usa H2 em memória — não requer PostgreSQL nem nenhuma variável de ambiente configurada.
cd mobile
npm testOutras variantes:
npm test -- --watch # modo watch para desenvolvimento
npm test -- --coverage # gera relatório de cobertura
npm test -- --ci # modo CI (sem watch, mais estrito)# Verificar tipos TypeScript no mobile sem compilar
cd mobile && npx tsc --noEmit
# Subir mobile em modo túnel (útil quando celular e PC não estão na mesma rede)
cd mobile && npx expo start --tunnel
# Ver logs do backend no Docker
docker-compose logs -f backend
# Ver logs do banco no Docker
docker-compose logs -f postgres
# Resetar tudo (apaga volume do banco — começa do zero, Flyway re-popula)
docker-compose down -v && docker-compose up -d
# Conectar no banco via psql dentro do container
docker exec -it ford_app_db psql -U ford -d ford_mobile
# Gerar um JWT_SECRET aleatório (256 bits em hex)
openssl rand -hex 64docs/arquitetura.md— diagramas de arquitetura (componentes, camadas e fluxo de requisição) em Mermaiddocs/adr/— todas as decisões arquiteturais relevantes registradas como ADRs numeradasdocs/handoff/— handoffs entre sessões de trabalho (excluídos do git por padrão; servem como contexto de quem está retomando o projeto)backend/src/main/resources/db/migration/— schema versionado e seed de dados
Com mais tempo, o grupo implementaria:
- Múltiplos veículos por usuário — hoje cada usuário tem um único veículo
- Cadastro de usuário pelo app — hoje os usuários vêm do seed do banco
- Notificações push — lembretes de revisão via Expo Notifications
- Agendamento integrado de verdade — conexão com o sistema de agendamento das concessionárias, em vez de apenas registrar a solicitação
- Mapa de concessionárias — localização real em vez de distância fixa
- Assistente virtual com IA — tirar dúvidas sobre o veículo e a manutenção
- Cálculo dinâmico do score de saúde — hoje o score vem fixo do seed
- Refresh token — renovar a sessão sem novo login
- Cobertura de testes no frontend além do escopo restrito atual
| Métrica | Valor |
|---|---|
| Endpoints REST | 17 |
| Telas mobile | 13 |
| Testes Jest (mobile) | 127 |
| Testes JUnit (backend) | 96 |
| Migrations Flyway | 21 |
| ADRs documentados | 41 |
- Cybersecurity embutida — JWT com expiração configurável, validação de inputs com Bean Validation, CORS restrito, rate limiting por IP, respostas de erro sem stack trace ou detalhes internos
- Arquitetura em camadas — separação rígida de
controller → service → repository, DTOs no contrato externo, entidades nunca expostas, lógica de negócio fora do controller - TDD no backend — testes escritos antes da implementação, cobrindo controllers, services e o handler global de erros
- CI completo bloqueando merge — pipeline GitHub Actions roda testes do backend (JUnit + H2 em memória), Jest no mobile e verificação de tipos TypeScript. Branch protection na
mainexige todos os checks verdes - Histórico de decisões versionado — toda decisão arquitetural relevante registrada como ADR em
docs/adr/, permitindo entender o porquê de cada escolha mesmo meses depois




