O Formaê é um assistente acadêmico para estudantes da UFBA, inspirado no MeForma original e no trabalho de João Pedro Rodrigues Cerqueira, mas com uma arquitetura nova: local-first, sem backend com dados sensíveis, com PWA estática, extensão de navegador e núcleo compartilhado em Rust/WASM.
Hoje o repositório já entrega:
- PWA em React + Vite publicada no GitHub Pages
- planner visual local com busca, filtros, dark mode, modo compacto, drag and drop e mapa de dependências
- importação manual de texto do SIGAA
- sincronização automática local com o SIGAA via extensão MV3
- vault local cifrado no navegador
- endurecimento do vault com passkey, política explícita de derivação e preferência por WebAuthn PRF quando disponível
- parser de horários UFBA 2025 em Rust/WASM
- catálogo público seed versionado
- discovery público versionado de portais e páginas de currículo oficiais
Endereço público atual:
https://mentorzx.github.io/formae/
Hoje existem dois jeitos bem diferentes de interagir com o projeto:
- uso comum: abrir a PWA publicada, instalar a extensão e importar localmente do SIGAA
- desenvolvimento: clonar o repositório, instalar Node/Rust/pnpm e rodar tudo localmente
Se você só quer usar o Formaê, ignore pnpm, Rust, wasm-pack e qualquer comando de terminal. Isso é só para quem vai desenvolver o projeto.
O fluxo de usuário final está abaixo.
Este README deve ser atualizado sempre que uma mudança no produto afetar:
- instalação
- configuração
- fluxo de uso
- comandos de desenvolvimento
- limitações conhecidas
Ou seja: se o jeito de usar o Formaê mudar, este passo a passo também precisa mudar no mesmo commit ou na mesma rodada.
Esse é o caminho certo para quem abriu o GitHub agora e só quer usar o produto.
https://mentorzx.github.io/formae/
No estado atual, a extensão ainda não está publicada na Chrome Web Store nem no AMO. Então a instalação continua manual, via artefatos do repositório:
- releases:
https://github.com/Mentorzx/formae/releases/latest
Hoje os artefatos publicados são:
.zippara Chrome/Chromium.xpipara Firefox
Quando a extensao estiver publicada em loja, este README deve trocar esse passo para o fluxo direto de Chrome Web Store e AMO.
Na popup da extensão:
- informe CPF/usuário do SIGAA
- informe a senha
- clique em
Salvar em memória
Na rota Importação:
- clique em
Importar automaticamente - a extensão lê localmente as views do SIGAA
- o snapshot fica salvo só no navegador
Visão GeralePlanejadorpassam a refletir esse estado
Hoje ainda faltam duas coisas para o fluxo ficar realmente popular e trivial:
- publicar a extensão em loja oficial
- reduzir ainda mais o atrito da instalação inicial
Então o fluxo de uso já existe, mas ainda está em estágio de preview avançado, não de produto “clicou e usou” para qualquer pessoa.
O repositório agora já deixa pronta a parte operacional para publicacao:
- pagina publica de privacidade:
https://mentorzx.github.io/formae/#/privacidade - pagina publica de suporte:
https://mentorzx.github.io/formae/#/suporte - metadata do AMO em
apps/extension/store/amo-metadata.json - texto base da Chrome Web Store em
apps/extension/store/chrome-listing.pt-BR.md - checklist de readiness em
apps/extension/store/store-readiness-checklist.md - script de upload e publish para Chrome Web Store API
- script de assinatura/submissao para AMO
- workflow manual
Publish Extension Stores - guia objetivo de publicacao do Chrome em
apps/extension/store/chrome-publicacao.pt-BR.md
O que ainda depende do dono da conta:
- conta de publisher da Chrome Web Store
- conta AMO
- segredos de API
- preencher listing e privacidade no dashboard do Chrome
- revisao das lojas
As instruções abaixo são para quem vai editar código, rodar testes ou contribuir com o projeto.
gh repo clone Mentorzx/formae
cd formaeSe você não usa gh, pode usar:
git clone https://github.com/Mentorzx/formae.git
cd formaeVocê precisa ter instalado localmente:
- Node.js
22+ corepackpnpm 10+- Rust stable
wasm-pack
No Linux/macOS, o caminho feliz fica assim:
corepack enable
corepack prepare pnpm@10.18.3 --activate
rustup default stable
cargo install wasm-packFoi exatamente o erro que você encontrou. Nesse caso, o ambiente ainda não tem pnpm disponível no PATH.
Faça isto:
corepack enable
corepack prepare pnpm@10.18.3 --activate
pnpm --versionSe o corepack também não existir, então o problema vem antes: o Node.js da máquina não está instalado corretamente ou não está no PATH.
Resumo direto:
- usuário final não precisa de
pnpm - desenvolvedor precisa de Node + Corepack + pnpm funcionando antes de rodar qualquer comando do monorepo
Na raiz do projeto:
pnpm installO app web usa o núcleo Rust/WASM. Antes do primeiro uso local:
pnpm prepare:wasmpnpm dev:webDepois abra:
http://localhost:4173/#/
Para maintainer, nao para usuario final.
- Registrar conta de developer.
- Ativar verificacao em duas etapas na conta Google.
- Habilitar a Chrome Web Store API no Google Cloud.
- Criar OAuth consent screen e OAuth client.
- Gerar refresh token.
- Criar o item no dashboard e preencher listing + privacy.
- Configurar:
export CWS_CLIENT_ID=...
export CWS_CLIENT_SECRET=...
export CWS_REFRESH_TOKEN=...
export CWS_PUBLISHER_ID=...
export CWS_EXTENSION_ID=...- Rodar upload:
pnpm publish:chrome-webstore- Para submeter para review/publicacao:
pnpm publish:chrome-webstore -- --publish- Criar conta no AMO.
- Emitir JWT issuer + secret.
- Revisar
apps/extension/store/amo-metadata.json. - Configurar:
export AMO_JWT_ISSUER=...
export AMO_JWT_SECRET=...
export AMO_CHANNEL=listed- Rodar assinatura/submissao:
pnpm publish:firefox-amoDepois de abrir a PWA, o fluxo principal é:
Visão GeralMostra o estado local do snapshot salvo no navegador.PlanejadorMostra a grade viva, com dependências, drag and drop, filtros e simulador local de IRA.CatálogoMostra os seeds e fontes públicas que o app conhece.ImportaçãoÉ a tela para importar manualmente ou disparar a sincronização automática local com a extensão.ArquiteturaExplica as fronteiras técnicas e decisões do projeto.
Se você quer testar o Formaê sem extensão:
- Abra
Importação - Cole texto copiado do SIGAA
- O app detecta códigos de componente e horários
- O parser Rust/WASM normaliza horários como
35N12 - Salve o snapshot local no navegador
- Volte para
Visão GeralouPlanejador
O que isso já faz:
- detectar componentes
- detectar horários
- associar com o catálogo seed
- gerar um
StudentSnapshotlocal - alimentar visão geral e planner
Hoje o sync automático funciona localmente via extensão MV3, sem enviar suas credenciais para servidor do Formaê.
pnpm dev:webNo Chrome ou Chromium:
- Abra
chrome://extensions - Ative
Modo do desenvolvedor - Clique em
Carregar sem compactação - Selecione a pasta:
apps/extension
Se você quiser gerar artefatos de distribuição locais:
pnpm package:extensionIsso gera:
- um
.zippara Chrome emdist/releases - um
.xpipara Firefox emdist/releases - checksums e manifesto de release determinístico
- smoke runtime local para popup, background e content script nos dois targets
Use:
http://localhost:4173/#/importacao
No estado atual:
- a popup da extensão arma a janela curta de aprovação do sync
- a extensão usa as credenciais só em memória
- a extensão lê
Minhas TurmaseMinhas Notaslocalmente no SIGAA - o snapshot automático é salvo localmente no vault do navegador
Visão GeralePlanejadorpassam a refletir esse estado local
O Planejador é hoje a área mais forte da interface.
Você pode:
- buscar por código ou nome
- ocultar concluídas
- mostrar só componentes liberadas agora
- destacar componentes com horário local
- destacar componentes em revisão
- passar o mouse para ver cadeia de pré-requisitos e liberações
- clicar para fixar uma disciplina como foco
- arrastar componentes planejáveis entre períodos
- renomear colunas para algo como
2026.2,2027.1etc. - alternar entre modo detalhado e compacto
- alternar entre modo claro e escuro
- fazer uma projeção local de IRA
Importante:
- o planner é derivado do snapshot local salvo no navegador
- ele não é uma confirmação oficial do SIGAA em tempo real
- quando a grade seed ainda estiver rasa ou ambígua, trate a leitura como aproximação local
O vault local hoje já existe e pode usar passkey como endurecimento de sessão.
Na prática atual:
- os dados do snapshot ficam no navegador
- o vault é cifrado localmente
- a passkey ajuda a bloquear/desbloquear a sessão local
- quando o navegador e o autenticador suportam PRF, o vault passa a preferir esse material como caminho principal de derivação para novos wraps e migra o cofre local na primeira sessão compatível
- a política do vault fica persistida explicitamente como
prf-firstoubrowser-local-wrap, em vez de depender só do estado momentâneo da sessão - ao desligar a passkey, o cofre migra de volta para
browser-local-wrapantes de remover a credencial local - quando PRF não estiver disponível, o fallback continua sendo
browser-local-wrap - o resumo bruto preservado após sync automático também foi minimizado; a PWA guarda o texto estruturado necessário sem trafegar o dump combinado completo do SIGAA
Use .env.example apenas como modelo.
Regras do projeto:
- nunca commitar credenciais reais
- nunca colocar credenciais em arquivos rastreados
- usar variáveis locais só quando necessário para testes privados
- tratar credenciais do SIGAA como efêmeras e de sessão
O teste privado do fluxo web -> extensão -> SIGAA -> vault local fica em:
infra/private-sync-e2e
Fluxo básico:
cd infra/private-sync-e2e
pnpm install
pnpm sync:webObservações:
- a PWA precisa estar rodando localmente
- a extensão precisa estar carregada no navegador
- o harness espera a rota
#/importacao - o relay legado via
window.postMessagefica restrito a localhost; no domínio publicado a PWA usa a ponte direta da extensão - esse fluxo é para validação local privada, não para uso público normal do produto
Na raiz do monorepo:
pnpm dev:web
pnpm prepare:wasm
pnpm build
pnpm test
pnpm lint
pnpm package:extension
pnpm smoke:extension
node scripts/verify-extension-release.mjs
node scripts/audit-extension-package.mjsValidação só do app web:
pnpm --filter @formae/web typecheck
pnpm --filter @formae/web testAtualizar o catálogo público versionado:
pnpm --dir infra/public-catalog-builder buildHoje esse snapshot já inclui:
- páginas públicas oficiais com provenance por captura
- um índice de discovery separado em
infra/static-data/public-catalog.discovery.json - estruturas curriculares públicas do SIGAA
- detalhes públicos de matriz curricular por curso/entrada quando a fonte viva expõe essa navegação
- componentes e faixas de horário públicos normalizados para consumo local pela PWA
apps/
web/ # PWA publicada no GitHub Pages
extension/ # integração local com SIGAA via navegador
desktop/ # espaço reservado para companion futuro em Tauri
packages/
protocol/ # contratos compartilhados entre web, extensão e runtimes locais
crates/
domain/ # modelo acadêmico canônico
parser/ # parser de horários UFBA/SIGAA
rules/ # regras curriculares e pendências
crypto/ # contratos e metadados do vault local
wasm_core/ # bridge WebAssembly
test_fixtures/ # fixtures e replay de contrato
docs/
architecture.md
adr/
infra/
public-catalog-builder/
static-data/
private-sync-e2e/
O Formaê ainda não é o ponto final do produto. Hoje ainda faltam, entre outras coisas:
- catálogo público ainda mais amplo por curso e entrada
- distribuição assinada e publicada da extensão
- cobertura mais profunda de histórico e documentos do SIGAA
- prova operacional em lojas públicas, além do empacotamento e smoke local de Chrome/Firefox
- arquitetura: docs/architecture.md
- decisões arquiteturais: docs/adr
- marca e uso do nome: TRADEMARKS.md
O código-fonte está sob Apache-2.0.
O nome Formaê, sua identidade visual presente e futura, e seus ativos de marca não estão liberados para rebranding derivado. Veja: