Roger, a pergunta faz todo o sentido. Resposta directa:

## Não é confuso para o fluxo normal

Quem usa o **Self-Service** em `ligbox.com.br` **não passa** por `ligbox.com.br/onboard`.

O fluxo real é:

```
ligbox.com.br (registo/login)
    → redirectToOnboard()
    → onboard.ligbox.com.br/onboard?planned_email=...&onboard_handoff=...
```

O utilizador salta directamente para o subdomínio do produto. O `/onboard` no domínio principal é sobretudo **compatibilidade** — bookmarks antigos, links em documentação, alguém que escreve o URL à mão.

---

## Porque existem dois sítios (não é capricho)

| Razão | Explicação |
|-------|------------|
| **Spec 016** | Portal e wizard são **origens diferentes**; senha/e-mail passam por handoff API + cookie `.ligbox.com.br` |
| **Spec 018** | Dois bundles, dois deploys — site leve, wizard completo |
| **Segurança** | Wizard + API Carbonio isolados em `onboard.*` |
| **Marketing vs produto** | `ligbox.com.br` = landing; `onboard.*` = ferramenta de activação |

Ter tudo em `ligbox.com.br/onboard` **sem** subdomínio obrigava a meter o wizard inteiro no bundle do site — exactamente o que a Spec 018 acabou de separar.

---

## Onde pode haver confusão ou erro

| Cenário | Risco | Gravidade |
|---------|-------|-----------|
| Utilizador normal (Self-Service) | Nenhum — nunca vê o redirect | ✅ |
| Bookmark `ligbox.com.br/onboard` | Redirect rápido → subdomínio; e-mail vem do cookie | ⚠ Baixo |
| Link antigo **com** `?onboard_handoff=...` no domínio principal | O redirect actual **não reencaminha** o token handoff — só o e-mail | ⚠ Médio (edge case) |
| Duas URLs na documentação | Confusão para equipa, não para cliente | ⚠ Baixo |
| Flash de página antes do redirect | Sensação de “saltou de sítio” | ⚠ Cosmético |

O fluxo principal (`redirectToOnboard`) está correcto. O ponto fraco é só o **redirect legacy** em `RouterApp.jsx` quando alguém entra em `ligbox.com.br/onboard` com parâmetros na URL.

---

## O que recomendo (arquitectura)

### Manter (por agora)
- **`onboard.ligbox.com.br/onboard`** = URL **canónica** do produto
- **`ligbox.com.br/onboard`** = redirect de compatibilidade (não promover em marketing)

### Melhorar (pequeno, se quiseres)
1. **Redirect preservar query string completa** (`planned_email` + `onboard_handoff`)
2. **Traefik 301** `ligbox.com.br/onboard` → `onboard.ligbox.com.br/onboard` (mais rápido que JS, sem flash)
3. **Documentação/links** — só `onboard.ligbox.com.br`; nunca `ligbox.com.br/onboard` em botões novos

### Não fazer (sem refactor grande)
- Servir o wizard em `ligbox.com.br/onboard` em produção — volta a misturar bundles e complica o handoff cross-origin

---

## Resumo

| Pergunta | Resposta |
|----------|----------|
| É confuso? | **Para o cliente normal, não** — ele nunca vê o redirect |
| Incorre em erros? | **Raramente** — risco real só em links legacy com token na URL errada |
| Devemos mudar? | **Não o modelo** (dois subdomínios); **sim** podemos endurecer o redirect legacy |

Queres que faça já o fix do redirect (preservar `onboard_handoff` + eventual 301 no Traefik)? São ~15 minutos e fecham o único buraco real que identifiquei.

[REDACTED]


<user_query>
sim faca o  fix do redirect (preservar onboard_handoff + eventual 301 no Traefik) e relate na espc 018
</user_query>


[REDACTED]


[REDACTED]

Shell

ssh root@10.10.10.114 'grep -n "ligbox.com.br\|onboard.ligbox" /root/traefik/dynamic.yml 2>/dev/null | head -40' 2>/dev/null || ssh root@10.10.10.114 'find / -name "dynamic.yml" 2>/dev/null | head -5'

Find Traefik dynamic config for ligbox domains on CT114


[REDACTED]

