Spec 016: backlog export códigos backup 2FA (Roger).
Agrega opções guardar local, Google Drive, Telegram, WhatsApp e cofre — implementação futura.
This commit is contained in:
parent
44dad0063c
commit
45b0914de8
4 changed files with 275 additions and 1 deletions
|
|
@ -135,6 +135,8 @@
|
|||
- [📄 spec.md](specs/014-funnel-phase-timing/spec.md)
|
||||
- **016-onboard-self-service-prefill**
|
||||
- [📄 spec.md](specs/016-onboard-self-service-prefill/spec.md)
|
||||
- [tasks.md](specs/016-onboard-self-service-prefill/tasks.md)
|
||||
- [BACKLOG-2FA-BACKUP-EXPORT.md](specs/016-onboard-self-service-prefill/BACKLOG-2FA-BACKUP-EXPORT.md)
|
||||
- **018-service-orchestration**
|
||||
- [📄 spec.md](specs/018-service-orchestration/spec.md)
|
||||
- **020-purge-history-desk**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
# Spec 016 — Backlog: Exportar códigos backup 2FA
|
||||
|
||||
**Criado:** 2026-06-19
|
||||
**Solicitado por:** Roger
|
||||
**Status:** 📋 **BACKLOG** — aguardando implementação
|
||||
**Prioridade:** P2 (UX + retenção; não bloqueia onboarding)
|
||||
**Sistema:** Portal VM112 (`ibytera-mail-portal`) — modal `PortalTotpSetup.jsx`
|
||||
**Agregado a:** [spec.md](spec.md) (Spec 016)
|
||||
**Relacionado:** Spec 004 (Desk — backup codes equivalentes), Spec 021 (segurança wizard)
|
||||
|
||||
---
|
||||
|
||||
## Contexto
|
||||
|
||||
Após activar o TOTP no portal (`ligbox.com.br`), o utilizador vê o ecrã **«Salve estes códigos»** com 10 códigos de recuperação de uso único. Hoje só pode **ler na tela** e clicar **«Continuar para o onboarding →»**.
|
||||
|
||||
**Problema:** utilizadores perdem os códigos por não os guardarem; recuperação posterior é mais difícil.
|
||||
|
||||
**Pedido Roger:** oferecer **opções explícitas** para guardar os códigos em locais seguros de escolha do utilizador.
|
||||
|
||||
---
|
||||
|
||||
## Ecrã actual (referência)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 🛡️ Autenticação em duas etapas │
|
||||
│ Mais segurança para proteger sua conta│
|
||||
├─────────────────────────────────────────┤
|
||||
│ Salve estes códigos │
|
||||
│ Use um código se perder o celular... │
|
||||
│ │
|
||||
│ 3A8A8D08 598AF02F │
|
||||
│ 328CE565 9E6D208A │
|
||||
│ ... (10 códigos) │
|
||||
│ │
|
||||
│ [ NOVO — barra de acções de export ] │
|
||||
│ │
|
||||
│ [ Continuar para o onboarding → ] │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Ficheiro:** `frontend/src/PortalTotpSetup.jsx` (estado `recoveryCodes`)
|
||||
|
||||
---
|
||||
|
||||
## Requisitos funcionais (backlog)
|
||||
|
||||
### FR-B01 — Descarregar ficheiro local
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Guardar no computador»** / **«Descarregar .txt»** |
|
||||
| Formato | `.txt` UTF-8 com cabeçalho Ligbox + data + login + 10 códigos |
|
||||
| Nome ficheiro | `ligbox-codigos-recuperacao-{login}-{YYYYMMDD}.txt` |
|
||||
| API browser | `Blob` + `<a download>` — sem servidor |
|
||||
| Confirmação | Checkbox «Guardei os códigos» **ou** contador mínimo 5s antes de «Continuar» (opcional P2) |
|
||||
|
||||
### FR-B02 — Google Drive
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Guardar no Google Drive»** |
|
||||
| Método | Google Picker API ou OAuth scope `drive.file` — upload de ficheiro `.txt` |
|
||||
| Conta | Conta Google do utilizador (consentimento explícito) |
|
||||
| Fallback | Se OAuth falhar → sugerir descarregar local |
|
||||
|
||||
### FR-B03 — Telegram
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Enviar para Telegram»** |
|
||||
| Método A (MVP) | Deep link `https://t.me/share/url?text=` com texto codificado (utilizador escolhe chat) |
|
||||
| Método B (futuro) | Bot Ligbox + `sendMessage` após `/start` com token one-time |
|
||||
| Aviso UI | «Não envie para grupos públicos» |
|
||||
|
||||
### FR-B04 — WhatsApp
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Enviar para WhatsApp»** |
|
||||
| Método | Deep link `https://wa.me/?text=` (Web Share API em mobile quando disponível) |
|
||||
| Limitação | Sem API Business no MVP — partilha manual para contacto escolhido |
|
||||
|
||||
### FR-B05 — Cofre de senhas (password vault)
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Abrir no cofre de senhas»** |
|
||||
| Suporte MVP | **Copiar tudo** + instruções para 1Password / Bitwarden / Apple Passwords |
|
||||
| Suporte fase 2 | Web Share API → apps instaladas que aceitem `text/plain` |
|
||||
| Suporte fase 3 | Integração **1Password** (`onepassword://` ou Connect) / **Bitwarden** (CLI web vault export) — avaliar viabilidade |
|
||||
| Formato cópia | Bloco estruturado para colar como Secure Note |
|
||||
|
||||
**Modelo texto cofre:**
|
||||
|
||||
```
|
||||
Ligbox — Códigos de recuperação 2FA
|
||||
Conta: {login}
|
||||
Gerado: {ISO date}
|
||||
---
|
||||
{código1}
|
||||
{código2}
|
||||
...
|
||||
Cada código funciona apenas uma vez.
|
||||
```
|
||||
|
||||
### FR-B06 — Copiar todos (complementar)
|
||||
|
||||
| Item | Detalhe |
|
||||
|------|---------|
|
||||
| Acção | Botão **«Copiar códigos»** (já parcialmente previsto noutros fluxos) |
|
||||
| Feedback | Toast «Copiado» 2s |
|
||||
|
||||
---
|
||||
|
||||
## Requisitos não-funcionais
|
||||
|
||||
| ID | Regra |
|
||||
|----|-------|
|
||||
| NFR-01 | Códigos **nunca** enviados para servidor Ligbox excepto armazenamento já existente (`recovery_codes` hash server-side) |
|
||||
| NFR-02 | Exportações cliente-side preferidas (download, clipboard, deep links) |
|
||||
| NFR-03 | Google Drive / Telegram bot exigem **consentimento** explícito antes de upload |
|
||||
| NFR-04 | Não logar códigos em plaintext em analytics / webhooks / Desk |
|
||||
| NFR-05 | UI pt-BR; ícones reconhecíveis (Drive, Telegram, WhatsApp, cofre) |
|
||||
| NFR-06 | Funcionar em desktop e mobile (layout responsivo) |
|
||||
|
||||
---
|
||||
|
||||
## UX proposta — barra de acções
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ 💾 Computador ☁️ Google Drive 📋 Copiar │
|
||||
│ ✈️ Telegram 💬 WhatsApp 🔐 Cofre │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Botões secundários (outline), não competir com CTA principal «Continuar».
|
||||
- Tooltip em cada botão com explicação curta.
|
||||
- Após qualquer export bem-sucedido: badge «✓ Guardado» no botão correspondente (sessão).
|
||||
|
||||
---
|
||||
|
||||
## Fases de implementação (backlog)
|
||||
|
||||
| Fase | Entrega | Esforço | Prioridade |
|
||||
|------|---------|---------|------------|
|
||||
| **B1** | Descarregar `.txt` + Copiar todos | S | P2 — quick win |
|
||||
| **B2** | Deep links Telegram + WhatsApp | S | P2 |
|
||||
| **B3** | Bloco «Cofre» + instruções 1Password/Bitwarden | S | P2 |
|
||||
| **B4** | Google Drive OAuth upload | M | P3 |
|
||||
| **B5** | Telegram Bot Ligbox (opcional) | L | P4 |
|
||||
| **B6** | Web Share API nativo (mobile) | S | P3 |
|
||||
| **B7** | Paridade Spec 004 Desk (`activate.html` backup export) | M | P3 |
|
||||
|
||||
---
|
||||
|
||||
## Tarefas backlog
|
||||
|
||||
Ver [tasks.md](tasks.md) secção **Backlog 2FA export**.
|
||||
|
||||
---
|
||||
|
||||
## Critérios de aceitação (quando implementar)
|
||||
|
||||
1. **Given** utilizador concluiu TOTP, **When** vê ecrã códigos, **Then** tem ≥3 opções de guardar (local, copiar, +1 canal).
|
||||
2. **Given** clica «Guardar no computador», **When** download completa, **Then** ficheiro `.txt` contém 10 códigos + metadados.
|
||||
3. **Given** clica Telegram/WhatsApp, **When** app abre, **Then** texto pré-preenchido com códigos (utilizador confirma envio).
|
||||
4. **Given** export concluído, **When** clica «Continuar para onboarding», **Then** fluxo Spec 016 mantém-se (pré-preenchimento wizard).
|
||||
5. **Given** auditoria segurança, **When** revista logs VM112, **Then** zero códigos em plaintext em logs.
|
||||
|
||||
---
|
||||
|
||||
## Fora de escopo (esta fase)
|
||||
|
||||
- Re-envio de códigos por e-mail (já pode existir noutro fluxo — não duplicar sem revisão)
|
||||
- Armazenamento Ligbox cloud dos códigos do utilizador
|
||||
- Integração LastPass / Dashlane proprietária (só via cofre genérico / Web Share)
|
||||
|
||||
---
|
||||
|
||||
## Referências código
|
||||
|
||||
| Ficheiro | Notas |
|
||||
|----------|-------|
|
||||
| `frontend/src/PortalTotpSetup.jsx` | Ecrã códigos — ponto de inserção UI |
|
||||
| `frontend/src/portalAuth.js` | `confirmPortalTotp()` → `recovery_codes` |
|
||||
| `frontend/src/ligbox/components/TwoFactorCardHeader.jsx` | Cabeçalho modal |
|
||||
| Spec 004 `backup_codes.py` | Padrão Desk (paridade futura) |
|
||||
|
||||
---
|
||||
|
||||
## Histórico
|
||||
|
||||
| Data | Evento |
|
||||
|------|--------|
|
||||
| 2026-06-19 | Roger solicita opções export — registado como backlog agregado Spec 016 |
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
**Status:** Implementação
|
||||
**Prioridade:** P0 (regressão UX onboarding)
|
||||
**Sistema:** Portal VM112 (`ibytera-mail-portal`) — wizard `/onboard`
|
||||
**Relacionado:** Spec 012 (ticket no `onboarding.started`), chat bruto `CHAT_BRUTO_ONBOARD_INFRA_SUPORTE_20260603`
|
||||
**Relacionado:** Spec 012 (ticket no `onboarding.started`), chat bruto `CHAT_BRUTO_ONBOARD_INFRA_SUPORTE_20260603`
|
||||
**Backlog agregado:** [BACKLOG-2FA-BACKUP-EXPORT.md](BACKLOG-2FA-BACKUP-EXPORT.md) — export códigos 2FA (Roger 2026-06-19)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -96,6 +97,18 @@ Utilizador entra directo em `/onboard` sem landing: campos vazios ou defaults (`
|
|||
| `frontend/src/ligbox/components/SelfServiceCard.jsx` | registo/login/TOTP → `beginOnboardingForEmail` + credenciais |
|
||||
| `frontend/src/App.jsx` | `loadWizardStateForOnboard()` no init + `useEffect` de sync |
|
||||
| `frontend/src/AdminPasswordField.jsx` | senha mascarada + reveal com `verifyStepUp` (2FA) |
|
||||
| `frontend/src/PortalTotpSetup.jsx` | Modal 2FA + ecrã «Salve estes códigos» |
|
||||
|
||||
---
|
||||
|
||||
## Backlog agregado (não implementado)
|
||||
|
||||
| Item | Documento | Status |
|
||||
|------|-----------|--------|
|
||||
| Export códigos backup 2FA (local, Drive, Telegram, WhatsApp, cofre) | [BACKLOG-2FA-BACKUP-EXPORT.md](BACKLOG-2FA-BACKUP-EXPORT.md) | 📋 Backlog P2 |
|
||||
| Tarefas | [tasks.md](tasks.md) | 0/16 concluídas (export) |
|
||||
|
||||
**Pedido Roger (2026-06-19):** dar ao utilizador opções para guardar os 10 códigos de recuperação além de apenas visualizar no ecrã.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
61
specs/016-onboard-self-service-prefill/tasks.md
Normal file
61
specs/016-onboard-self-service-prefill/tasks.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Spec 016 — Tasks
|
||||
|
||||
**Spec:** Pré-preenchimento Self-Service → Wizard
|
||||
**Backlog 2FA export:** [BACKLOG-2FA-BACKUP-EXPORT.md](BACKLOG-2FA-BACKUP-EXPORT.md)
|
||||
|
||||
---
|
||||
|
||||
## Entregue (core Spec 016)
|
||||
|
||||
- [x] `beginOnboardingForEmail()` + `ligbox_planned_email`
|
||||
- [x] `setPortalOnboardCredentials()` → sessionStorage senha
|
||||
- [x] `syncWizardWithPlannedEmail()` — prioridade Self-Service
|
||||
- [x] `loadWizardStateForOnboard()` no mount wizard
|
||||
- [x] Fluxo registo → TOTP → redirect `/onboard`
|
||||
- [x] `PortalTotpSetup.jsx` — ecrã «Salve estes códigos» (visual only)
|
||||
|
||||
---
|
||||
|
||||
## Backlog — Export códigos backup 2FA (Roger 2026-06-19)
|
||||
|
||||
**Status:** 📋 Aguardando implementação
|
||||
**Prioridade:** P2
|
||||
|
||||
### Fase B1 — Quick wins
|
||||
- [ ] **B1-01** Botão «Descarregar .txt» em `PortalTotpSetup.jsx`
|
||||
- [ ] **B1-02** Botão «Copiar todos os códigos» + toast confirmação
|
||||
- [ ] **B1-03** Formato ficheiro `ligbox-codigos-recuperacao-{login}-{date}.txt`
|
||||
|
||||
### Fase B2 — Partilha manual (deep links)
|
||||
- [ ] **B2-01** Botão Telegram → `t.me/share/url`
|
||||
- [ ] **B2-02** Botão WhatsApp → `wa.me/?text=`
|
||||
- [ ] **B2-03** Aviso segurança «não partilhe em grupos públicos»
|
||||
|
||||
### Fase B3 — Cofre de senhas (MVP)
|
||||
- [ ] **B3-01** Botão «Guardar no cofre» → copiar Secure Note formatada
|
||||
- [ ] **B3-02** Modal instruções 1Password / Bitwarden / Apple Passwords
|
||||
|
||||
### Fase B4 — Google Drive
|
||||
- [ ] **B4-01** OAuth Google + scope `drive.file`
|
||||
- [ ] **B4-02** Upload `.txt` para Drive do utilizador
|
||||
- [ ] **B4-03** Fallback para download local se OAuth falhar
|
||||
|
||||
### Fase B5 — Integrações avançadas (opcional)
|
||||
- [ ] **B5-01** Web Share API (mobile)
|
||||
- [ ] **B5-02** Telegram Bot Ligbox (envio directo)
|
||||
- [ ] **B5-03** Paridade export na Spec 004 Desk (`activate.html`)
|
||||
|
||||
### Fase B6 — UX / segurança
|
||||
- [ ] **B6-01** Barra de acções responsiva (ícones + labels)
|
||||
- [ ] **B6-02** Badge «✓ Guardado» por canal usado
|
||||
- [ ] **B6-03** Revisão NFR: zero códigos em logs/webhooks
|
||||
|
||||
---
|
||||
|
||||
## Dependências
|
||||
|
||||
| Tarefa | Depende de |
|
||||
|--------|------------|
|
||||
| B4 Google Drive | Conta Google Cloud + OAuth client |
|
||||
| B5-02 Telegram Bot | Token bot + política privacidade |
|
||||
| B5-03 Desk paridade | Spec 004 maintainers |
|
||||
Loading…
Reference in a new issue