diff --git a/Obsidian/Brain/log.md b/Obsidian/Brain/log.md index 2173601..67ca2a4 100644 --- a/Obsidian/Brain/log.md +++ b/Obsidian/Brain/log.md @@ -1648,3 +1648,6 @@ Touched: Migracao Schema-per-Tenant, index ## [2026-06-12 11:49] session | F1 schema-per-tenant: template + helpers + clone Touched: Migracao Schema-per-Tenant + +## [2026-06-13 04:52] session | F3 schema-per-tenant: frontend tenantDb +Touched: Migracao Schema-per-Tenant diff --git a/Obsidian/Brain/wiki/Migracao Schema-per-Tenant.md b/Obsidian/Brain/wiki/Migracao Schema-per-Tenant.md index 9f26fe1..d18e982 100644 --- a/Obsidian/Brain/wiki/Migracao Schema-per-Tenant.md +++ b/Obsidian/Brain/wiki/Migracao Schema-per-Tenant.md @@ -1,6 +1,18 @@ # Migração Schema-per-Tenant -**Status:** F2 concluída e smoke-testada (2026-06-12). Próximo: F3 (frontend useTenantDb). +**Status:** F3 concluída no branch `feat/schema-per-tenant` (2026-06-13, build de produção passa). Próximo: F4 (edge functions). F0-F2 estão em `main`; F3+ no branch até cutover (F5/F6). + +## F3 — entregue (branch feat/schema-per-tenant, migration 07) +- `src/lib/supabase/tenantClient.js` (`tenantDb()`, `tenantSchemaName()`) + `src/composables/useTenantDb.js` +- `tenantStore`: getters `activeTenantSlug`/`activeTenantSchema`; `my_tenants()` RPC agora devolve slug+name (migration 20260612000007) +- codemod `scripts/codemod-tenant-db.py`: `supabase.from('<84 tabelas + 6 views tenant>')` → `tenantDb().from(...)` em 139 arquivos (777 chamadas), removeu 173 `.eq('tenant_id')` de cadeias tenant +- 4 agentes (2 ondas) fizeram a passada manual: tenant_id fora de payloads/selects/.or/.is; onConflict ajustado (singletons → `'singleton'`); realtime de tabelas tenant aponta pro `activeTenantSchema`; repos dropam tenant_id defensivamente de payloads de callers externos +- **descoberta importante: ZERO embeds cross-schema** — todos os FK embeds são tenant→tenant (mesmo schema, ex. `agenda_eventos`→`patients`,`insurance_plans`) ou global→global (`profile_specialties`→`profiles`). O `attachProfiles`/fake-embed do blueprint NÃO é necessário aqui. +- gotcha: `AGENDA_EVENT_SELECT` (constante de select) tinha tenant_id — selecionar coluna inexistente quebra PostgREST; varrer constantes `*_SELECT`, não só `.from()` + +### Pendências F3 (fora do escopo, cross-tenant/anon → tratar em F4/F6) +- `AgendadorPublicoPage.vue` — scheduler público anon, resolve tenant por `link_slug` (precisa RPC/edge de resolução slug→schema, igual channel_routing) +- `Saas{Feriados,NotificationTemplates,DocumentTemplates,Whatsapp}Page.vue` — gerenciam defaults do sistema (tenant_id NULL) ou views cross-tenant; após F6 devem mirar `_tenant_template` ou `channel_routing`. Continuam apontando pra public (funcional até o drop da F6). ## F2 — entregue (migration 20260612000006) Os 3 únicos pontos de criação de tenant (`provision_account_tenant`, `create_clinic_tenant`, `ensure_personal_tenant_for_user` — este último também acionado pelo trigger de signup `handle_new_user_create_personal_tenant`) agora chamam `clone_tenant_template()` na mesma transação: clone falhou → tenant não nasce. Smoke: ensure_personal criou tenant pessoal `tenant_terapeuta_pessoal` com 84 tabelas + registro, 2ª chamada idempotente, drop limpou tudo. Não há fluxo de exclusão de tenant no sistema (drop_tenant_schema fica pra uso admin/manual).