ssh root@10.10.10.114 'sed -n "125,195p" /root/traefik/dynamic.yml; echo "---"; sed -n "595,615p" /root/traefik/dynamic.yml'

Read Traefik ligbox routers and redirect middleware


Implementando o redirect com query string preservada e o 301 no Traefik.

[REDACTED]

StrReplace

export function buildOnboardUrl(plannedEmail, { handoffToken } = {}) {
  const base = wizardBaseUrl()
  const email = resolvePlannedEmail(plannedEmail)
  const params = new URLSearchParams()
  if (email) {
    setPlannedEmailPersist(email)
    params.set(PLANNED_EMAIL_URL_PARAM, email)
  }
  if (handoffToken) {
    params.set(ONBOARD_HANDOFF_URL_PARAM, handoffToken)
  }
  const qs = params.toString()
  return `${base}${WIZARD_ONBOARD_PATH}${qs ? `?${qs}` : ''}`
}

/**
 * Redirect legacy `ligbox.com.br/onboard` ou `/wizard` → wizard canónico (Spec 018).
 * Preserva toda a query string (incl. `onboard_handoff`) e preenche `planned_email` se em falta.
 */
export function buildLegacyOnboardRedirectUrl(
  search = '',
  { cookieEmail = '', storageEmail = '' } = {},
) {
  const params = new URLSearchParams(search)
  const email =
    normalizePlannedEmail(params.get(PLANNED_EMAIL_URL_PARAM)) ||
    normalizePlannedEmail(cookieEmail) ||
    normalizePlannedEmail(storageEmail)
  if (email && !params.has(PLANNED_EMAIL_URL_PARAM)) {
    params.set(PLANNED_EMAIL_URL_PARAM, email)
  }
  const qs = params.toString()
  return `${wizardBaseUrl()}${WIZARD_ONBOARD_PATH}${qs ? `?${qs}` : ''}`
}

export function buildOnboardUrl(plannedEmail, { handoffToken } = {}) {
  const base = wizardBaseUrl()
  const email = resolvePlannedEmail(plannedEmail)
  const params = new URLSearchParams()
  if (email) {
    setPlannedEmailPersist(email)
    params.set(PLANNED_EMAIL_URL_PARAM, email)
  }
  if (handoffToken) {
    params.set(ONBOARD_HANDOFF_URL_PARAM, handoffToken)
  }
  const qs = params.toString()
  return `${base}${WIZARD_ONBOARD_PATH}${qs ? `?${qs}` : ''}`
}

import {
  PLANNED_EMAIL_URL_PARAM,
  WIZARD_ONBOARD_PATH,
  normalizePlannedEmail,
  resolvePlannedEmail,
  setPlannedEmailPersist,
} from './plannedEmailHandoff'

import {
  PLANNED_EMAIL_URL_PARAM,
  WIZARD_ONBOARD_PATH,
  resolvePlannedEmail,
  setPlannedEmailPersist,
} from './plannedEmailHandoff'

import { buildLegacyOnboardRedirectUrl } from './lib/onboardUrl'

import { buildOnboardUrl, readPlannedEmailFromCookie } from './lib/onboardUrl'

    window.location.replace(
      buildLegacyOnboardRedirectUrl(window.location.search, {
        cookieEmail: readPlannedEmailFromCookie(),
        storageEmail: localStorage.getItem('ligbox_planned_email') || '',
      }),
    )

    const params = new URLSearchParams(window.location.search)
    const email =
      params.get('planned_email') ||
      readPlannedEmailFromCookie() ||
      (localStorage.getItem('ligbox_planned_email') || '').trim()
    window.location.href = buildOnboardUrl(email)


[REDACTED]

import { buildLegacyOnboardRedirectUrl, readPlannedEmailFromCookie } from './lib/onboardUrl'

import { buildLegacyOnboardRedirectUrl } from './lib/onboardUrl'

test('URL handoff inclui onboard_handoff sem expor senha', () => {
  const base = 'https://onboard.ligbox.com.br/onboard?planned_email=admin%40betinplace.com'
  const token = 'a'.repeat(32)
  const url = `${base}&onboard_handoff=${encodeURIComponent(token)}`
  assert.ok(url.includes('onboard_handoff='))
  assert.ok(!url.includes('password='))
  assert.ok(!url.includes('senha'))
})

test('buildLegacyOnboardRedirectUrl preserva onboard_handoff e planned_email', () => {
  const search = '?planned_email=admin%40betinplace.com&onboard_handoff=token123'
  const url = buildLegacyOnboardRedirectUrlPure(search)
  assert.equal(
    url,
    'https://onboard.ligbox.com.br/onboard?planned_email=admin%40betinplace.com&onboard_handoff=token123',
  )
})

test('buildLegacyOnboardRedirectUrl preenche planned_email a partir do cookie', () => {
  const url = buildLegacyOnboardRedirectUrlPure('?onboard_handoff=token123', {
    cookieEmail: 'admin@empresa.com.br',
  })
  assert.ok(url.includes('planned_email=admin%40empresa.com.br'))
  assert.ok(url.includes('onboard_handoff=token123'))
})

function buildLegacyOnboardRedirectUrlPure(search, opts = {}) {
  const params = new URLSearchParams(search)
  const email =
    normalizePlannedEmail(params.get('planned_email')) ||
    normalizePlannedEmail(opts.cookieEmail || '') ||
    normalizePlannedEmail(opts.storageEmail || '')
  if (email && !params.has('planned_email')) {
    params.set('planned_email', email)
  }
  const qs = params.toString()
  return `https://onboard.ligbox.com.br/onboard${qs ? `?${qs}` : ''}`
}

test('URL handoff inclui onboard_handoff sem expor senha', () => {
  const base = 'https://onboard.ligbox.com.br/onboard?planned_email=admin%40betinplace.com'
  const token = 'a'.repeat(32)
  const url = `${base}&onboard_handoff=${encodeURIComponent(token)}`
  assert.ok(url.includes('onboard_handoff='))
  assert.ok(!url.includes('password='))
  assert.ok(!url.includes('senha'))
})

Write

# Traefik CT114 — redirect legacy onboard (Spec 018)
# Aplicar em /root/traefik/dynamic.yml no CT114 (portainer / 10.10.10.114)
#
# Router priority 90: abaixo de ligbox-api (100), acima de ligbox-Router (default).
# Query string preservada automaticamente pelo middleware redirectRegex.

# routers:
#     ligbox-onboard-legacy-Router:
#       rule: (Host(`ligbox.com.br`) || Host(`www.ligbox.com.br`)) && (PathPrefix(`/onboard`) || PathPrefix(`/wizard`))
#       priority: 90
#       service: ligbox-web-Service
#       entryPoints:
#       - websecure
#       tls:
#         certResolver: letsencrypt
#       middlewares:
#       - ligbox-to-onboard-redirect
#
# middlewares:
#     ligbox-to-onboard-redirect:
#       redirectRegex:
#         regex: ^https?://(www\.)?ligbox\.com\.br/(?:onboard|wizard)(.*)
#         replacement: https://onboard.ligbox.com.br/onboard${2}
#         permanent: true


[REDACTED]

Shell

ssh root@10.10.10.114 'cp /root/traefik/dynamic.yml /root/traefik/dynamic.yml.bak.$(date +%Y%m%d)-spec018-onboard-redirect && python3 << "PY"
from pathlib import Path
p = Path("/root/traefik/dynamic.yml")
text = p.read_text()
if "ligbox-onboard-legacy-Router" in text:
    print("already present")
else:
    router = """    ligbox-onboard-legacy-Router:
      rule: (Host(`ligbox.com.br`) || Host(`www.ligbox.com.br`)) && (PathPrefix(`/onboard`) || PathPrefix(`/wizard`))
      priority: 90
      service: ligbox-web-Service
      entryPoints:
      - websecure
      tls:
        certResolver: letsencrypt
      middlewares:
      - ligbox-to-onboard-redirect

"""
    marker = "    ligbox-Router:"
    if marker not in text:
        raise SystemExit("ligbox-Router marker not found")
    text = text.replace(marker, router + marker, 1)

if "ligbox-to-onboard-redirect:" not in text:
    mw = """    ligbox-to-onboard-redirect:
      redirectRegex:
        regex: ^https?://(www\\.)?ligbox\\.com\\.br/(?:onboard|wizard)(.*)
        replacement: https://onboard.ligbox.com.br/onboard${2}
        permanent: true
"""
    marker = "    redirect-onboard-ligbox:"
    if marker not in text:
        raise SystemExit("redirect-onboard-ligbox marker not found")
    text = text.replace(marker, mw + "    redirect-onboard-ligbox:", 1)

p.write_text(text)
print("updated dynamic.yml")
PY
docker exec traefik kill -HUP 1 2>/dev/null || docker restart traefik 2>/dev/null || (cd /root/traefik && docker compose restart traefik) 2>/dev/null; sleep 2; grep -A8 "ligbox-onboard-legacy" /root/traefik/dynamic.yml'

Apply Traefik 301 redirect on CT114 with backup


[REDACTED]

ssh root@10.10.10.114 'grep -A6 "ligbox-to-onboard-redirect" /root/traefik/dynamic.yml'; echo "---"; curl -sI "https://ligbox.com.br/onboard?planned_email=admin@test.com&onboard_handoff=abc123" 2>&1 | head -12

Verify Traefik middleware and 301 redirect

StrReplace

**Regra de ouro:** nunca `rsync` do `dist/` do wizard para `/opt/ligbox-web/` nem o inverso.

### 4.1 Redirect legacy `/onboard` (Spec 018 — 2026-06-19)

URLs antigas `ligbox.com.br/onboard` e `/wizard` **não servem o wizard** — redireccionam para o canónico `onboard.ligbox.com.br/onboard`.

```mermaid
sequenceDiagram
  participant U as Browser
  participant T as Traefik CT114
  participant W as ligbox-web :8092
  participant O as onboard.ligbox.com.br

  U->>T: GET ligbox.com.br/onboard?onboard_handoff=…
  T->>U: 301 Location: onboard.ligbox.com.br/onboard?…
  Note over T: priority 90, middleware ligbox-to-onboard-redirect

  U->>T: GET ligbox.com.br/onboard (sem Traefik match edge)
  T->>W: fallback SPA
  W->>U: JS buildLegacyOnboardRedirectUrl (preserva query)
```

| Camada | Mecanismo | Preserva query |
|--------|-----------|----------------|
| **Traefik** (preferido) | Router `ligbox-onboard-legacy-Router` + middleware `ligbox-to-onboard-redirect` | ✅ automático |
| **SPA fallback** | `buildLegacyOnboardRedirectUrl()` em `RouterApp.jsx` | ✅ `planned_email` + `onboard_handoff` + resto |

Snippet IaC: `deploy/traefik/ligbox-onboard-legacy-redirect.snippet.yml`
Backup CT114: `dynamic.yml.bak.YYYYMMDD-spec018-onboard-redirect`

**URL canónica do produto:** `https://onboard.ligbox.com.br/onboard` — não promover `ligbox.com.br/onboard` em links novos.

---

**Regra de ouro:** nunca `rsync` do `dist/` do wizard para `/opt/ligbox-web/` nem o inverso.

---

| 3 — scripts deploy + guards | ✅ Feito | `build:site`, `check-build-site`, `deploy-guard`, `deploy/*.sh` |
| 3b — redirect legacy `/onboard` | ✅ Feito | Traefik 301 + `buildLegacyOnboardRedirectUrl()` |
| 4 — `src/shared/` | ⬜ Opcional | |

| 3 — scripts deploy + guards | ✅ Feito | `build:site`, `check-build-site`, `deploy-guard`, `deploy/*.sh` |
| 4 — `src/shared/` | ⬜ Opcional | |


Traefik 308 com query string preservada. A seguir: testes, build e deploy do site.

[REDACTED]

Shell

cd /root/workspace/projects/ibytera-mail-portal/frontend && npm run test:handoff 2>&1 && npm run build:site 2>&1 && bash ../deploy/ligbox-web/deploy.sh 2>&1 | tail -15

Test handoff, build and deploy site

StrReplace

| `RouterApp.jsx` | `/onboard` legacy → `buildLegacyOnboardRedirectUrl()` (preserva `onboard_handoff`; Spec 018) |

| `RouterApp.jsx` | `/onboard` legacy → `buildOnboardUrl(resolvePlannedEmail(...))` |


[REDACTED]

Shell

systemctl restart ligbox-web && sleep 1 && curl -sI "https://ligbox.com.br/wizard?onboard_handoff=tok456" 2>&1 | grep -iE 'HTTP|location' && curl -s -o /dev/null -w "site:%{http_code}\n" http://127.0.0.1:8092/

Verify /wizard redirect and site health


Roger, feito — redirect legacy corrigido e documentado na **Spec 018**.

## O que foi implementado

### 1. JavaScript (fallback SPA)
Nova função `buildLegacyOnboardRedirectUrl()` em `lib/onboardUrl.js`:
- Preserva **toda** a query string (`onboard_handoff`, `planned_email`, etc.)
- Preenche `planned_email` a partir do cookie/localStorage se faltar na URL
- Usa `location.replace()` (evita loop no botão “voltar”)

`RouterApp.jsx` usa esta função quando alguém chega a `/onboard` ou `/wizard` no site (só se o Traefik não interceptar primeiro).

### 2. Traefik 301/308 (CT114 — preferido)
Novo router `ligbox-onboard-legacy-Router` (priority 90) + middleware `ligbox-to-onboard-redirect`:

```
ligbox.com.br/onboard?...  →  308  →  onboard.ligbox.com.br/onboard?...
ligbox.com.br/wizard?...   →  308  →  onboard.ligbox.com.br/onboard?...
```

**Testado:**
```
GET https://ligbox.com.br/onboard?planned_email=admin@test.com&onboard_handoff=abc123
→ Location: https://onboard.ligbox.com.br/onboard?planned_email=admin@test.com&onboard_handoff=abc123
```

### 3. Testes
2 testes novos em `plannedEmailHandoff.test.js` — **7/7 passam**.

### 4. Documentação
- **Spec 018** §4.1 — diagrama + tabela Traefik vs SPA fallback
- **Spec 016** — referência ao novo redirect
- Snippet IaC: `deploy/traefik/ligbox-onboard-legacy-redirect.snippet.yml`
- Backup CT114: `dynamic.yml.bak.*-spec018-onboard-redirect`

### 5. Deploy
Site rebuild + deploy na VM112 (`index-DlqKUi5K.js`).

---

## Como funciona agora (dupla proteção)

| Entrada | Quem trata | Resultado |
|---------|------------|-----------|
| `ligbox.com.br/onboard?...` | **Traefik** (308) | Redirect imediato, sem carregar JS |
| Mesmo URL se Traefik falhar | **SPA fallback** | `buildLegacyOnboardRedirectUrl()` |
| Self-Service normal | `redirectToOnboard()` | Vai directo a `onboard.ligbox.com.br` |

**URL canónica:** `https://onboard.ligbox.com.br/onboard` — não usar `ligbox.com.br/onboard` em links novos.

[REDACTED]


[Image]
<user_query>

</user_query>


Roger, os ícones das features 5–7 estão partidos — vou verificar paths e assets no servidor.

[REDACTED]

curl -sI "https://ligbox.com.br/assets/orbit/orbit-security.png" | head -6; curl -sI "https://ligbox.com.br/assets/orbit/orbit-support.png" | head -6; curl -sI "https://ligbox.com.br/assets/orbit/orbit-backup.png" | head -6; curl -sI "https://ligbox.com.br/assets/features/feature-shield.png" | head -6; curl -s "https://ligbox.com.br/assets/orbit/orbit-security.png" | head -c 8 | xxd

Check feature/orbit PNG HTTP responses

ls -la /opt/ligbox-web/assets/orbit/orbit-{security,support,backup}.png /opt/ligbox-web/assets/features/feature-shield.png 2>&1

Verify PNG files exist on ligbox-web


Os PNGs respondem 200 — provável cache envenenado nos ícones `orbit` (features 5–7). Vou adicionar cache-bust e republicar.

[REDACTED]


[REDACTED]

List feature and icon assets


[REDACTED]

StrReplace

const FEATURE_ASSET_VER = '20260619c'

function featureSrc(path) {
  return `${path}?v=${FEATURE_ASSET_VER}`
}

function FeatureIcon({ src, alt }) {
  return (

  )
}

