Plataforma integrada para acompanhamento de criancas e gestantes do programa Pequenos Cariocas da Prefeitura do Rio de Janeiro, reunindo informacoes de saude, educacao e assistencia social em um unico painel de monitoramento.
O PIC (Pequenos Cariocas) e uma aplicacao fullstack que permite:
- Dashboard Gerencial: Visualizar indicadores agregados de participantes do programa com metricas de regularidade por secretaria (Saude, Educacao, Assistencia Social)
- Monitoramento de Protocolos: Acompanhar o cumprimento de protocolos obrigatorios como vacinacao, frequencia escolar, atualizacao de CadUnico, entre outros
- Busca Individual: Pesquisar participantes por nome ou CPF com filtros avancados e multi-selecao
- Analise Temporal: Graficos de evolucao do programa, tempo medio de irregularidade e taxa de resolucao de alertas
- Gestao de Acessos: Sistema de governanca com permissoes por unidade (CRAS, Escolas, Clinicas, AP, CRE, CAS)
- Total de participantes ativos no programa
- Percentual de participantes regulares vs irregulares
- Breakdown por secretaria (SMS, SME, SMAS)
- Regularidade por protocolo individual (CadUnico, Creche, Vacinacao, etc.)
- Filtros multi-selecao com logica AND (ex: ver quem tem CadUnico E Creche irregulares)
- Cascata inteligente de filtros
- Evolucao temporal do resultado do programa
- Distribuicao por safra de ingresso (cohort)
- Motivos de saida do programa
- Tempo medio de irregularidade por secretaria
- Histograma de distribuicao por faixas de tempo
- Taxa de resolucao mensal de alertas
- Python 3.13 - Linguagem principal
- FastAPI - Framework web async de alta performance
- Polars 1.35+ - Processamento de dados (substitui Pandas para maior performance)
- Google BigQuery - Data warehouse para armazenamento
- Redis 7+ - Cache distribuido
- PyJWT - Autenticacao via JWT/OAuth2 (gov.br)
- Next.js 16 - Framework React com App Router
- React 19 - UI Library
- shadcn/ui - Biblioteca de componentes (Radix UI)
- TypeScript 5 - Type safety
- Tailwind CSS 4 - Estilizacao utility-first
- TanStack Query 5 - Gerenciamento de estado servidor
- Recharts 3 - Graficos e visualizacoes
- react-window - Virtualizacao de listas longas
- NextAuth.js 5 - Autenticacao OAuth2
app-pic/
βββ src/
β βββ api/ # Endpoints da API
β β βββ v1/
β β βββ admin.py # Endpoints de governanca/admin
β β βββ dashboard.py # Metricas agregadas do dashboard
β β βββ participants.py # Listagem de participantes
β β βββ auth.py # Autenticacao
β β βββ queries.py # Queries SQL BigQuery
β β βββ schemas.py # Schemas Pydantic
β βββ config/
β β βββ env.py # Variaveis de ambiente
β β βββ .env # Configuracoes locais (gitignored)
β βββ core/
β β βββ middlewares/ # Middlewares FastAPI
β β βββ security/ # JWT, permissoes, governanca
β βββ frontend/ # Aplicacao Next.js
β β βββ app/
β β β βββ components/ # Componentes React
β β β β βββ ui/ # Componentes base (shadcn)
β β β β βββ OverviewTab.tsx # Aba de visao geral
β β β β βββ ProfessionalTab.tsx # Aba de busca individual
β β β β βββ FilterCard.tsx # Card de filtros
β β β β βββ ...
β β β βββ services/ # Servicos de API
β β β βββ types.ts # Tipos TypeScript
β β β βββ login/ # Pagina de login
β β β βββ admin/ # Pagina de administracao
β β βββ package.json
β βββ utils/
β β βββ bigquery.py # Cliente BigQuery com Arrow
β β βββ cache_manager.py # Sistema de cache L1/L2
β β βββ data_manager.py # Pipeline de dados e filtros
β β βββ data_manager_config.py # Configuracoes do DataManager
β β βββ log.py # Configuracao de logs (Loguru)
β βββ main.py # Entrypoint FastAPI
βββ scripts/
β βββ bootstrap_super_admin.py # Script para criar primeiro admin
βββ docker-compose.yml
βββ Dockerfile
βββ pyproject.toml # Dependencias Python (uv)
βββ justfile # Comandos de desenvolvimento
βββ README.md
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Request β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β L1 - Memory Cache (InMemoryCache) β
β β’ Thread-safe, TTL-based β
β β’ Instant access (~0.001s) β
β β’ Local ao processo β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MISS
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β L2 - Redis Cache β
β β’ Pickle + LZ4 compression β
β β’ Compartilhado entre processos β
β β’ TTL configuravel (default 5min) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MISS
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BigQuery (via Arrow) β
β β’ Query SQL completa β
β β’ Zero-copy transfer para Polars β
β β’ ~3-5s por query β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β fetch_filter_paginate() β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β 1. GET DATASET ββββΆβ 2. GOVERNANCE ββββΆβ 3. APPLY FILTERS β
β (Cache/BQ) β β FILTERS β β (Polars) β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β 4. APPLY SEARCH ββββΆβ 5. SORT ββββΆβ 6. FILTER OPTIONSβ
β (Nome/CPF) β β (Coluna) β β (Cascata) β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββ
β 7. PAGINATE β
β (Slice) β
ββββββββββββββββββββ
O sistema suporta filtros avancados com:
- Multi-selecao: Selecionar multiplos valores para um filtro
- Logica AND: Quando multiplos protocolos sao selecionados com um status, apenas participantes que tenham TODOS os protocolos com aquele status sao exibidos
- Cascata inteligente: Opcoes de filtro sao recalculadas baseadas nos filtros ativos, excluindo o proprio filtro para manter suas opcoes disponiveis
- Filtros de array: Suporte a filtrar por campos dentro de arrays de structs (ex: protocolo_listagem.descricao)
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β Login ββββββΆβ Keycloak ββββββΆβ gov.br ββββββΆβ Callback β
β Page β β (RMI) β β OAuth2 β β /api/ β
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JWT Token (preferred_username = CPF) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Governance Table (BigQuery) β
β β’ Verifica se CPF esta cadastrado β
β β’ Carrega permissoes (IDs autorizados) β
β β’ Determina nivel: user/admin/super_admin β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
O sistema possui 3 niveis de acesso:
| Nivel | Descricao |
|---|---|
| user | Ve apenas dados das unidades atribuidas (CRAS, Escolas, Clinicas, AP, CRE, CAS) |
| admin | Pode gerenciar usuarios com subset de seus IDs |
| super_admin | Acesso total, pode gerenciar qualquer usuario |
Filtros de governanca sao aplicados em memoria apos buscar do cache, garantindo que cada usuario veja apenas seus dados autorizados sem afetar o cache compartilhado.
Todos os endpoints requerem header Authorization: Bearer <token>.
| Metodo | Endpoint | Descricao |
|---|---|---|
| GET | /health |
Health check |
| GET | /api/v1/dashboard |
Metricas agregadas do dashboard |
| GET | /api/v1/participants |
Lista participantes com filtros e paginacao |
| GET | /api/v1/admin/me |
Informacoes do usuario atual |
| GET | /api/v1/admin/users |
Lista usuarios (apenas admin) |
| PUT | /api/v1/admin/users/{cpf} |
Cria/atualiza usuario (UPSERT) |
| DELETE | /api/v1/admin/users/{cpf} |
Soft-delete de usuario |
| GET | /api/v1/admin/available-ids |
IDs disponiveis para atribuicao |
| Parametro | Tipo | Descricao |
|---|---|---|
page |
int | Pagina atual (1-indexed) |
page_size |
int | Itens por pagina (1-10000) |
search |
string | Busca por nome ou CPF |
bypass_cache |
bool | Forca refresh do cache |
sort_by |
string | Coluna para ordenacao |
sort_order |
asc/desc | Direcao da ordenacao |
grupo, status, bairro, etc. |
string | Filtros simples |
protocolo_descricao |
string | Filtro de protocolo (multi-selecao com virgula) |
protocolo_status |
string | Filtro de status do protocolo |
Crie um arquivo src/config/.env com:
# BigQuery
GCP_SERVICE_ACCOUNT_CREDENTIALS={"type": "service_account", ...}
BQ_PROJECT_ID=rj-pic-dev
BQ_DATASET_ID=app_pequenos_cariocas
BQ_TABLE_ID_PARTICIPANTS_LISTAGEM=endpoint_participante_listagem
BQ_TABLE_ID_DASHBOARD=endpoint_participante_visao_geral
BQ_TABLE_ID_DATA_ACCESS=controle_acesso
# OAuth2 (Keycloak/RMI)
RMI_ISSUER=https://seu-keycloak.com/realms/seu-realm
RMI_AUDIENCE=seu-client-id
# Cache
REDIS_URL=redis://localhost:6379
CACHE_TTL_SECONDS=300Crie um arquivo src/frontend/.env.local com:
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=seu-secret-aleatorio-32-chars
NEXT_PUBLIC_API_URL=http://localhost:8089
RMI_ISSUER=https://seu-keycloak.com/realms/seu-realm
RMI_CLIENT_ID=seu-client-id
RMI_CLIENT_SECRET=seu-client-secret- Python 3.13+
- Node.js 20+
- uv (gerenciador de pacotes Python)
- just (command runner)
- Redis (ou Docker para subir localmente)
# Clonar repositorio
git clone https://github.com/prefeitura-rio/app-pic.git
cd app-pic
# Instalar dependencias Python
uv sync
# Instalar dependencias Frontend
cd src/frontend && npm install && cd ../..
# Subir Redis (se nao tiver rodando)
docker run -d -p 6379:6379 redis:7-alpineO backend usa um Postgres novo (identidade + espelho local do access_policy do
data-proxy β ver plan.md secao 7) na instancia rj-iplanrio-dia:us-central1:postgres.
Localmente, conecte via Cloud SQL Auth Proxy rodando no seu proprio laptop
(autentica com seu login gcloud, sem depender de acesso ao cluster/Kubernetes).
Instalar (escolha o comando do seu SO β veja mais opcoes/versoes em releases):
# macOS
brew install cloud-sql-proxy# Linux (amd64)
URL="https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.25.3"
curl "$URL/cloud-sql-proxy.linux.amd64" -o cloud-sql-proxy
chmod +x cloud-sql-proxy
sudo mv cloud-sql-proxy /usr/local/bin/cloud-sql-proxy# Windows (x64, PowerShell)
curl.exe -o cloud-sql-proxy.exe https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.25.3/cloud-sql-proxy.x64.exeRodar (deixe em um terminal separado enquanto usa a API):
# macOS / Linux
cloud-sql-proxy --gcloud-auth --port 5432 rj-iplanrio-dia:us-central1:postgres# Windows
.\cloud-sql-proxy.exe --gcloud-auth --port 5432 rj-iplanrio-dia:us-central1:postgresRequer roles/cloudsql.client no projeto rj-iplanrio-dia pra sua conta gcloud.
Com o proxy rodando, src/config/.env ja aponta pra ele
(APP_PIC_PG_HOST=localhost, APP_PIC_PG_PORT=5432).
# Listar todos os comandos disponiveis
just
# Rodar backend (porta 8089)
just run-api
# Rodar frontend (porta 3000)
just run-frontend
# Rodar ambos em paralelo
just dev
# Linting
just lint # Python + Frontend
just lint-python # Apenas Python
just lint-frontend # Apenas Frontend
# Formatacao
just fmt # Python + Frontend
just fix # Auto-fix Python (ruff)Para criar o primeiro super admin:
-
Edite
scripts/bootstrap_super_admin.pye configure o CPF:SUPER_ADMIN_CPF = "12345678900" # CPF do primeiro admin
-
Execute o script:
uv run python scripts/bootstrap_super_admin.py
-
Faca login com o CPF configurado via gov.br.
# Build e start
docker-compose up -d --build
# Logs
docker-compose logs -f
# Stop
docker-compose downEm producao, configure as variaveis via secrets do Kubernetes ou sistema de CI/CD. Nunca commite credenciais no repositorio.
- Polars ao inves de Pandas - 10x mais rapido para operacoes de DataFrame
- Cache L1/L2 - Evita deserializacao repetida e queries ao BigQuery
- Filter options pre-computadas - Calculadas durante cache write (instant em cache hit)
- Arrow para BigQuery - Transferencia zero-copy de dados
- Virtualizacao de listas - react-window para selects com muitas opcoes
- React.memo e useCallback - Evita re-renders desnecessarios no frontend
- Filtros combinados de array - Explode + filter em uma unica operacao
| Operacao | Cache Hit | Cache Miss |
|---|---|---|
| /dashboard | ~0.1s | ~5s |
| /participants (paginado) | ~0.3s | ~5s |
| Filtro cascata | ~0.05s | N/A |
| Multi-select com AND | ~0.1s | N/A |
O botao "Atualizar" no frontend envia bypass_cache=true que:
- Ignora cache L1 (memoria) e L2 (Redis)
- Busca dados frescos do BigQuery
- Substitui o cache antigo
Verifique se:
- CPF esta cadastrado na tabela de governanca (
controle_acesso) - Usuario esta marcado como
active=true - Cookies estao sendo aceitos pelo navegador
NEXTAUTH_SECRETesta configurado corretamente
- Verifique logs do backend:
logs/api_*.log - Confirme que o CPF no JWT (
preferred_username) bate com a tabela de governanca - Para admins segmentados, verifique se possui IDs suficientes atribuidos
- Verifique se a tabela
BQ_TABLE_ID_DASHBOARDesta correta - Limpe o cache com
bypass_cache=true - Verifique os logs para erros de query
- Crie uma branch a partir de
staging - Faca suas alteracoes
- Rode
just linte corrija problemas - Abra um PR para
staging
Projeto interno da Prefeitura do Rio de Janeiro - Escritorio Municipal de Dados.