Sessoes 1-6 acumuladas: hardening B2, defesa em camadas, +192 testes
Repositorio estava ha ~5 sessoes sem commit. Consolida tudo desde d088a89.
Ver commit.md na raiz para descricao completa por sessao.
# Numeros
- A# auditoria abertos: 0/30
- V# verificacoes abertos: 5/52 (todos adiados com plano)
- T# testes escritos: 10/10
- Vitest: 192/192
- SQL integration: 33/33
- E2E (Playwright, novo): 5/5
- Migrations: 17 (10 novas Sessao 6)
- Areas auditadas: 7 (+documentos com 10 V#)
# Highlights Sessao 6 (hoje)
- V#34/V#41 Opcao B2: tenant_features com plano + override (RPC SECURITY DEFINER, tela /saas/tenant-features)
- A#20 rev2 self-hosted: defesa em 5 camadas (honeypot + rate limit + math captcha condicional + paranoid mode + dashboard /saas/security)
- Documentos hardening (V#43-V#49): tenant scoping em storage policies (vazamento entre clinicas eliminado), RPC validate_share_token, signatures policy granular
- SaaS Twilio Config (/saas/twilio-config): UI editavel para SID/webhook/cotacao; AUTH_TOKEN permanece em env var
- T#9 + T#10: useAgendaEvents.spec.js + Playwright E2E (descobriu bug no front que foi corrigido)
# Sessoes anteriores (1-5) consolidadas
- Sessao 1: auth/router/session, normalizeRole extraido
- Sessao 2: agenda - composables/services consolidados
- Sessao 3: pacientes - tenant_id em todas queries
- Sessao 4: security review pagina publica - 14/15 vulnerabilidades corrigidas
- Sessao 5: SaaS - P0 (A#30: 7 tabelas com RLS off corrigidas)
# .gitignore ajustado
- supabase/* + !supabase/functions/ (mantem 10 edge functions, ignora .temp/migrations gerados pelo CLI)
- database-novo/backups/ (regeneravel via db.cjs backup)
- test-results/ + playwright-report/
- .claude/settings.local.json (config local com senha de dev removida do tracking)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
<!--
|
||||
|--------------------------------------------------------------------------
|
||||
| Agência PSI
|
||||
|--------------------------------------------------------------------------
|
||||
| Criado e desenvolvido por Leonardo Nohama
|
||||
|
|
||||
| Tecnologia aplicada à escuta.
|
||||
| Estrutura para o cuidado.
|
||||
|
|
||||
| Arquivo: src/views/pages/saas/development/SaasDevelopmentPage.vue
|
||||
| Data: 2026
|
||||
| Local: São Carlos/SP — Brasil
|
||||
|--------------------------------------------------------------------------
|
||||
| © 2026 — Todos os direitos reservados
|
||||
|--------------------------------------------------------------------------
|
||||
-->
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import DevOverviewTab from './DevOverviewTab.vue';
|
||||
import DevRoadmapTab from './DevRoadmapTab.vue';
|
||||
import DevEstruturaTab from './DevEstruturaTab.vue';
|
||||
import DevAuditoriaTab from './DevAuditoriaTab.vue';
|
||||
import DevVerificacoesTab from './DevVerificacoesTab.vue';
|
||||
import DevTestsTab from './DevTestsTab.vue';
|
||||
import DevCompetitorsTab from './DevCompetitorsTab.vue';
|
||||
import DevDatabaseTab from './DevDatabaseTab.vue';
|
||||
import DevExportTab from './DevExportTab.vue';
|
||||
|
||||
const activeTab = ref(0);
|
||||
|
||||
const tabs = [
|
||||
{ key: 'overview', label: 'Visão Geral', icon: 'pi-home', component: DevOverviewTab },
|
||||
{ key: 'roadmap', label: 'Roadmap', icon: 'pi-flag', component: DevRoadmapTab },
|
||||
{ key: 'estrutura', label: 'Estrutura', icon: 'pi-sitemap', component: DevEstruturaTab },
|
||||
{ key: 'auditoria', label: 'Auditoria', icon: 'pi-verified', component: DevAuditoriaTab },
|
||||
{ key: 'verificacoes', label: 'Verificações',icon: 'pi-search', component: DevVerificacoesTab },
|
||||
{ key: 'testes', label: 'Testes', icon: 'pi-check-square',component: DevTestsTab },
|
||||
{ key: 'concorrentes', label: 'Concorrentes',icon: 'pi-globe', component: DevCompetitorsTab },
|
||||
{ key: 'banco', label: 'Banco de Dados',icon: 'pi-database', component: DevDatabaseTab },
|
||||
{ key: 'export', label: 'Exportar', icon: 'pi-download', component: DevExportTab }
|
||||
];
|
||||
|
||||
const activeComponent = computed(() => tabs[activeTab.value]?.component);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dev-page">
|
||||
<!-- Header -->
|
||||
<section class="dev-header">
|
||||
<div class="flex items-center gap-3 mb-1">
|
||||
<div class="grid place-items-center w-10 h-10 rounded-md shrink-0 bg-indigo-500/10 text-indigo-500">
|
||||
<i class="pi pi-code text-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="font-bold text-xl tracking-tight text-[var(--text-color)]">Desenvolvimento</h1>
|
||||
<p class="text-xs text-[var(--text-color-secondary)]">
|
||||
Área interna de trabalho — roadmap, auditoria, concorrentes, banco
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tabs -->
|
||||
<nav class="dev-tabs">
|
||||
<button
|
||||
v-for="(tab, idx) in tabs"
|
||||
:key="tab.key"
|
||||
:class="['dev-tab', { active: idx === activeTab }]"
|
||||
@click="activeTab = idx"
|
||||
>
|
||||
<i :class="['pi', tab.icon]" />
|
||||
<span>{{ tab.label }}</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<!-- Conteúdo da aba -->
|
||||
<section class="dev-content">
|
||||
<component :is="activeComponent" />
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dev-page {
|
||||
padding: 16px 20px 40px;
|
||||
max-width: 1600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dev-header {
|
||||
padding: 10px 14px 14px;
|
||||
background: var(--surface-card, #fff);
|
||||
border: 1px solid var(--surface-border, #e2e8f0);
|
||||
border-radius: 10px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.dev-tabs {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
overflow-x: auto;
|
||||
background: var(--surface-card, #fff);
|
||||
border: 1px solid var(--surface-border, #e2e8f0);
|
||||
border-radius: 10px;
|
||||
padding: 6px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.dev-tab {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 7px 13px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: 7px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-color-secondary);
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.dev-tab:hover {
|
||||
background: color-mix(in srgb, var(--primary-color) 8%, transparent);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.dev-tab.active {
|
||||
background: color-mix(in srgb, var(--primary-color) 12%, transparent);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.dev-tab i {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.dev-content {
|
||||
min-height: 400px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user