const features = [
  {
    icon: featureSrc('/assets/features/feature-shield.png'),
    alt: 'Controle e privacidade',
    title: '1. Controle e Privacidade Total',
    description: 'Seu próprio servidor hospedado na nuvem Lig-it. Você tem as chaves.',
  },
  {
    icon: featureSrc('/assets/features/feature-security.png'),
    alt: 'Segurança empresarial',
    title: '2. Segurança de Nível Empresarial',
    description: 'Proteção contra malware, anti-spam inteligente e firewall de rede dedicado.',
  },
  {
    icon: featureSrc('/assets/features/feature-audit.png'),
    alt: 'Rastreabilidade e auditoria',
    title: '3. Rastreabilidade, Auditoria e Proteção de Entrega',
    description:
      'Monitoramento contínuo de SPF, DKIM e DMARC através da plataforma EasyDMARC, certificada SOC 2 Type II e SOC 3, reduzindo riscos de spoofing, phishing e bloqueio de mensagens.',
  },
  {
    icon: featureSrc('/assets/features/feature-backup.png'),
    alt: 'Backups e recuperação',
    title: '4. Backups Automáticos e Recuperação',
    description: 'Backups confiáveis e integrados com planos de recuperação de desastres (DR).',
  },
  {
    icon: featureSrc('/assets/orbit/orbit-security.png'),
    alt: 'Monitoramento contínuo',
    title: '5. Monitoramento Contínuo',
    description: 'Supervisão 24/7 da infraestrutura para garantir disponibilidade e performance.',
  },
  {
    icon: featureSrc('/assets/orbit/orbit-support.png'),
    alt: 'Suporte especializado',
    title: '6. Suporte Especializado',
    description: 'Equipe técnica dedicada da Lig-it para acompanhar sua operação.',
  },
  {
    icon: featureSrc('/assets/orbit/orbit-backup.png'),
    alt: 'Atualizações e manutenção',
    title: '7. Atualizações e Manutenção Inclusas',
    description: 'Atualizações constantes com novas funcionalidades e correções de segurança.',
  },
]

function FeatureIcon({ src, alt }) {
  return (

  )
}

const features = [
  {
    icon: '/assets/features/feature-shield.png',
    alt: 'Controle e privacidade',
    title: '1. Controle e Privacidade Total',
    description: 'Seu próprio servidor hospedado na nuvem Lig-it. Você tem as chaves.',
  },
  {
    icon: '/assets/features/feature-security.png',
    alt: 'Segurança empresarial',
    title: '2. Segurança de Nível Empresarial',
    description: 'Proteção contra malware, anti-spam inteligente e firewall de rede dedicado.',
  },
  {
    icon: '/assets/features/feature-audit.png',
    alt: 'Rastreabilidade e auditoria',
    title: '3. Rastreabilidade, Auditoria e Proteção de Entrega',
    description:
      'Monitoramento contínuo de SPF, DKIM e DMARC através da plataforma EasyDMARC, certificada SOC 2 Type II e SOC 3, reduzindo riscos de spoofing, phishing e bloqueio de mensagens.',
  },
  {
    icon: '/assets/features/feature-backup.png',
    alt: 'Backups e recuperação',
    title: '4. Backups Automáticos e Recuperação',
    description: 'Backups confiáveis e integrados com planos de recuperação de desastres (DR).',
  },
  {
    icon: '/assets/orbit/orbit-security.png',
    alt: 'Monitoramento contínuo',
    title: '5. Monitoramento Contínuo',
    description: 'Supervisão 24/7 da infraestrutura para garantir disponibilidade e performance.',
  },
  {
    icon: '/assets/orbit/orbit-support.png',
    alt: 'Suporte especializado',
    title: '6. Suporte Especializado',
    description: 'Equipe técnica dedicada da Lig-it para acompanhar sua operação.',
  },
  {
    icon: '/assets/orbit/orbit-backup.png',
    alt: 'Atualizações e manutenção',
    title: '7. Atualizações e Manutenção Inclusas',
    description: 'Atualizações constantes com novas funcionalidades e correções de segurança.',
  },
]

Shell

cd /root/workspace/projects/ibytera-mail-portal/frontend && npm run deploy:site 2>&1 | tail -8

Build and deploy site with feature cache-bust


[REDACTED]

systemctl restart ligbox-web && curl -s -o /dev/null -w "%{http_code} %{content_type}\n" "http://127.0.0.1:8092/assets/orbit/orbit-security.png?v=20260619c"

