diff --git a/_sidebar.md b/_sidebar.md index f1dad7a..0699565 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -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** diff --git a/specs/016-onboard-self-service-prefill/BACKLOG-2FA-BACKUP-EXPORT.md b/specs/016-onboard-self-service-prefill/BACKLOG-2FA-BACKUP-EXPORT.md new file mode 100644 index 0000000..2da86cb --- /dev/null +++ b/specs/016-onboard-self-service-prefill/BACKLOG-2FA-BACKUP-EXPORT.md @@ -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` + `` — 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 | diff --git a/specs/016-onboard-self-service-prefill/spec.md b/specs/016-onboard-self-service-prefill/spec.md index 2424aa6..d811310 100644 --- a/specs/016-onboard-self-service-prefill/spec.md +++ b/specs/016-onboard-self-service-prefill/spec.md @@ -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ĂŁ. --- diff --git a/specs/016-onboard-self-service-prefill/tasks.md b/specs/016-onboard-self-service-prefill/tasks.md new file mode 100644 index 0000000..238b227 --- /dev/null +++ b/specs/016-onboard-self-service-prefill/tasks.md @@ -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 |