Restart ligbox-web and verify cached orbit URL


[REDACTED]

sleep 2 && systemctl is-active ligbox-web && curl -s -o /dev/null -w "%{http_code} %{content_type}\n" "http://127.0.0.1:8092/assets/orbit/orbit-security.png?v=20260619c"

Verify ligbox-web after restart


Roger, vi o screenshot — os ícones **5, 6 e 7** estavam partidos; os **1–4** ok.

### Causa
Os pontos 5–7 usam imagens de `/assets/orbit/` (as mesmas do radar). Durante o deploy incompleto anterior, o browser guardou **HTML em cache** como se fosse PNG nesses URLs. Os ícones 1–4 usam `/assets/features/` — não foram afectados.

No servidor os ficheiros estão corretos (HTTP 200, `image/png`).

### Correção aplicada
- Cache-bust `?v=20260619c` em **todos** os ícones da secção Benefícios
- `loading="eager"` nos ícones (carregam logo, não lazy)
- Deploy do site concluído

### O que fazer aí
**Ctrl+Shift+R** em https://ligbox.com.br/#beneficios

Os três ícones (Monitoramento, Suporte, Atualizações) devem voltar a aparecer.

Se ainda falharem, no DevTools → Network filtra `orbit-security` e confirma `Type: image/png` (não `document`).

[REDACTED]


[Image]
[Image]
<user_query>
ode colocar a logo do ligbox na pagina do onboard  pode azer um pouquino maiso do que o logo que ta alagpra , consegue ? sem atrapalhar nada na qopigina ?
</user_query>


[REDACTED]

List available Ligbox logo assets


Substituindo o placeholder "L" pela logo Ligbox no header do wizard, com tamanho ligeiramente maior e fundo claro para contraste no header escuro.

[REDACTED]

StrReplace

        <header className="wcl__header">
          <div className="wcl__header-brand">
            <img
              src="/assets/ligbox-logo-hero-web.png?v=20260619d"
              alt="Ligbox"
              className="wcl__logo-img"
              width={168}
              height={44}
              decoding="async"
            />
          </div>

              L

            Ligbox Onboard

.wcl__header-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex-shrink: 0;
}

.wcl__logo-img {
  display: block;
  height: 2.35rem;
  width: auto;
  max-width: 10.5rem;
  object-fit: contain;
  padding: 0.22rem 0.5rem;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.97);
  box-shadow: 0 1px 10px rgba(0, 16, 32, 0.22);
}

.wcl__logo {

.wcl__header-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

.wcl__logo {


[REDACTED]

@media (max-width: 900px) {
  .wcl__header,
  .wcl__body,
  .wcl__toolbar,
  .wcl__statusbar {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }

  .wcl__logo-img {
    height: 2rem;
    max-width: 9rem;
    padding: 0.18rem 0.4rem;
  }

  .wcl__body {

@media (max-width: 900px) {
  .wcl__header,
  .wcl__body,
  .wcl__toolbar,
  .wcl__statusbar {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }

  .wcl__body {

Shell

cd /root/workspace/projects/ibytera-mail-portal/frontend && npm run deploy:wizard 2>&1 | tail -12

Build and deploy wizard with new logo


[REDACTED]

systemctl restart ligbox-wizard && sleep 2 && curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8090/onboard && curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8090/assets/ligbox-logo-hero-web.png

Restart wizard and verify onboard + logo asset


Roger, feito.

### O que mudou no onboard

- Substituí o quadrado cyan com **"L"** + texto "Ligbox Onboard" pela **logo oficial** (`ligbox-logo-hero-web.png` — a mesma do site).
- Tamanho: **~37px de altura** (antes ~28px) — um pouco maior, sem ocupar o header.
- Fundo branco suave atrás da logo para ficar legível no header escuro (`#002033`), sem alterar o resto do layout.
- Em mobile reduz ligeiramente (~32px).

### Deploy
Wizard actualizado em `onboard.ligbox.com.br` — faz **Ctrl+Shift+R** para ver.

O canto superior esquerdo deve mostrar a logo **ligbox** completa (ícone + wordmark), com `empresa · dominio.com` à direita como antes.

[REDACTED]