# FastApp Engine Documentation Bundle Source index: https://creator.fastapp.cloud/fastapp/public-docs/llms.txt Versioned LLM/MCP catalog: https://creator.fastapp.cloud/fastapp/public-docs/catalog.json MCP transport: https://creator.fastapp.cloud/api/mcp --- # API Parsers e Exportacao Source file: docs/api-parsers.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/api-parsers Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/api-parsers # API Parsers e Exportacao As APIs dinamicas do FastApp suportam dois fluxos parecidos, mas com usos diferentes: - Parsers inline via `$parser` ou `$format`, usados para transformar a resposta da listagem em texto tecnico. - Exportacao de arquivos via endpoint `/export`, usada pela UI para download em formatos de escritorio. ## Parsers Inline Use parsers quando quiser mudar o corpo da resposta da propria listagem. | Format | Parameter | Content-Type | Description | | :--- | :--- | :--- | :--- | | **JSON** | `json` | `application/json` | Default format. Returns full envelope (`data`, `total`, etc). | | **CSV** | `csv` | `text/csv` | Returns raw records as a CSV table. | | **YAML** | `yaml` | `text/yaml` | Returns raw records in YAML format. | | **Markdown** | `markdown`, `md` | `text/markdown` | Returns GitHub-flavored markdown tables. | Examples: ```http GET /api/v1/data/app/lead?$parser=csv GET /api/v1/data/app/user?$parser=yaml GET /api/v1/data/app/lead/123?$parser=markdown ``` Parsers continuam funcionando com data sources externos: a resposta externa e normalizada antes da transformacao. ## Exportacao De Arquivos Use o endpoint dedicado quando a intencao for baixar arquivo com headers de download: ```http GET /api/v1/data/{app}/{object}/export?format=csv ``` Formatos suportados: | Format | Parameter | Content-Type | | :--- | :--- | :--- | | **CSV** | `format=csv` | `text/csv; charset=utf-8` | | **Excel** | `format=xlsx` | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` | | **PDF** | `format=pdf` | `application/pdf` | | **JSON** | `format=json` | `application/json; charset=utf-8` | O endpoint define `Content-Disposition: attachment` e gera filename usando o template do objeto, por padrao `{app}-{object}-{date}`. ## Escopos | Scope | Uso | | :--- | :--- | | `current_query` | Exporta a consulta filtrada/sortida, ignorando paginacao de tela e respeitando `max_rows`. | | `current_page` | Exporta apenas a pagina atual com `$limit` e `$skip`. | | `selected` | Exporta os IDs enviados em `ids=...`. | Examples: ```http GET /api/v1/data/task-board/task_item/export?format=xlsx&scope=current_query&status=TODO GET /api/v1/data/task-board/task_item/export?format=csv&scope=current_page&$limit=25&$skip=50 GET /api/v1/data/task-board/task_item/export?format=pdf&scope=selected&ids=a1,b2,c3 ``` O endpoint reaproveita filtros, sort, app hint, RBAC, data sources externos, relacoes e campos computed do contrato dinamico de listagem. ## Configuracao Por Objeto Todo objeto nasce exportavel por padrao. Para customizar: ```json { "ui_config": { "export": { "enabled": true, "formats": ["csv", "xlsx", "pdf", "json"], "scopes": ["current_query", "current_page", "selected"], "max_rows": 5000, "include_hidden_fields": false, "filename_template": "{app}-{object}-{date}", "fields": ["id", "nome", "status"] } } } ``` Regras importantes: - `enabled: false` remove o botao e bloqueia o endpoint para o objeto. - `formats` restringe o menu e o servidor. - `scopes` restringe consulta, pagina e selecionados. - `fields` define as colunas exportadas. - `include_hidden_fields` permite incluir campos com `show_in_list: false`. - Propriedades com `exportable: false` nunca entram na exportacao. ## UI O botao de exportacao fica em `CoreExportDataButton` e e usado por: - `CoreDynamicCRUD`, cobrindo tabela, lista, kanban, agenda, mapa e views hibridas. - CMS object views como `object_table`, `object_list`, `object_list_simple`, `object_list_integrated`, `object_kanban` e `object_schedule`. ## Limites - `max_rows` default: `5000`. - PDF limita a tabela renderizada as primeiras colunas para manter legibilidade. - Exportacao massiva/assincrona, relatorios customizados e envio agendado por email ficam fora desta sprint. --- # Autonomous Task Board worker Source file: docs/backlog-agent.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/backlog-agent Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/backlog-agent # Autonomous Task Board worker The local worker polls Task Board, but only acquires cards explicitly moved to `AGENT_READY`. The server control endpoint performs the lease operation in a Firestore transaction. The worker fails closed when that endpoint or its token is unavailable. ## Setup 1. Rotate any credentials previously shared in chat or logs. 2. Deploy the application with a new `TASK_BOARD_AGENT_SHARED_TOKEN` server secret. Use a different, restricted `TASK_BOARD_API_TOKEN` for record reads. 3. Configure the local variables documented in `.env.example`. 4. The default executor adapter invokes `codex exec` ephemerally with the `workspace-write` sandbox. `BACKLOG_AGENT_EXECUTOR_ARGS_JSON` is an argument array; the generated prompt file path is appended as the final argument. 5. Keep `BACKLOG_AGENT_ENABLE_RELEASE=0` until the release, smoke and rollback adapters have been reviewed. Commands are fixed operator configuration and are never generated by the model. Run one polling cycle: ```bash npm run agent:backlog:once ``` Run continuously at the configured interval (30 seconds by default): ```bash npm run agent:backlog ``` Create `.data/backlog-agent/STOP` to pause acquisition without killing the process. After three consecutive failures the circuit breaker pauses polling for five minutes by default. Both thresholds are configurable. ## Release adapter contract The release command must be idempotent for the pair `FASTAPP_AGENT_TASK_ID`/`FASTAPP_AGENT_EXECUTION_ID`, publish through the existing GitHub Release workflow, wait for its result and print a final JSON line containing `commit_sha`, `release_url` and optionally `artifact_url`. The smoke command must exit non-zero on an unhealthy production deployment. The rollback command must restore the previous immutable image. The worker never gives Task Board, Firebase, GitHub or VPS credentials to OpenClaw. OpenClaw receives redacted task context and an MCP capability profile restricted to `readonly` or `operator`. --- # Contexto Exportacao de Dados Source file: docs/export-data/CONTEXT.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/export-data/context Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/export-data/context # Contexto - Exportacao de Dados ## Overview Missao: adicionar exportacao/download de dados nas abas e views do FastApp que mostram registros de objetos. A feature deve respeitar o modelo do produto: apps sao definidos por JSON, objetos sao modulares e o runtime dinamico deve oferecer a capacidade de forma transversal. Branch da sprint: `feat/export-data`, criada a partir da `main`. Estado atual: Sprint concluida na branch `feat/export-data`. Tasks 1 a 8 concluidas e notificadas no Task Board. ## Decisoes Tomadas - O ponto principal da UI deve ser `CoreDynamicCRUD`, porque ele orquestra as views de tabela, lista, kanban, agenda, mapa e hibrida. - A API ja tem parsers (`$parser=csv|yaml|markdown`) em `server/utils/api-parser.ts`; CSV deve ser preservado e endurecido. - A sprint deve adicionar Excel e PDF como formatos reais de arquivo. - A exportacao deve reaproveitar a API dinamica e seus contratos de filtros, sort, app hint, data sources externos, computed fields e RBAC. - Configuracao por objeto deve ser feita em `schema.ui_config.export`, com defaults seguros quando ausente. - Tasks da sprint devem viver no Task Board (`task_item`), nao em arquivos de task separados. ## Evidencias Lidas - `docs/ura-ai/SPEC.md` e `docs/ura-ai/CONTEXT.md` para seguir o modelo SDD. - `task-board-app.json` e `scripts/seed-task-board.mjs` para entender o taskboard como app/objeto `task_item`. - `app/pages/[app]/[module]/[object]/index.vue` para entender carregamento de schema, dados, filtros e app hint. - `app/components/core/DynamicCRUD.vue` para localizar action bar universal, view modes e eventos de CRUD/bulk. - `app/components/core/DynamicTable.vue` para entender DataTable, selecao, filtros e bulk toolbar. - `server/api/v1/data/[app]/[object]/index.get.ts` para entender listagem, data source externo/interno, RBAC, enrichment e parser. - `server/utils/api-parser.ts` e `docs/api-parsers.md` para mapear CSV atual. - `server/utils/query-parser.ts` para filtros, sort e limite. - `server/api/v1/data/[app]/[object]/bulk.patch.ts` e `bulk.delete.ts` para entender selected/query bulk flows. - `server/utils/dynamic-db.ts`, `app/stores/appData.ts`, `server/utils/app-catalog.ts` para confirmar Firestore como storage primario. ## Estado das Tasks ### Fase 0 1. [x] Conferir branch atual e pendencias da URA. - `feat/URA-AI` estava limpa, sem mudancas rastreadas para commitar. 2. [x] Atualizar base e criar branch da sprint. - `main` estava atualizada com `origin/main`. - Branch `feat/export-data` criada a partir da `main`. 3. [x] Ler arquitetura relevante. - Validado pelas evidencias listadas acima. 4. [x] Criar spec/contexto SDD. - Criados `docs/export-data/SPEC.md` e este arquivo. 5. [x] Criar cards no Task Board. - Criados registros `task_item` `[Export Data] Task 1` ate `Task 8`. - `Task 1` ficou em `CONCLUIDA`; `Task 2` a `Task 8` ficaram em `BACKLOG`. - Correcao em 2026-06-05: a primeira criacao foi feita direto no Firestore e usou `app_origem_id: 16`, entao nao passou pelo dispatcher nem casou com a regra de comunicado do app `task-board` (`scope_app_id: 25`). Os cards foram removidos e recriados com `app_origem_id: 25`; a regra ativa `Teste Taskboard` enviou notificacao por email para cada card criado. - Ajuste posterior em 2026-06-05: os templates de alerta de `task_item` passaram a incluir `{{record.descricao}}` no corpo do email. Tambem foram criadas regras de update para o app `task-board` com filtros de status `TODO`, `EM_ANDAMENTO` e `CONCLUIDA`. - Ajuste posterior em 2026-06-05: foi criada tambem a regra generica `Alerta Taskboard - Update Generico`, sem filtro de status, com assunto "Seu card foi atualizado". O endpoint de PATCH agora passa o registro anterior e os campos enviados ao dispatcher, permitindo usar `{{record.__changes_summary}}` no template para listar o que mudou. ### Sprint `feat/export-data` 1. [x] Task 1 - Contexto e planejamento SDD. 2. [x] Task 2 - Contrato server-side de exportacao. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`, validando o corpo com diff de status. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. - Implementado contrato inicial em `server/api/v1/data/[app]/[object]/export.get.ts`. - Criado utilitario `server/utils/export-data.ts` para config default, colunas exportaveis, filename, headers e serializacao CSV/JSON. - Default de formatos por objeto: `csv`, `xlsx`, `pdf`, `json`. Nesta task CSV/JSON ja respondem; XLSX/PDF retornam `501` com mensagem explicita e serao implementados na Task 3. - Testes adicionados em `tests/api/export-data.spec.ts`. - Validacao: `npm run test:api` passou. `npm run build` excedeu 120s e `npx tsc --noEmit -p .nuxt/tsconfig.server.json` nao rodou porque `typescript` nao esta instalado diretamente no projeto. 3. [x] Task 3 - Serializadores CSV/XLSX/PDF/JSON. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. - Instaladas dependencias `exceljs`, `pdfkit` e `@types/pdfkit`. - `server/utils/export-data.ts` agora serializa CSV, JSON, XLSX e PDF. - `server/api/v1/data/[app]/[object]/export.get.ts` responde os quatro formatos do contrato com headers de download. - Testes cobrem buffers XLSX/PDF, CSV com BOM/escape e JSON por colunas. - Validacao: `npm run test:api` passou com 3 arquivos e 11 testes. `npm run build` excedeu 300s. 4. [x] Task 4 - UI universal no CoreDynamicCRUD. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - Implementado botao universal de exportacao no action bar do `app/components/core/DynamicCRUD.vue`, sem duplicar logica nas views filhas. - O menu respeita `schema.ui_config.export.enabled` e `schema.ui_config.export.formats`; quando ausente, todos os objetos continuam nascendo exportaveis com `csv`, `xlsx`, `pdf` e `json`. - O download usa `/api/v1/data/:app/:object/export`, preserva filtros atuais de `route.query`, `fixedFilter` e `appHint`, exibe loading e toasts de sucesso/erro. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. - Validacao: `npm run test:api` passou com 3 arquivos e 11 testes. `npm run build` voltou a exceder 300s. 5. [x] Task 5 - Escopos de exportacao. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - O endpoint `/api/v1/data/:app/:object/export` agora entende `scope=current_query|current_page|selected`. - `current_query` exporta a consulta filtrada ignorando paginacao de tela e usando o limite seguro do schema. - `current_page` respeita `$limit` e `$skip` para baixar apenas a pagina visivel. - `selected` aceita `ids` string ou numericos, busca registros locais por ID sem depender do operador `in` do Firestore e valida o limite maximo antes de gerar arquivo. - O menu de exportacao do `CoreDynamicCRUD` ganhou controle compacto de escopo antes dos formatos, com suporte opcional a `schema.ui_config.export.scopes`. - Testes cobrem resolucao de escopos e IDs mistos. Validacao: `npm run test:api` passou com 3 arquivos e 12 testes. `npm run build` voltou a exceder 300s. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. 6. [x] Task 6 - Cobertura em CMS e views especiais. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - Extraido o menu de exportacao para `CoreExportDataButton`, mantendo o mesmo comportamento do `CoreDynamicCRUD` e permitindo reuso por views que nao passam pelo CRUD universal. - `CoreDynamicCRUD` agora usa `CoreExportDataButton` em vez de manter a logica de exportacao embutida. - `useCmsBinding` passou a expor `queryParams` derivados dos filtros, sort, projection e limit configurados na secao CMS. - `CoreCmsElementProxy` ganhou exportacao para elementos de listagem como `object_list_simple`, `object_list_integrated`, `object_kanban` e `object_schedule`. - `CoreCmsSectionObjectTable` e `CoreCmsSectionObjectList` tambem ganharam o botao de exportacao no cabecalho, preservando filtros/sort da binding CMS. - Validacao: `npm run test:api` passou com 3 arquivos e 12 testes. `npm run build` voltou a exceder 300s. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. 7. [x] Task 7 - Testes e regressao. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM_ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - Extraido helper client-side `app/utils/export-client.ts` para tornar a montagem de query/download do `CoreExportDataButton` testavel sem DOM. - `CoreExportDataButton` passou a usar o helper client-side, reduzindo logica interna e preservando o comportamento visual. - Testes adicionados para formatos/escopos desabilitados, remocao de paginacao em `current_query`, pagina atual, selecionados, IDs de selecao e leitura de filename em `Content-Disposition`. - Validacao: `npm run test:api` passou com 3 arquivos e 16 testes. `npm run build` voltou a exceder 300s. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. 8. [x] Task 8 - Documentacao final e handoff. - Movida para `EM_ANDAMENTO` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update EM_ANDAMENTO` e a regra generica `Alerta Taskboard - Update Generico`. - `docs/api-parsers.md` foi atualizado para documentar a diferenca entre parsers inline (`$parser`/`$format`) e endpoint de download `/export`. - `docs/export-data/SPEC.md` foi atualizado de Gate 1 para spec final da sprint, com decisoes fechadas, endpoint, configuracao JSON, arquivos de handoff e riscos restantes. - Este contexto foi atualizado para refletir conclusao completa da sprint. - Validacao final: `npm run test:api` deve permanecer com 3 arquivos e 16 testes; `npm run build` permaneceu excedendo 300s durante a sprint. - Movida para `CONCLUIDA` em 2026-06-05. O update do card disparou a regra especifica `Alerta Taskboard - Update CONCLUIDA` e a regra generica. ## Proximo Passo Branch `feat/export-data` pronta para validacao manual e posterior merge para `main` quando o usuario aprovar. ## Prompt de Continuacao Voce esta na branch `feat/export-data`. Antes de continuar: 1. Leia `docs/export-data/SPEC.md` e este arquivo inteiro. 2. Confira `git status --short --branch`. 3. Abra o Task Board e confirme os cards `Task 1` ate `Task 8`. 4. Ao criar ou recriar cards do Task Board, use o fluxo da API/dispatcher ou dispare as regras de `comunicado_config` do app `task-board`; nao inserir direto no Firestore sem notificar. 5. So implemente feature code depois da aprovacao do usuario. 6. Sprint implementada em commits pequenos e cards movidos para `CONCLUIDA`. 7. Antes de subir para `main`, validar manualmente os downloads CSV/XLSX/PDF/JSON nos escopos Consulta, Pagina e Selecionados em uma tela dinamica e em uma view CMS. --- # Exportacao de Dados Spec Final Source file: docs/export-data/SPEC.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/export-data/spec Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/export-data/spec # Exportacao de Dados - Spec Final > Status: Sprint implementada na branch `feat/export-data`. --- ## 1. Evidencias Lidas no Repositorio - Stack e arquitetura: `package.json`, `ARCHITECTURE.md`, `app/types/schema.ts`, `app/fastapp/manifest.ts`. - Runtime dinamico: `app/pages/[app]/[module]/[object]/index.vue`, `app/components/core/DynamicCRUD.vue`, `DynamicTable.vue`, `DynamicList.vue`, `DynamicKanban.vue`, `DynamicIntegratedList.vue`. - API dinamica: `server/api/v1/data/[app]/[object]/index.get.ts`, `server/utils/query-parser.ts`, `server/utils/dynamic-db.ts`, `server/utils/data-source-resolver.ts`, `server/utils/legacy-list-contract.ts`, `server/utils/api-parser.ts`. - Bulk e selecao: `server/api/v1/data/[app]/[object]/bulk.patch.ts`, `bulk.delete.ts`, `server/utils/bulk-data.ts`. - RBAC e app scope: `server/middleware/rbac-data-scope.ts`, `server/utils/rbac-data-scope.ts`, `server/utils/user-membership-scope.ts`. - Task Board: `task-board-app.json`, `scripts/seed-task-board.mjs`, objeto `task_item` com `ui_mode: "kanban"`. - SDD interno: `docs/ura-ai/SPEC.md`, `docs/ura-ai/CONTEXT.md`, `app/types/draft-app.ts`, `server/api/apps/wizard-commit.post.ts`. - Estado existente de parsers: `docs/api-parsers.md`, `server/utils/api-parser.ts`. --- ## 2. Como Esta Feature Deve Seguir o Modelo FastApp O sistema e um construtor de apps orientado por objetos no JSON do `app`. A exportacao deve ser uma capacidade transversal do runtime dinamico, nao uma tela hardcoded por cliente. Regras de arquitetura: - O ponto universal de entrada deve ficar no `CoreDynamicCRUD`, porque ele orquestra tabela, lista, kanban, agenda, mapa e views hibridas. - As views filhas (`DynamicTable`, `DynamicList`, `DynamicKanban`, `DynamicIntegratedList`, CMS object views) nao devem duplicar logica de exportacao; elas devem expor dados/estado ao CRUD ou reaproveitar helper comum. - A exportacao precisa respeitar o mesmo contrato de filtros, sort, app hint, RBAC e data source usado por `/api/v1/data/:app/:object`. - O schema do objeto deve poder configurar a capacidade por metadado, com default seguro. Proposta inicial: `schema.ui_config.export.enabled !== false`, `schema.ui_config.export.formats`, `schema.ui_config.export.max_rows`, `schema.ui_config.export.filename_template`, `schema.ui_config.export.include_hidden_fields`. - O comportamento padrao deve funcionar mesmo sem metadado novo: todo objeto de dados que aparece em CRUD/listagem pode exportar CSV e, apos implementacao, XLSX e PDF. Resultado da sprint: a exportacao virou capacidade transversal do runtime, com backend dedicado, UI reutilizavel, cobertura em CMS e testes de regressao. --- ## 3. Objetivo Adicionar uma acao padrao de download/exportacao em todas as abas e views que mostram dados de objetos do FastApp, permitindo baixar os registros visiveis ou a consulta filtrada em formatos comuns de sistemas administrativos. Formatos alvo da sprint: - CSV: aproveitar e endurecer parser existente. - XLSX: planilha Excel real. - PDF: relatorio tabular basico com cabecalho, filtros e colunas. - JSON: opcional no menu para diagnostico/uso tecnico. --- ## 4. Fora de Escopo Inicial - Exportar anexos/binarios de `CoreAssetUpload`. - Criar designer visual de relatorios PDF. - Exportar dashboards graficos como imagem. - Criar agendamento/envio por email. - Exportar milhoes de linhas em processamento assincrono. - Implementar permissao nova sem antes entender o modelo atual de RBAC; a Sprint 1 deve reutilizar read permission/app scope existente. --- ## 5. Estado Atual Ja existe suporte parcial a parsers na API dinamica: - `$parser=csv`, `$format=csv`: retorna CSV via `server/utils/api-parser.ts`. - `$parser=yaml`, `$parser=markdown`: existem para usos tecnicos. Limites do estado atual: - `CoreDynamicCRUD` usa `CoreExportDataButton` no action bar. - CSV de export usa schema para labels, ordem, visibilidade e `exportable`. - XLSX/PDF foram adicionados com `exceljs` e `pdfkit`. - O endpoint dedicado decide entre consulta filtrada, pagina atual e selecionados. - Headers de download e filename estao formalizados no helper server-side. --- ## 6. UX Proposta No action bar do `CoreDynamicCRUD` e nas views CMS de objeto, ha botao com icone `pi pi-download` e tooltip "Exportar". Ao clicar, abre menu compacto com: - "CSV" - "Excel" - "PDF" - "JSON" Escopos de exportacao: - Consulta filtrada: refaz request com filtros/sort atuais e limite de export. - Pagina atual: envia `$limit` e `$skip` atuais. - Selecionados: envia `ids=...` quando houver selecao ativa. O default da UI e "Consulta filtrada" com limite seguro e feedback de loading, sucesso e erro. --- ## 7. Contrato de API Proposto Manter compatibilidade com parsers existentes e adicionar endpoint dedicado para formatos que precisam de headers/arquivo: - `GET /api/v1/data/:app/:object/export?format=csv|xlsx|pdf|json` - Query normal de filtros/sort: mesmos parametros de `index.get.ts`. - `scope=current_query|current_page|selected` - `ids=...` quando `scope=selected`. - `fields=campo1,campo2` opcional. - `include_hidden=0|1` Reaproveitamento: - Usar `resolveObjectDataSource`, `resolveObjectSchema`, `parseQueryParams`, `mergeRbacWhereConstraint`, enriquecimento de relacoes/computed e fallback interno/externo do endpoint de listagem. - Serializacao centralizada em `server/utils/export-data.ts`. Headers: - `Content-Type` correto por formato. - `Content-Disposition: attachment; filename="--."`. - BOM UTF-8 para CSV quando necessario para Excel. --- ## 8. Modelagem em App JSON Adicionar suporte a metadado opcional por objeto: ```json { "ui_config": { "export": { "enabled": true, "formats": ["csv", "xlsx", "pdf", "json"], "scopes": ["current_query", "current_page", "selected"], "max_rows": 5000, "include_hidden_fields": false, "filename_template": "{app}-{object}-{date}", "fields": ["id", "nome", "status", "created_at"] } } } ``` Defaults quando ausente: - `enabled: true` para objetos de dados com CRUD/lista. - `formats: ["csv", "xlsx", "pdf", "json"]`. - `scopes: ["current_query", "current_page", "selected"]`. - `max_rows: 5000`. - Campos exportados: `show_in_list !== false`, mais `id`, respeitando ordem do schema; campos `object/json/array/inner_collection` devem ser serializados de forma segura ou excluidos no PDF. --- ## 9. Permissionamento e Seguranca - Exportacao deve passar pelos mesmos middlewares e constraints de leitura. - Nao deve permitir burlar filtros de app/membership via query. - `include_hidden_fields` so pode ser respeitado se o usuario tiver permissao administrativa ou se o schema permitir explicitamente. - Exports de objetos externos devem encaminhar query sanitizada, como a listagem. - Limites de linhas e tamanho de arquivo devem ser aplicados no servidor. - Campos sensiveis podem ser bloqueados por metadado futuro: `exportable: false` em `PropSchema`. --- ## 10. Sprint `feat/export-data` ### Task 1 - Contexto e planejamento SDD - Concluida Aceite: - Branch `feat/export-data` criada a partir da `main`. - `docs/export-data/SPEC.md` e `CONTEXT.md` criados. - Cards da sprint criados no Task Board. - Nenhum feature code implementado antes da aprovacao. ### Task 2 - Contrato server-side de exportacao - Concluida Aceite: - Endpoint ou parser dedicado de export definido e coberto por testes. - CSV existente preservado sem quebrar `docs/api-parsers.md`. - Headers de download e filename implementados. - Filtros, sort, app hint e RBAC continuam aplicados. ### Task 3 - Serializadores CSV/XLSX/PDF/JSON - Concluida Aceite: - CSV usa labels/ordem do schema e lida com valores especiais. - XLSX gera arquivo abrivel no Excel/Sheets. - PDF gera relatorio tabular basico com cabecalho, data e colunas visiveis. - JSON baixa envelope ou linhas de forma documentada. - Dependencias novas justificadas e minimizadas. ### Task 4 - UI universal no CoreDynamicCRUD - Concluida Aceite: - Botao de export aparece em views de dados sem duplicacao por view. - Menu de formatos respeita `schema.ui_config.export`. - Estado de loading/toast para sucesso/erro. - Funciona em tabela, lista, kanban e pagina dinamica padrao. ### Task 5 - Escopos de exportacao - Concluida Aceite: - Exportar consulta filtrada com sort atual. - Exportar pagina atual quando configurado. - Exportar selecionados quando houver selecao. - Limites e mensagens claras quando exceder max rows. ### Task 6 - Cobertura em CMS e views especiais - Concluida Aceite: - `object_table`, `object_list_simple`, `object_kanban` no CMS nao perdem comportamento. - Dashboards/listagens customizadas sao avaliadas e documentadas. - Onde export nao for aplicavel, a UI nao mostra acao quebrada. ### Task 7 - Testes e regressao - Concluida Aceite: - Testes API para formatos, filtros, sort, selected ids, RBAC e limite. - Teste de componente ou E2E minimo para menu/botao. - `npm run test:api` passa. ### Task 8 - Documentacao final e handoff - Concluida apos commit desta task Aceite: - `docs/api-parsers.md` atualizado. - `docs/export-data/CONTEXT.md` atualizado com o que foi feito. - Cards movidos para `CONCLUIDA` ao concluir cada task. - Commits pequenos por task com mensagens claras. --- ## 11. Decisoes Fechadas e Riscos Restantes 1. XLSX/PDF sao gerados no servidor para preservar RBAC, filtros e exportacao da consulta sem depender de cache local. 2. Dependencias escolhidas: `exceljs` para XLSX e `pdfkit` para PDF. 3. Limite inicial default: `max_rows=5000`, configuravel por objeto. 4. A Sprint 1 reutiliza permissao/escopo de leitura; permissao `export` dedicada fica como evolucao futura. 5. Campos computed e relacionamentos sao enriquecidos antes da serializacao. 6. Campos exportados seguem `show_in_list !== false`, `fields`, `include_hidden_fields` e `exportable: false`. 7. `npm run build` nao concluiu dentro de 300s durante a sprint; `npm run test:api` passou com 16 testes. --- ## 12. Handoff - Endpoint principal: `server/api/v1/data/[app]/[object]/export.get.ts`. - Helpers server-side: `server/utils/export-data.ts`. - Botao reutilizavel: `app/components/core/ExportDataButton.vue`. - Helpers client-side testaveis: `app/utils/export-client.ts`. - Cobertura UI dinamica: `app/components/core/DynamicCRUD.vue`. - Cobertura CMS: `app/components/core/cms/CoreCmsElementProxy.vue`, `CoreCmsSectionObjectTable.vue`, `CoreCmsSectionObjectList.vue`. - Testes: `tests/api/export-data.spec.ts`. - Documentacao operacional: `docs/api-parsers.md`. Para validar manualmente, abrir qualquer tela de objeto, clicar no icone de download e testar CSV, Excel, PDF e JSON nos escopos Consulta, Pagina e Selecionados quando houver selecao. --- # FastApp Agent Project Bootstrap Source file: docs/FASTAPP_AGENT_PROJECT_BOOTSTRAP.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/fastapp-agent-project-bootstrap Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/fastapp-agent-project-bootstrap # FastApp Agent Project Bootstrap This document defines the first structured LLM/MCP-ready agent surface for FastApp. ## Goal Expose one agent that can: - Read public FastApp documentation. - Inspect existing apps. - Create or update a generic app through Nuxt APIs. - Operate records inside a generic app through `/api/v1/data/:app/:object`. ## Why This Layer Exists The existing `fastapp-agent` route is useful as a prompt-driven playground, but it is not a stable integration contract for external orchestration. A project-level agent surface needs: - A fixed agent identity. - A typed tool catalog. - Machine-readable input schemas. - A deterministic execution endpoint. - Public discovery routes that LLM and MCP wrappers can consume. ## First Agent Agent id: `fastapp-generic-app-operator` Responsibilities: - Retrieve public docs before acting. - Inspect apps before mutating them. - Create or patch apps through `/api/app`. - List, create, patch, and delete records through `/api/v1/data`. - Apply granular schema mutations for modules, objects, properties, relations, actions, and pages. - Manage permissions and memberships through structured RBAC tools. ## Routes Public discovery: - `/fastapp/public-docs/llms.txt` - `/fastapp/public-docs/manifest.json` - `/fastapp/public-docs/agents.json` Execution: - `GET /api/agent/catalog` - `POST /api/agent/execute` - `GET /api/mcp` - `POST /api/mcp` ## MCP Transport `POST /api/mcp` exposes a JSON-RPC transport over the same agent registry and executor. It does not define a second tool contract; `tools/list` reads `server/utils/agents/registry.ts` and `tools/call` forwards execution to `/api/agent/execute`. Supported methods: - `initialize` - `tools/list` (`listTools` alias) - `tools/call` (`callTool` alias) Example `tools/call` payload: ```json { "jsonrpc": "2.0", "id": "1", "method": "tools/call", "params": { "agentId": "fastapp-generic-app-operator", "name": "create_record", "arguments": { "app": "crm", "object": "lead", "data": { "name": "Ada" } }, "dryRun": true } } ``` Write behavior is inherited from `/api/agent/execute`: writes default to dry-run previews, RBAC is enforced by the underlying Nuxt routes, and execution/audit logs are emitted by the agent executor plus the MCP adapter. ## Tool Model Each tool definition contains: - `name` - `title` - `description` - `readOnly` - `api` binding to an existing Nuxt route - `inputSchema` - optional `examples` The executor validates input against the declared schema before forwarding the call to the underlying Nuxt API. ## Tool Families - Discovery: public docs and app catalog lookup. - App lifecycle: create, patch, delete full apps. - App schema: upsert and delete modules, objects, properties, relations, actions, and pages. - Data: list, create, patch, and delete generic object records. - Data intelligence: aggregate, profile, and suggest filters for any object using the same generic data route and RBAC constraints. - RBAC: list roles, permissions, and memberships; create/update/delete permissions; assign/update/remove memberships. Current limitation: - Role creation is still blocked by the existing backend policy in `/api/v1/data/:app/role`. ## Dry Run Support `POST /api/agent/execute` accepts `dryRun: true`. In dry-run mode the executor does not mutate state. It returns the exact internal request shape that would be sent to the Nuxt API. This is useful for: - tool debugging - MCP wrappers - approval workflows - prompt iteration ## Current Orchestration Status Implemented in the unified `/api/fastapp-agent` route: - Server-side multi-step tool loop over the shared agent catalog. - Server-managed prompt assembly with a small frontend instruction hint. - Compiled generic app context for object/property/relation/action ranking. - Conditional planner and verifier calls to reduce token usage on simple requests. - Write-policy handling that converts backend mutations to dry-run previews unless explicit confirmation is present. - Generic record field matching through aliases, normalized names, property metadata, and semantic schema scoring. - Frontend `ui_apply_filters` action that syncs tool queries to generic table/list filters and sort. - Generic data intelligence tools: `aggregate_records`, `profile_object_data`, and `suggest_filters`. - Dynamic CRUD view capability context so the agent can see generic filter/sort/search/write support, active fields, metric fields, date fields, relation fields, and current query state. - Resilient agent routing: stale browser `agent_id` values fall back to `fastapp-generic-app-operator`, and the frontend Copilot scopes saved execution agents to the app that produced them. - App-scoped data routes in the playground legacy path instead of hardcoded object-only endpoints. ## Suggested Next Steps 1. Add persistent per-user/per-app agent memory for compressed summaries, preferences, and previous decisions. 2. Add structured frontend result cards for aggregate/profile/list tool outputs instead of relying on assistant prose parsing. 3. Add a dedicated frontend approval UI for dry-run write previews. 4. Keep MCP clients aligned with `/api/agent/catalog` and `/api/agent/execute` as tools evolve. 5. Continue migrating remaining legacy playground delta/data action flows to structured tool previews. 6. Add pgvector-backed schema/document retrieval when compiled context ranking is not enough. --- # Contexto de Trabalho Jean / FastApp Source file: docs/jean/CONTEXTO.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/docs/jean/contexto Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/docs/jean/contexto # Contexto de Trabalho - Jean / FastApp Este documento registra o modo generico de trabalho no projeto FastApp. Ele deve servir para qualquer sprint, sem depender de uma feature especifica. ## Principios - O FastApp e um construtor de apps orientado por objetos em JSON. - Objetos viram CRUDs, views, formularios, automacoes, dados e experiencias dinamicas. - A IA deve entender o sistema antes de implementar: ler a Task 1 da sprint, arquitetura, schemas, componentes dinamicos e APIs relevantes. - O desenvolvimento segue Spec Driven Development, mas as tasks executaveis da sprint vivem no Task Board dinamico da FastApp. - A partir deste fluxo, o contexto especifico da sprint deve estar na Task 1 do Task Board. Nao criar arquivos de sprint como `docs//CONTEXT.md` ou `docs//SPEC.md`, salvo se o usuario pedir explicitamente. - A Task 1 deve conter tudo que a IA precisa para entender a sprint: objetivo, arquivos a ler, arquitetura impactada, regras, riscos, criterios de aceite e plano macro. ## Fluxo de Sprint 1. Criar branch a partir da `main`, com nome `feat/`. 2. Conferir `git status --short --branch` antes de qualquer alteracao. 3. Ler `docs/jean/CONTEXTO.md`, `docs/jean/PROMPTSTART` e a Task 1 da sprint. 4. Criar cards no Task Board com titulo, descricao completa e prompt otimizado. 5. Ao criar/mover cards, respeitar o painel de Comunicados. Cards nao devem ser inseridos de forma silenciosa sem disparar regras configuradas. 6. Mover a task para `EM_ANDAMENTO` antes de implementar. 7. Fazer commits pequenos e claros na branch da sprint. 8. Fazer push para o GitHub a cada entrega importante. 9. Ao concluir uma task, mover o card para `CONCLUIDA` e garantir notificacao. 10. Ao fim da sprint, trazer `main` para a branch, validar, levar a sprint para `main` e criar release quando o usuario pedir. ## Task Board - App: `task-board`. - Objeto: `task_item`. - Cards devem ter prefixo da sprint, por exemplo: `[Nome Sprint] Task 1 - Contexto e arquitetura`. - A Task 1 e obrigatoria e deve ser o contexto completo da sprint. - O contexto da sprint deve ficar no corpo da Task 1, nao em arquivo separado. - As demais tasks devem quebrar a entrega em blocos pequenos e commitaveis. - Status padrao: - `BACKLOG` - `TODO` - `EM_ANDAMENTO` - `CONCLUIDA` - Sempre preencher: - `titulo` - `descricao` - `prompt_otimizado` - `feature` - `taxonomia_n1` - `taxonomia_n2` - `taxonomia_n3` - `prioridade` - `status` - `ordem` - `app_origem_id` ## Comunicados O painel de Comunicados e parte do fluxo de trabalho. - Criacao de card deve notificar. - Update de card deve notificar. - Mudanca para `TODO`, `EM_ANDAMENTO` e `CONCLUIDA` deve notificar por regra especifica. - Update generico deve enviar email tipo "Seu card foi atualizado" com resumo do que mudou. - Se uma operacao precisar ser feita via script, o script deve reproduzir as regras ativas de `comunicado_config`. ## Commits - Commits devem ser pequenos, rastreaveis e associados a uma task. - Mensagens recomendadas: - `docs: add working process context` - `feat: add ` - `test: cover ` - `docs: finalize handoff` - Depois de cada commit importante, fazer `git push origin `. ## Como a IA Deve Agir - Trabalhar de forma autonoma quando a tarefa estiver clara. - Buscar contexto no repo antes de assumir arquitetura. - Usar padroes existentes do FastApp em vez de criar uma arquitetura paralela. - Preferir `rg` para buscas. - Usar `apply_patch` para edicoes manuais. - Nao reverter alteracoes do usuario. - Validar com testes disponiveis. - Reportar claramente quando `npm run build` ou outro comando nao concluir. - Manter o usuario informado com updates curtos durante trabalhos longos. ## Arquivos Para Entender a FastApp Leia estes arquivos antes de iniciar uma sprint que mexe em objetos, CRUDs, formularios, CMS, API dinamica ou automacoes: - `package.json` - `ARCHITECTURE.md` - `app/types/schema.ts` - `app/pages/[app]/[module]/[object]/index.vue` - `app/pages/[app]/[module]/index.vue` - `app/components/core/DynamicCRUD.vue` - `app/components/core/DynamicForm.vue` - `app/components/core/DynamicTable.vue` - `app/components/core/DynamicList.vue` - `app/components/core/DynamicKanban.vue` - `app/components/core/FieldRenderer.vue` - `app/components/core/PropertyField.vue` - `app/components/core/cms/CoreCmsRenderer.vue` - `app/composables/useCmsBinding.ts` - `server/api/v1/data/[app]/[object]/index.get.ts` - `server/api/v1/data/[app]/[object]/index.post.ts` - `server/api/v1/data/[app]/[object]/[id].patch.ts` - `server/utils/dynamic-db.ts` - `server/utils/query-parser.ts` - `server/utils/meta-resolver.ts` - `server/utils/meta-validation.ts` - `server/utils/rbac-data-scope.ts` - `server/utils/data-source-resolver.ts` - `server/utils/comunicado-dispatcher.ts` - `task-board-app.json` ## Task 1 Como Fonte De Contexto Toda sprint deve ter uma Task 1 dedicada a contexto. Ela deve responder: - Qual e o objetivo da sprint? - Por que isso importa para o produto? - Quais arquivos a IA deve ler antes de implementar? - Quais objetos, componentes, APIs e schemas podem ser impactados? - Quais decisoes tecnicas ja estao assumidas? - Quais duvidas ou riscos precisam ser resolvidos? - Quais sao os criterios de aceite da sprint? - Quais sao as tasks seguintes e a ordem sugerida? Se a sessao cair, se outra IA assumir ou se houver perda de contexto, a IA deve retomar lendo `docs/jean/CONTEXTO.md`, `docs/jean/PROMPTSTART` e a Task 1 da sprint no Task Board. --- # 🤖 FastApp Agent — Arquitetura e Guia Técnico Source file: AGENT_ARCHITECTURE.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/agent-architecture Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/agent-architecture # 🤖 FastApp Agent — Arquitetura e Guia Técnico > **Visão:** O FastApp Agent não é apenas um chatbot. É uma camada de inteligência que lê, entende e modifica a própria estrutura de um app em tempo real — com parsing de linguagem natural, execução de APIs e feedback visual imediato. --- ## 1. Os Dois Agentes Atuais | Agente | Arquivo | Propósito | |--------|---------|-----------| | **AI Architect (entrypoint)** | `pages/fastapp/agent.vue` | Entrada especializada que redireciona para o runtime unificado em modo `architect` | | **Agent Playground (runtime unificado)** | `pages/fastapp/agent-playground.vue` | Ambiente completo: presets, scopes, live data, delta parsing, execução de ações | | **Frontend AI Copilot** | `components/ai/copilot/FrontendAICopilotSidebar.vue` | Copilot global da UI (modo `client`) desacoplado do runtime de arquitetura/playground | O **Playground é a evolução** — é nele que o roteamento de agentes, os formatos de delta e a execução de APIs estão implementados de forma mais robusta. --- ## 2. Arquitetura Geral ``` ┌─────────────────────────────────────────┐ │ AGENT PLAYGROUND │ │ │ │ ┌──────────┐ ┌────────────────────┐ │ │ │ Presets │ │ Scope Selector │ │ │ │ Architect│ │ App/Módulo/Objeto │ │ │ │ DataAsst │ │ /Propriedade │ │ │ └────┬─────┘ └────────┬───────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────────────────────┐ │ │ │ System Prompt Builder │ │ │ │ systemPrompt + deltaFormat │ │ │ │ + contextJson (scoped schema) │ │ │ │ + liveData (se ativo) │ │ │ └────────────────┬────────────────┘ │ │ │ │ │ ▼ │ │ POST /api/fastapp-agent │ │ │ │ │ ▼ │ │ ┌────────────────────────────────┐ │ │ │ Delta Parser │ │ │ │ parseDeltaBlocks() → │ │ │ │ text | delta cards │ │ │ └────────────────┬───────────────┘ │ │ │ │ │ ┌─────────┴──────────┐ │ │ ▼ ▼ │ │ Render Markdown DeltaCard UI │ │ (marked + shiki) + Botão Executar │ │ │ │ │ ┌──────────┘ │ │ ▼ │ │ executeDataAction() → │ │ /api/v1/data/{object} │ └─────────────────────────────────────────┘ ``` --- ## 3. Contexto: O que o Agente Recebe ### 3.1 System Prompt (composto dinamicamente) ``` [System Prompt do Preset] --- FORMAT --- [Delta Format Prompt] --- SCHEMA DO APP --- ```json { scopedContext } // JSON do escopo selecionado ``` --- LIVE DATA (se ativo) --- ```json [ { registros ao vivo } ] ``` --- APIS DISPONÍVEIS --- - GET /api/v1/data/{object} - POST /api/v1/data/{object} - PATCH /api/v1/data/{object}/{id} - DELETE /api/v1/data/{object}/{id} ``` ### 3.2 Escopos de Contexto (`scopedContext`) O Playground tem 4 escopos configuráveis que determinam **o que o agente vê**: | Escopo | O que envia para o LLM | |--------|------------------------| | `app` | Manifesto completo do app (objetos, módulos, páginas) | | `module` | Módulo + seus objetos resolvidos | | `object` | Schema JSON de um único objeto (propriedades, relações, ações) | | `property` | Definição de uma única propriedade | > 💡 **Regra de ouro:** sempre use o menor escopo possível. Enviar o schema de um único objeto é muito mais eficiente do que todo o app. --- ## 4. Formatos de Output do LLM O agente aceita **dois formatos** de resposta: ### 4.1 AGENT_DELTA (Schema Mutations) Usado pelo agente **Architect** para alterar a estrutura do app: ``` ### AGENT_DELTA ```json { "action": "ADD_OBJECT", "name": "ativo", "label": "Ativo Financeiro", "properties": [ { "name": "codigo", "type": "string", "required": true }, { "name": "valor", "type": "number", "content_type": "currency" } ] } ``` ``` **Actions disponíveis:** | Action | O que faz | |--------|-----------| | `ADD_OBJECT` | Cria ou atualiza um objeto no draft | | `ADD_PROPERTY` | Adiciona/atualiza uma propriedade em um objeto | | `ADD_MODULE` | Cria ou atualiza um módulo | | `ADD_RELATION` | Adiciona uma relação entre objetos | | `ADD_ACTION` | Adiciona uma ação customizada a um objeto | | `ADD_PAGE` | Adiciona uma página ao app | | `DELETE` | Marca um objeto/módulo para remoção | ### 4.2 DATA_ACTION (Execução de APIs) Usado pelo agente **Assistente de Dados** para operar em registros reais: ```json { "action": "DATA_ACTION", "method": "GET", "object_name": "lead", "endpoint": "/api/v1/data/lead", "payload": {} } ``` ```json { "action": "INSIGHT", "category": "anomalia | padrao | oportunidade | alerta", "label": "Título", "description": "Análise baseada nos dados", "affected_records": [1, 2, 3], "recommended_action": "O que fazer" } ``` ### 4.3 SUGGESTION (Próximos Passos) Qualquer agente pode emitir sugestões no formato: ``` [SUGGESTION: Texto da sugestão] ``` São coletadas e renderizadas como bloco de navegação ao fim da resposta. --- ## 5. Parser: Como Funciona o `parseDeltaBlocks()` O parser é um **state machine** que processa a resposta raw do LLM: ``` Raw LLM Response │ ├── Tokeniza por regex: ```json {...} ``` │ ├── Para cada bloco JSON: │ ├── tryParseJson() → tem campo "action"? │ │ ├── SIM → DeltaCard (renderizado como card interativo) │ │ └── NÃO → Bloco de código normal (renderizado por shiki) │ ├── Para texto plano entre blocos: │ └── flush() → busca markers AGENT_DELTA legados │ └── Brace-counter para isolar JSON │ └── SUGGESTION extractor → bloco de sugestões ``` ### Limpeza de JSON (`cleanJson`) O LLM frequentemente gera JSON "sujo" com: - Comentários inline (`// isso é um campo`) - Trailing commas (`{ "a": 1, }`) O `cleanJson()` remove ambos antes de fazer `JSON.parse()`. --- ## 6. Merging Engine (`useFastappArchitect`) O draft de schema funciona em **camada de sessão sobre a base persistida**: ``` Base (banco de dados) Session (memória local) ┌────────────────────┐ + ┌────────────────────┐ │ objects: [...] │ │ sessionObjects: [...] │ │ modules: [...] │ │ sessionModules: [...] │ │ pages: [...] │ │ sessionPages: [...] │ └────────────────────┘ └────────────────────┘ │ │ └──────────────────────────┘ │ mergedApp (computed) │ (session tem prioridade) ``` **Flags de merge:** - `_is_new`: objeto criado na sessão, não existe na base - `_is_modified`: objeto modificado na sessão - `_deleted`: marcado para deleção - `_full_properties_override`: substitui lista inteira em vez de fazer merge ### Schema Sanitizer (`validateAndSanitizeSchema`) Antes de aceitar qualquer JSON do LLM, o sanitizer: 1. Resolve `name` de múltiplos aliases (`name`, `key`, `entity_name`, `object_name`) 2. Injeta defaults de Ontologia v3 (`semantic`, `topology`, `engine`, `provider`) 3. Filtra propriedades inválidas (nome igual ao objeto, `name`, `key`) 4. Normaliza tipos de relação (`inner_collection` → `has_many`) 5. Auto-deriva `foreign_key` se não fornecida --- ## 7. Agent Presets System O Playground define um sistema de **presets de agente** salvos no `localStorage`: ```typescript interface AgentPreset { id: string; name: string; systemPrompt: string; // Personalidade e regras do agente deltaFormatPrompt: string; // Como o agente deve estruturar outputs analysisPrompt: string; // Para análise de imagens (Vision) model: string; // 'gpt-4o', 'gpt-4o-mini', etc. temperature: number; // 0 = determinístico, 1 = criativo liveDataMode?: boolean; // Se deve buscar dados reais automaticamente } ``` **Built-in presets:** - **Architect**: Foco em schema, usa AGENT_DELTA, temperature 0.2 - **Assistente de Dados**: Foco em dados, usa DATA_ACTION, ativa liveDataMode **Presets customizados** são salvos no localStorage e persistem entre sessões. --- ## 8. Input Multimodal ### Voz (Whisper STT) 1. `startRecording()` → `MediaRecorder` captura áudio do microfone 2. `AudioContext + AnalyserNode` → waveform visualizer em tempo real 3. `stopRecording()` → Blob enviado para `POST /api/transcribe` 4. Transcrição populada no input (se estava vazio, dispara `sendMessage()` automaticamente) ### Imagem (Vision) 1. Upload de imagem → base64 armazenado em `uploadedImage` 2. Enviado junto com o prompt para o LLM como conteúdo multimodal 3. `analysisPrompt` do preset define o comportamento de análise visual --- ## 9. Fluxo Completo de uma Interação ``` 1. Usuário digita/fala → userInput 2. sendMessage(): a. Monta system prompt (preset + delta format + schema + live data) b. POST /api/fastapp-agent com chat_history + new_prompt c. SSE streaming → tokens aparecem em tempo real no chat 3. Resposta recebida → parseDeltaBlocks(): a. Texto → renderizado com marked() + shiki syntax highlighting b. DeltaCards → cards interativos com botão "Executar" 4. Usuário clica "Executar" em um DeltaCard: a. AGENT_DELTA → applyDelta() → mergedApp atualizado no canvas b. DATA_ACTION → executeDataAction() → chamada real para /api/v1/data/{object} 5. Se DATA_ACTION retorna sucesso: a. Mensagem automática para o LLM notificando sucesso b. liveData atualizado em background ``` --- ## 10. O que Funciona Bem Hoje ✅ **Parser robusto** — suporta markdown, código, AGENT_DELTA legado e `action` em JSON puro ✅ **Merging não-destrutivo** — sessão sobre base, nunca perde dados ✅ **Schema sanitizer** — agente pode enviar aliases variados, sistema normaliza ✅ **Presets salvos** — agentes customizados persistem no browser ✅ **Scoped context** — token budget controlado, agente recebe só o necessário ✅ **Data Agent vivo** — executa CRUD real em qualquer objeto do app ✅ **Voz integrada** — Whisper STT com feedback visual de áudio ✅ **Vision** — análise de imagens para modelagem de schema --- ## 10.1 Estado Atual da Inteligencia AI Implementado em 2026-04-16: 1. **Prompt server-managed**: o frontend envia apenas um hint curto; `/api/fastapp-agent` monta o prompt completo com contexto, regras, ferramentas e politica de escrita. 2. **Compiled generic app context**: `server/utils/agents/compiled-context.ts` compila qualquer manifesto em objetos, aliases, propriedades, relacoes, acoes, rotas e campos de lookup. 3. **Context ranking**: o backend prioriza os objetos mais relevantes para o prompt e para o escopo ativo antes de enviar contexto ao modelo. 4. **Native tool loop**: o agente executa ferramentas estruturadas do catalogo por tool calling, incluindo UI, schema, dados, RBAC, automacao e agentes por objeto. 5. **Write policy seguro**: mutacoes backend usam preview/dry-run por padrao e exigem confirmacao explicita para execucao real. 6. **Token optimization**: planner e verifier agora sao condicionais; requests simples evitam chamadas auxiliares quando nao agregam valor. 7. **Generic app/data handling**: o playground e a automacao usam rotas app-scoped e inferencia semantica de campos, sem depender de nomes hardcoded de apps ou objetos. 8. **Frontend table/filter sync**: `ui_apply_filters` aplica filtros, busca e ordenacao na rota/query da tabela ativa; no playground, leituras continuam retornando a lista filtrada no chat. 9. **Generic data intelligence tools**: `aggregate_records`, `profile_object_data` e `suggest_filters` calculam metricas, agrupamentos, perfis de campos e candidatos de filtro para qualquer objeto. 10. **Dynamic view capability context**: o CRUD dinamico publica capacidades genericas da tela ativa (`canFilter`, `canSort`, `canSearch`, `canCreate`, `canUpdate`), campos ativos, campos de metrica, datas, relacoes e query atual. 11. **Agent routing resiliente**: `/api/fastapp-agent` cai para `fastapp-generic-app-operator` quando um `agent_id` salvo no browser nao existe no app ativo; o Copilot tambem escopa o execution agent salvo por app para evitar vazamento entre apps. Arquivos principais: - `server/api/fastapp-agent.post.ts` - `server/utils/agents/compiled-context.ts` - `server/utils/agents/data-intelligence-tools.ts` - `server/utils/agents/record-automation-tools.ts` - `app/components/fastapp/FastappAgentChat.vue` - `app/composables/useFastappAgent.ts` - `app/pages/fastapp/agent-playground.vue` - `app/utils/fastapp-agent-orchestration.ts` --- ## 11. Gaps Atuais e Melhorias Propostas ### 🔴 Crítico | Gap | Impacto | Solução Proposta | |----|---------|-----------------| | **Memória persistente ainda limitada** | O backend comprime histórico e aceita `conversation_memory`, mas não persiste memória longa por app/usuário | Persistir resumos e preferências por app, usuário e agente | | **Delta legado ainda existe** | O fluxo moderno usa tools, mas o playground ainda precisa suportar AGENT_DELTA para compatibilidade | Migrar gradualmente cards legados para previews/tool calls estruturados | | **Validação schema ainda parcial** | Algumas mutações passam por sanitizer, mas nem toda regra de `PropSchema` é validada antes do commit | Validator server-side completo antes de aplicar schema/data mutations | ### 🟡 Importante | Gap | Solução Proposta | |----|-----------------| | **RAG vetorial ainda não implementado** | Indexar objetos/props no pgvector quando o compiled context não for suficiente | | **Sem streaming de DeltaCards** | DeltaCards aparecem só no fim da resposta — mostrar incrementalmente | | **Presets no localStorage** | Migrar para banco para persistir entre devices | | **Result cards estruturados parciais** | Listagens ja tem apresentacao melhor no chat, mas aggregates/profiles ainda dependem mais da resposta textual do modelo | | **Confirmação visual de writes** | O backend ja gera dry-run/approval; falta UI dedicada para revisar e confirmar previews | ### 🟢 Futuro | Feature | Descrição | |---------|-----------| | **Tool: `apply_migration`** | Agente propõe e executa migrations de banco via Prisma | | **Tool: `create_dashboard`** | Agente cria widgets de BI a partir de uma pergunta | | **Agentes autônomos** | Multi-step planning: agente decompõe tarefa em subtasks, executa em paralelo | --- ## 12. Plano de Evolução (Roadmap) ### Fase 1 — Foundation (próximas semanas) - [x] **Migrar para Tool Use**: catalogo + executor + tool loop em `/api/fastapp-agent` - [x] **Context Compression**: resumo compacto de historico e prompt server-managed - [x] **Write Preview Policy**: dry-run para writes backend sem confirmacao explicita - [x] **Frontend Filter Sync**: filtros/ordenacao do agente aplicam na tabela generica via `ui_apply_filters` - [x] **Generic Data Intelligence Tools**: agregacao, perfil de dados e sugestao de filtros para qualquer objeto - [x] **Dynamic View Capability Context**: CRUD dinamico informa capacidades e campos da tela ativa ao agente - [x] **Embed Mode inicial**: Frontend AI Copilot usa o chat em modo `client` - [ ] **Persistent Context**: persistir memoria comprimida entre sessoes/devices - [ ] **Delta Validator**: validacao completa contra tipos do schema antes de commit ### Fase 2 — RAG & Context Intelligence (trimestre) - [x] **Compiled Schema Context**: ranking generico de objetos/propriedades/relacoes/acoes - [ ] **Schema Embeddings**: indexar objetos/props no pgvector - [ ] **Semantic Search**: agente busca contexto relevante ao invés de enviar tudo - [ ] **Cross-app Context**: agente pode consultar schemas de múltiplos apps ### Fase 3 — Autonomous Agents (semestre) - [x] **Planner Agent inicial**: planner condicional para tarefas complexas/architect - [x] **Executor Loop**: executa ferramentas genericas de schema, data, UI e RBAC - [x] **Approval Flow backend**: writes viram preview/dry-run sem confirmacao explicita - [ ] **Executor Agents especializados**: Schema Agent, Data Agent, UI Agent independentes - [ ] **Agent Orchestrator paralelo**: coordena multiplos agentes em paralelo ### Fase 4 — Universal Scope - [ ] **Agent por App**: cada app configura seus próprios agentes com regras de negócio - [ ] **Agent API**: `POST /api/{app}/agent` para integrar agentes via webhook externo - [ ] **Trigger-based Agents**: agentes ativados por eventos (novo registro, mudança de status) --- ## 13. Aplicando em Qualquer App Para usar o agente em um app específico: ```typescript // 1. Selecionar o app await selectAppContext(appId); // 2. Definir escopo focado scopeType.value = 'object'; scopeTargetKey.value = 'ativo'; // Nome do objeto // 3. Aplicar preset adequado applyAgent(BUILT_IN_AGENTS.find(a => a.id === 'data-assistant')); // 4. O agente automaticamente: // - Recebe o schema do objeto "ativo" // - Lista as APIs disponíveis para esse objeto // - Busca registros reais (liveDataMode) // - Está pronto para consultas em linguagem natural ``` --- ## 14. APIs Backend | Endpoint | Método | Função | |----------|--------|--------| | `/api/fastapp-agent` | POST | Proxy LLM com SSE streaming | | `/api/v1/data/{object}` | GET/POST | CRUD genérico | | `/api/v1/data/{object}/{id}` | PATCH/DELETE | Operações por ID | | `/api/transcribe` | POST | Whisper STT (áudio → texto) | | `/api/app/{id}` | PATCH | Atualizar schema do app | | `/api/system/snapshot` | POST | Gerar static-manifest.ts | --- > **Princípio Guia:** O agente é uma **interface de linguagem sobre o schema**. Qualquer coisa que um usuário possa configurar manualmente no Architect deve poder ser solicitada em linguagem natural ao agente — e executada com um clique de confirmação. --- # 🛰️ ANTIGRAVITY GUIDELINES — As Leis da Abstração Soberana (v3.1) Source file: ANTIGRAVITY_GUIDELINES.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/antigravity-guidelines Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/antigravity-guidelines # 🛰️ ANTIGRAVITY GUIDELINES — As Leis da Abstração Soberana (v3.1) > "Se algo é repetitivo, deve ser abstraído; se é específico, deve ser generalizado. Se é generalizável, o motor deve fazê-lo sozinho." Este documento consolida a filosofia de desenvolvimento do Fastapp Engine. Ele orienta como o Arquiteto IA e os desenvolvedores colaboradores devem atuar para reduzir o boilerplate através da **Escada de Abstração** e da **Auto-Evolução**. --- ## 1. O Princípio da Generalização Soberana 1. **Abstração > Customização**: Soluções genéricas no Core atendem múltiplos domínios via esquema. Evite "if (app === 'crm')". Em vez disso, use "if (object.has_feature('kanban'))". 2. **Esquema Governa a UI**: Nenhuma funcionalidade é "solta". Para cada comportamento em tela (ex: `is_sortable`, `is_filterable`), deve existir um metadado correspondente que o habilite. 3. **Fastapp como Modelo 0**: O Schema Manager é construído sobre as mesmas abstrações que oferece. Evoluir o Schema Manager é evoluir o motor para todos os inquilinos. 4. **Persistent DevShell**: Ferramentas de arquitetura (Sidebars de Design) devem ser Singleton Globais localizadas no Layout principal, garantindo estabilidade durante navegações e snapshots sem perda de estado. --- ## 2. Camadas de Core (A Escada de Abstração) As camadas do Core definem os níveis de inteligência e responsabilidade do motor: * 🟣 **Core L1 — Atômico**: Renderização pura de tipos e semânticas (money, phone, email, asset). * 🔵 **Core L2 — Padrões**: Kanban, Sidebars de edição, Layouts adaptativos baseados em `crud_mode` e comportamentos padronizados de CRUD. * 🟢 **Core L3 — Orquestração**: Lógica complexa de recursos e logística (routing_type, geo_constraints, alocação geotemporal). Automatização de UX baseada em Taxonomia Semântica. --- ## 3. Orquestração de Dados (DataSources) O sistema utiliza a abstração de **Conectividade** para gerenciar dados internos e externos: - **DataSource Object**: Define `type` (REST, Internal, GraphQL), `base_url`, `auth_strategy` (Bearer, API Key, Laravel Proxy) e headers globais. - **Vinculação**: Um App ou Object aponta para um `datasource_id`. Alterar a infraestrutura (ex: mudar o host do Laravel) exige apenas uma mudança no DataSource, refletindo em todos os objetos vinculados. - **Vantagem**: Desacoplamento total entre a definição da taxonomia e a infraestrutura física de rede. --- ## 4. Protocolo FADAP 3.0 (Sovereign Sync & DDL) A evolução estrutural segue um fluxo de estado atômico, soberano e OBRIGATORIAMENTE via API. Não há atalhos. 1. **Mutação (Sovereign Patch)**: Alterações estruturais (campos, objetos, workflows, crud_mode) ocorrem EXCLUSIVAMENTE via `PATCH /api/app/[id]` no Nuxt. 2. **Snapshot (Consolidação)**: Geração do `static-manifest.ts` disparada via `POST /api/system/snapshot`. **É a única forma de garantir que o runtime veja a nova estrutura.** 3. **DDL Automation**: Para objetos `nature: physical`, a criação ou alteração de tabelas é disparada pelo motor Nuxt APÓS o Patch de metadados, garantindo consistência. 4. **Estado & Cache**: O sistema invalida caches imediatamente após o snapshot. > [!CAUTION] > **Integrity Pitfall**: Nunca manipule o banco de dados diretamente ou edite o `static-manifest.ts`. Se você ignorar a API, criará um "drift" entre o Desejo (Metadados) e a Realidade (DB), quebrando o motor. > [!CAUTION] > **Integrity Pitfall**: Falhas no salvamento de metadados complexos (ex: arrays aninhados) podem corromper o esquema no banco. O `static-manifest.ts` é a sua "Fonte da Verdade" para recuperação (Disaster Recovery). --- ## 11. Defensive Dynamic Rendering (L1/L2) A renderização dinâmica deve ser resiliente a metadados incompletos ou malformados: 1. **Label Fallback**: Nunca assuma que `prop.label` existe. Use `prop.label || prop.name || ''` para evitar `TypeError: can't access property toUpperCase`. 2. **Multiplicity Logic Core**: - Toda propriedade do tipo `array` ou `inner_collection` deve ser considerada `isAttachedMany` por padrão. - A ausência de `foreign_object` não deve impedir a detecção de multiplicidade para tipos de coleção. 3. **Data Hydration Guards**: No `DynamicForm`, garanta que o pulso de dados inicial (`initialValues`) seja sanitizado antes de ser injetado no rastro de reatividade do Vee-Validate/Zod. --- ## 12. Metadata Integrity & Recovery 1. **Sovereign Restore**: Se o banco de dados for corrompido ou o salvamento via Arquiteto IA falhar de forma catastrófica, o procedimento de restauração deve ser: - Extrair o objeto íntegro do `static-manifest.ts`. - Realizar um `PATCH` manual/via script ignorando campos de auditoria (created_at/updated_at). - Disparar `/api/system/snapshot`. 2. **Validation before Writing**: Futuras evoluções do Core devem validar a integridade estrutural (Schema-of-Schemas) no motor Nuxt antes de persistir no DB. --- ## 5. Alinhamento Laravel (Identity & RBAC) O Laravel provê a inteligência de governança que o Nuxt interpreta: - **Identity Authority**: O Laravel define quem acessa o quê (`User` & `UserApp`). - **Dynamic RBAC**: Permissões (`fastapp_permission`) são exportadas para o Nuxt no payload do `me()` ou JWT. - **Data Sovereignty**: O Laravel governa o Domínio Externo (APIs de referência como Central Filtros) enquanto o Nuxt governa os Metadados e a execução de DDL. --- ## 6. Atributos de Comportamento (Ontologia v3) | Atributo | Valores | Impacto no Motor (Behavior) | | :--- | :--- | :--- | | **crud_mode** | `modal`, `sidebar`, `page` | Define onde o `CoreDynamicForm` será renderizado. | | **layout_grid** | `col-span-12`, `6`, `4`, `3` | Define a largura responsiva do campo no formulário (Grid de 12 colunas). | | **semantic** | `money`, `asset`, `point` | Ativa máscaras, uploads ou mapas (`CoreMapRenderer`). | | **routing_type**| `waypoint`, `route` | Ativa inteligência logística e cálculo de ETAs. | | **provider** | `local`, `external-api`| Define se o dado vem do Prisma local ou do Laravel/Externo. | --- ## 7. AI Mutation Guard & Fetch Rule > [!CAUTION] > **Fetch before Modify**: Sempre execute `GET /api/app/[id]` antes de propor mudanças para garantir o estado real da taxonomia e evitar sobrescrever metadados de outros agentes/usuários. > [!IMPORTANT] > **O Princípio da Mutação Soberana**: Para alterar a estrutura do próprio FastApp (Builder, Editores, Workflows), você deve realizar o `PATCH` no **App ID 16**. O motor aprende e evolui alterando seu próprio esquema. > [!IMPORTANT] > O motor aprende com cada app. O sucesso do Arquiteto IA é medido pela quantidade de código deletado em favor de metadados interpretados. --- ## 8. Arquitetura de Performance (Architect Sync) Para garantir que o Arquiteto IA seja fluido, seguimos estas regras de sincronização: 1. **Memory Memoization**: Evite `JSON.parse(JSON.stringify())` em cada pulso de reatividade. Utilize clones profundos apenas no início da sessão ou em trocas de contexto. 2. **Debounced Mutations**: Alterações em metadados granulares (como labels ou grid) devem ser disparadas com debounce (mínimo 300ms) para evitar layout thrashing. 3. **Reactive Bridges**: Páginas e componentes devem apenas "publicar" o esquema ativo no `systemStore.activeObjectSchema`, delegando a renderização da ferramenta de edição ao motor global. --- ## 9. UX Singleton Pattern (The Designer Hub) Para garantir uma experiência de desenvolvimento sem fricção: 1. **Fixed Shell Principle**: O Sidebar de Arquitetura deve ser persistente. Ele nunca deve ser destruído durante a navegação entre Table e Form de um mesmo objeto. 2. **Stateless Bridging**: O componente designer não possui estado próprio; ele é um espelho profundo do `activeObjectSchema` do sistema. 3. **No-Modal Architecting**: Evite modais para edição de metadados. Use sidebars fixos que permitam ao designer observar o impacto visual das mudanças no formulário dinâmico em tempo real. --- ## 10. Taxonomy-Driven GUI (Semantic Layer) A interface deve se adaptar automaticamente com base na taxonomia dos dados: 1. **Topology Awareness**: Componentes de lista devem detectar se o objeto é `root` (vários registros) ou `attached-one` (exibição de detalhes aninhados) e ajustar o layout automaticamente. 2. **Semantic Rendering**: O `CoreDynamicForm` deve priorizar atributos de semântica (ex: `semantic: asset` gera dropzone, `semantic: identity` gera destaque de cabeçalho). 3. **Visual Hierarchy**: Áreas de configuração no Sidebar devem seguir a hierarquia: Identidade (Quem) → Atributos (O quê) → Motor (Como) → Agente (Para quem). --- # 🏛️ APP HIERARCHY — A Pirâmide de Metadados Source file: APP_HIERARCHY.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/app-hierarchy Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/app-hierarchy # 🏛️ APP HIERARCHY — A Pirâmide de Metadados Este guia detalha a anatomia rigorosa de uma "Aplicação" no Fastapp Engine. A estrutura de metadados é o DNA que permite ao motor renderizar interfaces dinâmicas com inteligência. --- ## 🏛️ A Pirâmide de Abstração O sistema segue uma hierarquia de quatro níveis: 1. **App**: A unidade de negócio (ex: "CRM Flux", "Gestão de Ativos"). 2. **Module**: Agrupamento lógico de navegação (ex: "Comercial", "Configurações"). 3. **Object**: A entidade mestre de dados (ex: "Lead", "Broker", "Tarefa"). 4. **Property**: Os campos individuais que compõem o objeto (ex: "Nome", "Status"). --- ## 📦 1. App (`App`) O container principal da experiência do usuário. - `slug`: Identificador único usado na URL (ex: `/app/crm-flux`). - `objects`: Lista de definições de objetos disponíveis. - `modules`: Estrutura de navegação (sidebar) que organiza o acesso aos objetos. - `pages`: Lista de páginas customizadas ou dinâmicas integradas. - `provider`: Estratégia de dados padrão do app (`local` | `external-api`). - `is_api_data_source`: Flag de compatibilidade para forçar fonte externa. - `api_base_url`: URL base opcional para rotear `/api/v1/data/:object` para API externa. ## 🧱 2. Objeto (`SystemObject`) Define o comportamento da entidade na UI e no Storage. - `name`: Nome técnico em snake_case (ex: `crm_lead`). - `category`: [Master | Transactional | Configuration] (Ver `DATA_TAXONOMY.md`). - `nature`: [Physical | Embedded | Virtual] (Ver `DATA_TAXONOMY.md`). - `crud_mode`: [Modal | Page | Inline] (Define como o formulário de edição abre). - `provider`: Override de fonte de dados no nível do objeto. - `is_api_data_source`: Flag de compatibilidade para ativar API externa no objeto. - `api_url`: URL externa completa para este objeto (prioridade sobre `api_base_url` do app). - `api_path`: Path de recurso opcional quando o app já define `api_base_url`. ## 🏷️ 3. Propriedades (`Property`) Os átomos que definem o dado e sua validação. - `type`: [String | Number | Boolean | Enum | Date | Array | Json]. - `semantic`: [asset | money | percentage | phone | email | url | color | cpf | cnpj]. (Ver `DATA_TAXONOMY.md`, Ontologia v3) - `layout_grid`: Classes PrimeFlex/Tailwind para posicionamento (ex: `col-span-12 md:col-span-6`). - `show_in_list`: Visibilidade na tabela/lista principal. - `required`: Validação obrigatória em tempo de execução. ## 📄 4. Páginas (`Page`) Definem rotas integradas ao menu dinâmico. - `type: 'custom'`: Aponta para arquivo físico em `pages/` (ex: `/crm/leads`). - `type: 'dynamic_crud'`: Gera rota automática para o objeto alvo. - Atributos: `name`, `label`, `icon`, `path`, `component_key`. --- ## 🔗 Relacionamentos (`Relation`) Como os objetos se conectam entre si: - **has_many**: Relação 1:N (Ex: Um Lead tem muitas Tarefas). - **belongs_to**: Relação N:1 (Ex: Uma Tarefa pertence a um Lead). - **associates_with**: Relação N:N (Ex: Leads e Tags). ### Estratégias de Persistência - `reference_id`: Salva o ID do objeto relacionado (Chave Estrangeira). - `document_embed`: Salva o filho inteiro dentro do JSON do pai (usado com `nature: embedded`). --- > "Estruturar bem o metadado é garantir que o motor trabalhe para você, não contra você. Com a Ontologia v3, o metadado governa não só a persistência, mas também a renderização, a navegação e a inteligência artificial." --- # 🏛️ Fastapp Engine — Arquitetura Source file: ARCHITECTURE.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/architecture Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/architecture # 🏛️ Fastapp Engine — Arquitetura > Documento vivo. Atualizado para refletir o motor **Anti-Gravity** e a **Sovereign Navigation Architecture**. --- ## Visão Geral O **Fastapp Engine** é uma fábrica de aplicações. O motor genérico (Core) interpreta definições JSON e renderiza CRUD, formulários, tabelas e navegação automaticamente. Seguimos uma abordagem de **Escada de Abstração** (Core L1, L2, L3) para garantir que a complexidade seja tratada pelo motor, e não pela customização. ### 📚 Dimensões de Documentação - [🛰️ **Diretrizes Anti-Gravity**](./ANTIGRAVITY_GUIDELINES.md): O Norte e as Leis de Abstração. - [🏛️ **Hierarquia e Metadados**](./APP_HIERARCHY.md): Estrutura de App, Module, Object e Property. - [🧬 **Taxonomia de Dados**](./DATA_TAXONOMY.md): A semântica que governa o comportamento. - [🔌 **Protocolo Fadap**](./FADAP_PROTOCOL.md): Sincronização entre Metadados e Storage. - [🔄 **Sistema de Workflow**](./WORKFLOW_SYSTEM.md): Manual técnico de fluxos Human-Led. - [🧭 **Sistema de Tutoriais**](./TUTORIAL_SYSTEM.md): Onboarding interativo com Driver.js. - [📱 **WAHA Integration**](./WAHA_INTEGRATION.md): Camada de infraestrutura para WhatsApp (envio + webhook). - [📣 **Sistema de Comunicados**](./COMUNICADO_SYSTEM.md): Painel de regras de notificacao por evento (e-mail + WhatsApp). ```mermaid graph TB subgraph "A Fábrica (Fastapp Engine)" SEED["🌱 Seed / Builder"] SNAPSHOT["📸 Snapshot"] API["🔌 API Dinâmica v1"] CORE["⚙️ Core Components"] STORE["🗃️ System Store"] end subgraph "Modelo 01 (CRM Flux)" CRM_PAGES["📊 Dashboard + Kanban"] CRM_COMPS["🧩 Lead Components"] CRM_STORE["💾 Lead Store + Offline"] end subgraph "Modelo 02...N (Futuro)" FUTURE["🎫 Helpdesk, 📦 Inventário..."] end SEED --> SNAPSHOT --> STORE SEED --> API STORE --> CORE API --> CORE CORE --> CRM_PAGES CORE --> FUTURE CRM_COMPS --> CRM_PAGES CRM_STORE --> CRM_PAGES style SEED fill:#dc2626,color:#fff style CORE fill:#4338ca,color:#fff style API fill:#059669,color:#fff style SNAPSHOT fill:#7c3aed,color:#fff ``` --- ## Stack | Camada | Tecnologia | Versão | |--------|-----------|--------| | Framework | Nuxt 4 | `^4.3.1` | | UI Components | PrimeVue (Aura) | `^4.5.4` | | CSS | Tailwind CSS 3 + CSS custom properties | `^3.4.19` | | State (Global / UI) | Pinia (`system.ts`) | `^0.11.3` | | State (Data L3) | Pinia (`appData.ts`) | **SWR + Request Coalescing** | | Utilities | VueUse (`@vueuse/nuxt`) | `^14.2.1` | | Forms | VeeValidate + Zod | `^4.15.1` / `^3.25.76` | | Drag & Drop | vuedraggable | `^4.0.1` | | Realtime | Socket.IO (client + server) | `^4.8.3` | | ORM | Prisma | `^6.2.1` | | DB | PostgreSQL (Supabase) | — | --- ## Hierarquia: App → Module → Object → Property ```mermaid erDiagram APP ||--o{ MODULE : "contains" APP ||--o{ OBJECT : "defines" MODULE ||--o{ OBJECT_REF : "references" OBJECT ||--|{ PROPERTY : "has" APP { string name string slug boolean is_active boolean is_frozen } OBJECT { string name string label string type string crud_mode string key_property string label_property } PROPERTY { string name string label string type string content_type boolean required boolean show_in_list boolean show_in_form } ``` --- ## Taxonomia Semântica de Objetos Cada object no Fastapp é classificado por **3 eixos** independentes: ### 1. Categoria Semântica (`object.category`) Define o "comportamento de vida" do dado no ecossistema: | Categoria | Descrição | Exemplo | Impacto no Gerador | |-----------|-----------|---------|-------------------| | `master` | Dado mestre, estável, base para outros | Broker, AssetClass, User | Caches, dropdowns globais, busca por nome | | `transactional` | Eventos, registros de fluxo, alta volatilidade | Transaction, Lead, UserAsset | Índices por data, logs de auditoria, filtros de período | | `configuration` | Parâmetros do sistema ou do usuário | AppSettings, WalletProfile | Interfaces simplificadas ("Settings Page") | ### 2. Natureza Arquitetural (`object.nature`) Define **onde** o dado mora fisicamente: | Natureza | Armazenamento | Comportamento | |----------|--------------|---------------| | `physical` | Tabela própria no DB | ID único global, referenciável por qualquer um | | `embedded` | Dentro do JSON do pai | Sem tabela própria; morre se o pai for deletado | | `virtual` | Calculado em runtime | Agregações (ex: total_balance do usuário) | ### 3. Relacionamentos (`object.relations[]`) **Tipos de Vínculo:** | `relation.type` | Semântica | Exemplo | |-----------------|-----------|---------| | `belongs_to` | Referência a um master ou pai | UserAsset → Broker | | `has_one` | Propriedade de um filho único | User → WalletProfile | | `has_many` | Propriedade de uma coleção | WalletProfile → UserAsset[] | | `associates_with` | Relação N:N | Tag ↔ Lead | **Estratégias de Persistência:** | `relation.storage` | Como se salva | Quando usar | |---------------------|---------------|-------------| | `reference_id` | Salva apenas o ID (FK relacional) | Dados independentes | | `document_embed` | Salva o objeto inteiro no JSON | Dados acoplados ao pai | | `pivot` | Tabela intermediária | Relação N:N | ### Matriz Category × Nature ```mermaid graph TD subgraph "master" M_P["physical
Broker, AssetClass
Tabela própria"] M_E["embedded

(raro)"] M_V["virtual

(raro)"] end subgraph "transactional" T_P["physical
Lead, UserAsset
Tabela c/ índices"] T_E["embedded
Transaction
JSON no pai"] T_V["virtual
TotalBalance
Calculado"] end subgraph "configuration" C_P["physical
WalletProfile
Tabela simples"] C_E["embedded
AppSettings
JSON no App"] C_V["virtual

(raro)"] end style M_P fill:#059669,color:#fff style T_P fill:#2563eb,color:#fff style T_E fill:#7c3aed,color:#fff style T_V fill:#d97706,color:#fff style C_P fill:#64748b,color:#fff ``` ### Exemplo Concreto: App Gestão de Ativos ```mermaid erDiagram BROKER ||--o{ USER_ASSET : "belongs_to (reference_id)" ASSET_CLASS ||--o{ USER_ASSET : "belongs_to (reference_id)" USER_ASSET ||--|{ TRANSACTION : "has_many (document_embed)" WALLET_PROFILE ||--o{ USER_ASSET : "has_many (reference_id)" BROKER { string name string cnpj category master nature physical } ASSET_CLASS { string name enum risk_level category master nature physical } USER_ASSET { string ticker number quantity number avg_price category transactional nature physical } TRANSACTION { date date enum type number quantity number price category transactional nature embedded } WALLET_PROFILE { string name number target_conservative category configuration nature physical } ``` --- ## Meta-API & Gestão de Sistema Além do CRUD de dados (`/api/v1/data`), o Fastapp expõe endpoints de gestão para evoluir a própria estrutura do sistema em tempo de execução. ### 1. Snapshot (`POST /api/system/snapshot`) - **Função**: Gera uma "foto" estática do estado atual do banco (Apps, Objetos, Campos) em `app/fastapp/static-manifest.ts`. - **Uso**: Freeze de versão para produção ou backup de schema. ### 2. Schema Evolution (`PATCH /api/app/:id`) - **Função**: Permite alterar definições de objetos (adicionar campos, mudar layout) via API. - **Uso**: Editores visuais (Builder) ou scripts de migração (ex: `apply-layout-grid.ts`). ### 3. Storage Adaptation (`POST /api/data/:object/storage`) [Planejado] - **Função**: Analisa a definição do objeto e executa DDL (Create/Alter Table) para alinhar o banco físico. - **Uso**: Transformar um objeto "Generic" (JSON) em "Native" (Tabela SQL) para performance, sem reiniciar o servidor. ### 4. Admin Portal (Ferramentas de Gestão) - **Schema Manager**: Interface visual para editar Apps e Objetos (`PATCH /api/app`). Alavanca componentes dinâmicos para editar a si mesmo. - **API Tester**: "Mini Postman" integrado para testar endpoints do sistema (`/api/v1/data`) e validar respostas. - **AI Laboratory 🧪**: Versão evoluída do Agent Playground. Permite simular personas, gerir blueprints temporários (Laboratory Manifesto) e persistir contextos de análise LLM no LocalStorage. ### 5. Custom Pages & Dynamic Routing - **Configuração**: O manifesto suporta uma lista de `pages`. - **Roteamento**: - `page.type === 'custom'`: Aponta para um arquivo físico em `pages/`. - `page.type === 'dynamic_crud'`: Gera automaticamente a rota para o objeto. - **Visibilidade**: O `AppMenu.vue` resolve essas rotas dinamicamente para o sidebar. --- ## Fluxo de Runtime — Onde vive a inteligência ```mermaid sequenceDiagram participant URL as Browser URL participant Page as Dynamic Page participant Store as System Store participant Static as static-manifest.ts participant API as /api/app (GET) participant DataAPI as /api/v1/data/:object participant DynDB as dynamic-db.ts participant NativeModel as Prisma Model (Lead) participant RecordTable as Record Table (Generic) URL->>Page: /crm/crm/lead Page->>Store: fetchDefs() Page->>AppData: fetchObjectData('lead') - non-blocking SWR Note over AppData: Checking for pending promises... alt Already fetching (Request Coalescing) AppData-->>Page: await the same existing promise ✓ else Not in cache AppData->>DataAPI: GET /api/v1/data/lead?$limit=100 DataAPI-->>AppData: Data[] AppData-->>Page: Hydrated data ✓ end alt is_static (Snapshot ativo) Store->>Static: import StaticManifest Static-->>Store: App[] (instantâneo) else is_live (Dev / sem snapshot) Store->>API: GET /api/app API-->>Store: App[] (do banco) end Store-->>Page: objectSchema resolved Page->>DataAPI: GET /api/v1/data/lead DataAPI->>DynDB: isNativeModel("lead")? alt Modelo nativo existe DynDB->>NativeModel: prisma.lead.findMany() NativeModel-->>DataAPI: Lead[] else Modelo genérico (ex: tarefa) DynDB->>RecordTable: prisma.record.findMany(object_name) RecordTable-->>DataAPI: Record[] → flatten JSON end DataAPI-->>Page: data[] ``` --- ## API Dinâmica v1 ### Endpoints | Rota | Método | Descrição | |------|--------|-----------| | `/api/v1/data/:object` | GET | Lista (com filtros e ordenação via query params) | | `/api/v1/data/:object` | POST | Cria (com validação meta-driven) | | `/api/v1/data/:object/:id` | GET | Busca por ID | | `/api/v1/data/:object/:id` | PATCH | Atualiza (com validação) | | `/api/v1/data/:object/:id` | DELETE | Remove | ### Estratégia Híbrida: Native vs Generic ```mermaid graph LR REQ["Request /api/v1/data/:object"] META["meta-validation.ts
Resolve properties do manifest"] DYN["dynamic-db.ts
isNativeModel?"] subgraph "Caminho A: Native" PRISMA["prisma.lead / prisma.app
Model dedicado"] end subgraph "Caminho B: Generic" RECORD["prisma.record
data: Json + object_name"] FLATTEN["Flatten: {id, ...data, timestamps}"] end REQ --> META --> DYN DYN -->|"lead, app"| PRISMA DYN -->|"tarefa, contato, ..."| RECORD --> FLATTEN style PRISMA fill:#059669,color:#fff style RECORD fill:#7c3aed,color:#fff ``` - **Native**: objetos com model Prisma dedicado (`lead`, `app`). Performance máxima. - **Generic**: objetos criados no Builder. Usam tabela `Record` com `data Json`. Zero setup. ### Validação Meta-Driven ```mermaid graph TD BODY["Request Body"] --> RESOLVE["resolveObjectProperties(name)"] RESOLVE --> VALIDATE["validateBody(body, properties)"] VALIDATE -->|"required fields"| CHECK_REQ["Campos obrigatórios presentes?"] VALIDATE -->|"type checking"| CHECK_TYPE["string/number/boolean correto?"] CHECK_REQ -->|"❌"| ERR400["400: Validation failed"] CHECK_TYPE -->|"❌"| ERR400 VALIDATE -->|"✓"| CLEAN["cleanBody(body, properties)"] CLEAN -->|"strip _tabId, unknowns"| SAVE["Save to DB"] style ERR400 fill:#dc2626,color:#fff style SAVE fill:#059669,color:#fff ``` ### Filtragem & Ordenação (URL-Driven) A API aceita filtros e ordenação via query params. O frontend usa a URL como **fonte única de verdade**. **Query Parser** (`server/utils/query-parser.ts`): O motor agora prioriza o formato **Flattened** para query strings, facilitando a integração com APIs externas. | Operador | Formato Flat (Soberano) | Formato Legado (Legacy) | Descrição | |----------|----------------|----------------|-----------| | `=` | `?campo=valor` | `?filters[campo][=]=valor` | Igualdade simples | | `ne` | `?campo[ne]=valor` | `?filters[campo][$ne]=valor` | Diferente | | `gt` / `gte` | `?campo[gt]=5` | `?filters[campo][$gt]=5` | Maior que / Maior ou igual | | `lt` / `lte` | `?campo[lt]=10` | `?filters[campo][$lte]=10` | Menor que / Menor ou igual | | `like` | `?campo[like]=mario`| `?filters[campo][$like]=mario` | Busca textual (Case Insensitive) | | `between`| `?campo[between]=a,b`| `?filters[campo][between]=a,b` | Intervalo de valores | **Paginação e Ordenação Soberana:** | Parâmetro | Tipo | Descrição | Exemplo | |-----------|------|-----------|---------| | `$limit` | `number` | Quantidade de registros por página | `?$limit=50` | | `$skip` | `number` | Quantidade de registros a pular | `?$skip=100` | | `$sort[f]`| `1 / -1`| Ordenação (1=ASC, -1=DESC) | `?$sort[name]=1` | | `granularity`| `string`| Resolução temporal para BI | `?granularity=week` | **Coerção automática**: `"true"` → `boolean`, `"42"` → `number`, `"null"` → `null`. **Fluxo URL-Driven:** ```mermaid sequenceDiagram participant User as Usuário participant Filter as CoreDynamicFilter participant URL as URL (query params) participant Page as index.vue participant API as /api/v1/data/:object participant Table as CoreDynamicTable Note over Filter: onMounted → readFromUrl() User->>Filter: Seleciona campo, operador, valor Filter->>URL: router.replace({ query }) URL->>Page: watch(route.query) dispara Page->>API: GET /api/v1/data/lead?filters[status][=]=NOVO API-->>Page: data[] filtrado Page->>Table: :data="data" Note over URL: URL bookmarkável e compartilhável ``` - **Native models**: filtros viram cláusula `where` do Prisma (performático) - **Generic records**: filtros aplicados in-memory após fetch (JSON field) --- ## Sistema de Snapshot ```mermaid sequenceDiagram participant Admin as Admin Panel participant API as POST /api/system/snapshot participant DB as PostgreSQL participant FS as Filesystem participant Store as System Store Admin->>API: Clique "Gerar Snapshot" API->>DB: prisma.app.findMany() DB-->>API: App[] (com modules/objects JSON) API->>FS: writeFileSync(static-manifest.ts) FS-->>API: Arquivo gerado API-->>Admin: Toast "Snapshot gerado!" Note over Store: No próximo boot (produção): Store->>FS: import StaticManifest Note over Store: is_static = true, sem DB ``` ### Smart Store — Prioridade de Dados | Condição | Fonte | `is_static` | |----------|-------|-----------| | `StaticManifest.length > 0` + produção | Arquivo estático | `true` | | Dev mode (`import.meta.dev`) | API `/api/app` | `false` | | API falha + manifest existe | Arquivo estático (fallback) | `true` | | Nenhum manifest + API ok | API `/api/app` | `false` | ### `is_frozen` no App Cada App pode ter `is_frozen: true`. Quando congelado, o sistema ignora a API e usa exclusivamente o arquivo estático — simulando produção "compilada". --- ## Componentes Core ```mermaid graph TD subgraph "Navegação Soberana" HUB["CoreBuilderHub
Top bar contextual"] MENU["CoreAppMenu
Sidebar colapsável"] end subgraph "Orquestração" CRUD["CoreDynamicCRUD
mode: modal|page|inline"] end subgraph "Visualização" TABLE["CoreDynamicTable
columns via show_in_list"] LIST["CoreDynamicList
edição in-place"] end subgraph "Filtros" FILTER["CoreDynamicFilter
URL-driven, adaptive inputs"] end subgraph "Formulário" FORM["CoreDynamicForm
VeeValidate + Zod runtime"] FIELDS["CoreDynamicFields
recursivo, layout vertical|inline"] RENDERER["CoreFieldRenderer
type → PrimeVue"] end subgraph "Ferramentas do Arquiteto" ARCHITECT["FastApp Architect
Schema Studio v3"] FLOW["FastApp Flow
Visual Metadata Explorer"] AGENT["FastApp Agent
Enterprise AI Copilot"] end HUB -->|contexto builder| ARCHITECT & FLOW & AGENT MENU -->|contexto navegação| CRUD CRUD --> TABLE & LIST CRUD -->|Dialog| FORM FORM --> FIELDS FIELDS -->|inner_collection| FIELDS FIELDS --> RENDERER style CRUD fill:#4338ca,color:#fff style FORM fill:#059669,color:#fff style HUB fill:#0a0d14,color:#e2e8f0,stroke:#4338ca style ARCHITECT fill:#6366f1,color:#fff style FLOW fill:#2563eb,color:#fff style AGENT fill:#7c3aed,color:#fff ``` ### Props & Eventos | Componente | Props | Eventos | |-----------|-------|---------| | `CoreDynamicCRUD` | `schema`, `data`, `mode`, `objectName` | `create`, `update`, `delete`, `edit-click` | | `CoreDynamicTable` | `schema`, `data` | `edit`, `delete` | | `CoreDynamicList` | `schema`, `data`, `editable` | `edit`, `delete`, `update` | | `CoreDynamicForm` | `properties`, `initialValues` | `submit` | | `CoreDynamicFields` | `properties`, `values`, `errors`, `prefix`, `setFieldValue`, `layout` | — | | `CoreFieldRenderer` | `property`, `modelValue` | `update:modelValue` | ### CRUD Modes | Modo | Criar | Editar | View Default | |------|-------|--------|-------------| | `modal` | Dialog | Dialog | Table | | `page` | `/create` | `/[id]` | Table | | `inline` | Dialog | In-place na lista | List | --- ## Banco de Dados ```prisma model App { id Int @id @default(autoincrement()) name String slug String @unique description String? version String @default("1.0.0") icon String @default("pi pi-box") is_active Boolean @default(true) is_frozen Boolean @default(false) created_at DateTime @default(now()) modules Json @default("[]") objects Json @default("[]") } model Lead { id Int @id @default(autoincrement()) nome String email String whatsapp String status String @default("NOVO") ordem Int @default(0) } model Record { id Int @id @default(autoincrement()) object_name String data Json @default("{}") created_at DateTime @default(now()) updated_at DateTime @updatedAt @@index([object_name]) } ``` **Lead** = model nativo (performance). **Record** = tabela genérica para objetos dinâmicos. --- ## Estrutura de Diretórios ``` lead-nuxt/ ├── app/ │ ├── components/ │ │ ├── core/ # ⚙️ Motor dinâmico │ │ │ ├── BuilderHub.vue # 🔧 Top bar contextual (Sovereign Nav) │ │ │ ├── AppMenu.vue # 📁 Sidebar colapsável (route-driven) │ │ │ ├── DynamicCRUD.vue # Orquestrador (modal/page/inline) │ │ │ ├── DynamicFilter.vue # 🔍 Filtro universal (URL-driven) │ │ │ ├── DynamicTable.vue # DataTable por metadados │ │ │ ├── DynamicList.vue # List view com inline editing │ │ │ ├── DynamicForm.vue # Zod runtime + VeeValidate (recursivo) │ │ │ ├── DynamicFields.vue # Recursivo (inner_collection, Ontology v3) │ │ │ ├── FieldRenderer.vue # type → PrimeVue component │ │ │ ├── AssetUpload.vue # Upload para semantic: asset │ │ │ └── MapRenderer.vue # Mapa L2 (spatial_type: point) │ │ ├── fastapp/ # 🏗️ Ferramentas do Arquiteto │ │ │ ├── AgentChat.vue # Chat streaming com AI Architect │ │ │ ├── FastNode.vue # Node customizado para Vue Flow │ │ │ ├── PropertyListEditor # Editor visual de propriedades │ │ │ └── SchemaPropertyMgr # Manager de schemas v3 │ │ ├── crm/ # 📊 Custom: CRM Flux │ │ ├── sosplantao/ # 🏥 Custom: SosPlantão │ │ ├── central-filtros/ # 🏭 Custom: Central Filtros │ │ └── lead/ # 👤 Custom: Lead (Arquétipo) │ ├── layouts/ │ │ └── default.vue # Shell: BuilderHub + Sidebar + Content │ ├── pages/ │ │ ├── fastapp/ │ │ │ ├── apps.vue # Gerenciador + Snapshot │ │ │ ├── schema-v3.vue # 🏗️ FastApp Architect (3-pane) │ │ │ ├── diagram.vue # 🗺️ FastApp Flow (Vue Flow) │ │ │ └── agent.vue # 🤖 FastApp Agent (AI Copilot) │ │ ├── [app]/ │ │ │ ├── index.vue # App Dashboard │ │ │ ├── [module]/index.vue # Module Dashboard (Focal) │ │ │ └── [module]/[object]/ # 🔄 Rotas dinâmicas │ │ └── crm/ # Custom pages │ ├── fastapp/ │ │ ├── manifest.ts # Types: App, Module, Object, Property │ │ └── static-manifest.ts # 📸 Snapshot (auto-gerado) │ ├── stores/ │ │ ├── system.ts # SystemStore (currentApp, sidebarCollapsed) │ │ └── lead.ts # Store Lead (offline, socket) │ ├── composables/ │ │ ├── useAppManifest.ts # Navigation metadata helper │ │ └── useFastappArchitect.ts # Schema editor composable │ ├── utils/ │ │ └── MetaToFlow.ts # Metadata → Vue Flow (ER/Process) │ └── types/ │ └── schema.ts # PropSchema, ObjectSchema, CRUDMode ├── server/ │ ├── api/ │ │ ├── v1/data/[object]/ # 🔌 API Dinâmica │ │ ├── system/snapshot.post.ts # 📸 Gera static-manifest.ts │ │ ├── fastapp-agent.post.ts # 🤖 LLM Streaming endpoint │ │ ├── app/ # CRUD App (admin) │ │ └── lead/ # CRUD Lead (nativo) │ └── utils/ │ ├── prisma.ts # Singleton PrismaClient │ ├── dynamic-db.ts # Hybrid: native ↔ generic Record │ ├── meta-validation.ts # Validação meta-driven │ └── query-parser.ts # 🔍 Filtros/sort → Prisma where/orderBy ├── prisma/schema.prisma # Models: App, Lead, Record └── nuxt.config.ts ``` --- ## Camadas Custom sobre o Motor ```mermaid graph TB subgraph "Camada 3 — Custom (Produto)" P1["crm/leads.vue (Kanban)"] C1["lead/Card, Form, CRUD"] S1["stores/lead.ts (offline)"] end subgraph "Camada 2 — Motor Dinâmico" P2["[app]/[module]/[object]/*"] D1["core/DynamicCRUD"] D2["core/DynamicForm + Fields"] D3["core/DynamicTable + List"] S2["stores/system.ts"] end subgraph "Camada 1 — Infraestrutura" API_V1["/api/v1/data/:object"] API_LEGACY["/api/lead, /api/app"] DYNAMIC_DB["dynamic-db.ts"] META_VAL["meta-validation.ts"] PRISMA["Prisma + PostgreSQL"] SNAPSHOT["Snapshot System"] end P1 --> S1 --> API_LEGACY --> PRISMA P2 --> S2 --> SNAPSHOT P2 --> D1 --> D2 & D3 D1 -->|API calls| API_V1 API_V1 --> META_VAL --> DYNAMIC_DB --> PRISMA style P2 fill:#4338ca,color:#fff style API_V1 fill:#059669,color:#fff style SNAPSHOT fill:#7c3aed,color:#fff style P1 fill:#f59e0b,color:#000 ``` --- ## 🔧 Sovereign Navigation Architecture A navegação do Fastapp é governada por **dois contextos independentes**: | Contexto | Controlador | Store | Função | |---|---|---|---| | **Navegação** | `AppMenu.vue` (OverlayPanel + rota) | Local (`useFetch`) | Exibir módulos/objetos/páginas do app ativo | | **Builder** | `BuilderHub.vue` (Dropdown "Contexto") | `systemStore.selectedAppId` | Alvo dos botões Architect/Flow/Agent | ### Builder Hub Barra superior fixa (`h-14`, `bg-[#0a0d14]`) com: - **Toggle sidebar** (colapsa `15rem` → `4rem`) - **Brand** FastApp - **Dropdown Contexto** (`architect-dropdown`) — define qual app as ferramentas de arquiteto miram - **Pill Buttons** (segmented controls) — cada ferramenta com sua cor: - 🟢 **App** (emerald) → `/{slug}` - 🟣 **Architect** (indigo) → `/fastapp/schema-v3?app={id}` - 🔵 **Flow** (blue) → `/fastapp/diagram?app={id}` - 💜 **Agent** (purple) → `/fastapp/agent?app={id}` ### Sidebar Colapsável - **Expandida** (`w-60`): ícone + label + headers de módulo - **Colapsada** (`w-16`): ícones centralizados com tooltip PrimeVue - Estado persistido em `systemStore.sidebarCollapsed` via `useStorage` ### Ferramentas do Arquiteto | Ferramenta | Rota | Função | |---|---|---| | **FastApp Architect** | `/fastapp/schema-v3` | Schema Studio v3 — editor 3-pane de objetos, propriedades e metadados | | **FastApp Flow** | `/fastapp/diagram` | Visualização de metadados via Vue Flow (ER e Process modes, Dagre layout) | | **FastApp Agent** | `/fastapp/agent` | AI Copilot com streaming, contexto vivo e Domain-Aware Gap Analysis | --- ## 🔁 Auto-Evolução (O FastApp como Primeiro App) O FastApp é **seu próprio usuário mais avançado**. A cadeia de auto-evolução: ```mermaid graph LR AGENT["FastApp Agent
Briefing IA"] -->|"gera schema"| ARCHITECT["FastApp Architect
Schema Studio v3"] ARCHITECT -->|"salva draft"| FADAP["FADAP Protocol
Sync Metadata"] FADAP -->|"publica snapshot"| MANIFEST["static-manifest.ts"] MANIFEST -->|"alimenta"| MENU["AppMenu
Navegação"] MANIFEST -->|"alimenta"| FLOW["FastApp Flow
Diagrama"] MANIFEST -->|"alimenta"| AGENT style AGENT fill:#7c3aed,color:#fff style ARCHITECT fill:#6366f1,color:#fff style FADAP fill:#dc2626,color:#fff style FLOW fill:#2563eb,color:#fff ``` > "O motor se usa para se evoluir. Cada melhoria no Schema Manager melhora a capacidade de melhorar o próprio Schema Manager." --- ## Padrões Importantes ### Optimistic Updates Toda mutação no Lead atualiza o estado local **antes** da resposta do server. Em caso de erro, faz rollback. ### Tab ID (Anti-echo) Cada aba gera um `tabId` random. Socket.IO ignora eventos da própria aba. ### Dados ↔ App Sincronizados Toda propriedade nova em `ObjectSchema` deve ser: adicionada ao type, adicionada ao seed, consumida pelo componente. ### Native vs Generic Record Objetos com model Prisma → desempenho máximo. Objetos do Builder → tabela `Record` genérica, zero setup. --- ## Scripts ```bash npm run dev # Nuxt dev + Socket.IO :3001 npm run build # prisma generate + nuxt build npx prisma studio # DB admin GUI npx prisma db push # Sync schema → DB # Seed: /api/seed-system # Snapshot: botão no /fastapp/apps ``` --- # Auth/RBAC por App Membership em /api/v1/data Source file: AUTH_RBAC_DATA_SCOPE_PLAN.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/auth-rbac-data-scope-plan Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/auth-rbac-data-scope-plan # Auth/RBAC por App Membership em `/api/v1/data` Atualizado em: 2026-02-27 ## Objetivo Garantir isolamento de acesso por `app` e por papel do usuario em todas as rotas `GET/POST/PATCH/DELETE` de `/api/v1/data/*`, com suporte a restricao por propriedade (`constraint_property`) quando configurada. ## Status Atual ### Implementado - Enforce global no BFF Nuxt para toda rota `/api/v1/data/*`. - Decisao de acesso central no Laravel via `GET /api/v1/auth/app-access/{appName}`. - Aplicacao de constraint por dado nos handlers de: - listagem; - lookup; - dashboard metrics; - leitura por id; - update por id; - delete por id; - create. - Suporte a aliases de app (`-` e `_`) na validacao. - Suporte a membership curinga `app='*'` no endpoint `app-access` (acesso global por membership). - Usuarios privilegiados com membership `owner` em todos os apps conhecidos e tambem em `task-board`/`task_board`. ### Ajuste de abilities - Como o schema atual de `users` neste ambiente nao possui colunas `role` e `custom_abilities`, o calculo de abilities globais foi adaptado: - se houver membership ativo `app='*'` com role `owner/admin`, `allAbilities()` retorna `['*']`. - Resultado esperado apos novo login: `abilities` no auth devem incluir `*`. ## Plano Tecnico por Camadas ### 1) Frontend - Continuar enviando `auth_token` (cookie) e/ou `Authorization: Bearer`. - Enviar contexto de `app` quando necessario (`?app=` ou `x-fastapp-app`) em casos ambiguos. - Exibir UX consistente: - `401` para sessao/token invalido; - `403` para bloqueio de escopo/permissao. ### 2) Backend (Nuxt BFF) - Middleware `server/middleware/rbac-data-scope.ts`: - intercepta `/api/v1/data/*`; - resolve `object` e `action` (`read/create/update/delete/lookup/metrics`); - resolve `app` por query/header/referer + metadata do objeto; - valida no Laravel (`/api/v1/auth/app-access/{app}`), com fallback em `/api/v1/auth/me` para compatibilidade; - injeta escopo em `event.context.rbacDataScope`. - Utilitario `server/utils/rbac-data-scope.ts`: - injeta constraint no `where`; - injeta/valida constraint no body de escrita; - valida registro por `id` dentro do escopo; - injeta constraint na query forward para fontes externas. ### 3) Backend (Laravel API) - Endpoint `GET /api/v1/auth/app-access/{appName}`: - valida membership no app solicitado; - considera aliases e membership curinga `*`; - resolve permissao por role + acao + objeto; - aplica fallback conservador para leitura quando nao ha matriz de permissao; - retorna `constraint` quando existir `constraint_property`. ### 4) Schema - `fastapp_permission` deve manter convencao de nomes de permissao: - `objeto-read|create|update|delete`, `data.read`, `data:create`, etc. - Para escopo por dono/equipe, preencher `constraint_property` (ex.: `owner_id`, `team_id`). ### 5) Dados - `fastapp_user_app` e a fonte principal de autorizacao por app. - Para acesso total administrado por membership, manter: - memberships por app com role `owner`; ou - membership curinga `app='*'` com role `owner`. - Garantir `reference_id`/`reference_object` quando `constraint_property` exigir. ## Criterios de Aceite 1. Sem token, qualquer rota `/api/v1/data/*` retorna `401`. 2. Sem membership valido no app (nem curinga `*`), retorna `403`. 3. Com membership `owner/admin`, operacoes `POST/PATCH/DELETE` sao permitidas. 4. Com membership de leitura apenas, escrita retorna `403`. 5. Com `constraint_property`, leitura e escrita respeitam o escopo por registro. 6. Com membership curinga `*` role `owner`, acesso deve funcionar em app novo sem cadastro manual previo. 7. `GET /api/v1/auth/me` e login devem refletir `abilities: ['*']` para usuario com membership curinga `*` owner/admin (apos novo login/token). ## Validacao de Regressao 1. Smoke por rota: - `GET /api/v1/data/:object` - `POST /api/v1/data/:object` - `GET /api/v1/data/:object/:id` - `PATCH /api/v1/data/:object/:id` - `DELETE /api/v1/data/:object/:id` - `GET /api/v1/data/:object/lookup` - `GET /api/v1/data/:object/dashboard-metrics` 2. Matriz de papeis por app: - `owner/admin/member/viewer` x `read/create/update/delete`. 3. Casos de app ambiguo: - mesmo `object` em apps diferentes com `?app=` distinto. 4. Casos de aliases: - `task-board` vs `task_board`; - `central-filtros` vs `central_filtros`. 5. Caso curinga: - usuario com app `*` consegue acessar app nao previamente cadastrado no membership nominal. 6. Fontes externas: - confirmar forward de constraint e bloqueio por membership. 7. Nao regressao funcional: - envelope legado `{ total, limit, skip, data }` preservado. ## Observacoes - O projeto legado `api-fastapp-cloud` nao entra no fluxo ativo. - Base ativa considerada: `laravel-api`. - O typecheck global do `lead-nuxt` possui erros preexistentes fora deste escopo; validar regressao focando nas rotas RBAC e no fluxo de auth. --- # CMS V2 Implementacao Atual e Guia Tecnico Source file: CMS_V2_ROADMAP.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/cms-v2-roadmap Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/cms-v2-roadmap # CMS V2 - Implementacao Atual e Guia Tecnico Atualizado em: 2026-02-26 ## Objetivo Este documento consolida o estado real do CMS V2 no FastApp apos Sprint 1 e Sprint 1.5, com foco em: - implementacoes entregues - mapa de arquivos - contratos de dados - fluxo de edicao e runtime - integracao com objetos do app - limites atuais e proximos passos ## Escopo Entregue (Sprint 1 + 1.5) Status geral: - [x] Secoes verticais com reorder via drag and drop - [x] Fallback de reorder por botoes (up/down) - [x] Renderer CMS generico por registro de componentes - [x] Grid 12 colunas + rows (modelo compativel com Tailwind/Bootstrap) - [x] Binding de dados para objetos via `/api/v1/data/:object` - [x] Rich text editavel com toolbar + tokens de dados - [x] Secoes `object_list` e `object_cards` - [x] Persistencia de draft no `localStorage` com versao v2 - [x] Migracao automatica de chave legacy de `localStorage` - [x] Validacao/sanitizacao server-side no `PATCH /api/app/:id` - [x] Integracao do CMS no Schema Manager (`schema-v3`) e no runtime de paginas custom Ainda nao entregue (ja mapeado no contrato): - [x] renderer para `object_table` - [x] renderer para `kpi_strip` - [ ] drag and drop espacial de grid (hoje e reorder vertical) - [ ] fluxo publish com versao/historico de pagina - [ ] permissao/auditoria por usuario no nivel de secao ## Mapa de Arquivos (Implementacao CMS) ### Contratos e utilitarios - `app/types/schema.ts` - Define `PageSchemaV2`, `CmsSection`, `CmsSectionLayout`, `CmsSectionBinding`. - `CmsSectionType` inclui: `rich_text`, `object_list`, `object_cards`, `object_table`, `kpi_strip`. - Layout com grid: `col_span`, `row_span`, `col_start`, `row_start`, `min_height`. - `app/utils/cms-page.ts` - Fabrica e normaliza secoes (`createCmsSection`, `normalizeCmsSections`). - Migra pagina legacy html para secao `rich_text`. - Forca defaults de `layout_mode`, `theme_preset`, `sections` (`ensurePageSchemaV2`). - Templates rapidos de secao (`createCmsTemplateSection`) para `rich_text`, `object_list`, `object_cards`. - `app/composables/useCmsBinding.ts` - Resolve binding de dados de secao. - Converte `filters`, `sort`, `limit`, `projection` para query string. - Interpola contexto em filtros (`{{route.params.*}}`, `{{route.query.*}}`, etc). - Faz fetch generico em `/api/v1/data/:object`. ### Core CMS components - `app/components/core/cms/CoreCmsRenderer.vue` - Runtime principal de renderizacao. - Registry atual: - `rich_text` -> `CoreCmsSectionRichText` - `object_list` -> `CoreCmsSectionObjectList` - `object_cards` -> `CoreCmsSectionObjectCards` - Usa grid de 12 colunas com `gridColumn`/`gridRow`. - Fallback visual para tipo de secao nao suportado. - `app/components/core/cms/CoreCmsSectionPalette.vue` - Catalogo de templates de secao. - Adiciona secao nova com defaults de binding e props. - `app/components/core/cms/CoreCmsSectionStack.vue` - Lista vertical de secoes com drag and drop (`vuedraggable`). - Exibe metadados de cada secao (tipo, grid, objeto). - Fallback de reorder por botoes. - `app/components/core/cms/CoreCmsSectionInspector.vue` - Editor da secao selecionada. - Edita: - base: label, type, enabled - grid: span/start/min height - binding: source, object, limit - props especificas por tipo (`rich_text`, `object_list`, `object_cards`) - `app/components/core/cms/CoreCmsSectionRichText.vue` - Bloco editavel (contenteditable) com toolbar. - Suporte a tokens em modo leitura: - `{{record.campo}}` - `{{object.count}}` - `{{object.name}}` - `{{image:https://...}}` - `app/components/core/cms/CoreCmsSectionObjectList.vue` - Lista de registros conectada ao objeto. - Usa `CoreDynamicList`. - Suporte a layout `list`/`grid` e `columns`. - `app/components/core/cms/CoreCmsSectionObjectCards.vue` - Cards visuais conectados ao objeto. - Props: `image_field`, `title_field`, `description_field`, `cta_label`, `columns`. - Heuristica para inferir campos quando nao configurados. ### Integracao nas paginas - `app/pages/fastapp/schema-v3.vue` - Editor de pagina no Architect com: - `CoreCmsSectionPalette` - `CoreCmsSectionStack` - `CoreCmsSectionInspector` - `CoreCmsRenderer` (preview) - `pageFields` inclui `layout_mode` e `theme_preset`. - Garante pagina em formato V2 via `ensurePageSchemaV2`. - `app/pages/[app]/[module]/index.vue` - Runtime de pagina custom com edicao local. - Persistencia de draft em `localStorage`: - v2: `fastapp:cms:v2:draft:{appSlug}:{pageToken}` - legacy: `fastapp:cms:{appSlug}:{pageToken}` - Migracao automatica do legado para V2. ### Validacao de API - `server/api/app/[id].patch.ts` - Sanitiza `pages`, `sections`, `layout`, `binding`. - Valida `layout_mode` permitido. - Valida tipo/shape de `filters`, `sort`, `projection`, `limit`. - Se payload CMS for invalido, retorna `400` antes da tentativa SQL fallback. ## Contrato de Dados (PageSchemaV2) ```ts type CmsLayoutMode = 'flow_vertical' | 'split' | 'dashboard' type CmsSectionType = | 'rich_text' | 'object_list' | 'object_cards' | 'object_table' | 'kpi_strip' interface CmsSectionLayout { col_span?: number // 1..12 row_span?: number // 1..12 col_start?: number // 1..12 row_start?: number // 1..12 min_height?: string gap?: string | number width?: string align?: 'left' | 'center' | 'right' | 'stretch' } interface CmsSectionBinding { source_type?: 'none' | 'object' | 'static' object_name?: string filters?: Record sort?: Record limit?: number projection?: string[] } interface CmsSection { id: string type: CmsSectionType label: string order: number enabled: boolean layout?: CmsSectionLayout style?: Record binding?: CmsSectionBinding props?: Record actions?: Record } interface PageSchemaV2 { slug: string layout_mode?: CmsLayoutMode theme_preset?: string sections?: CmsSection[] } ``` ## Exemplo de Pagina CMS V2 ```json { "slug": "landing", "layout_mode": "flow_vertical", "theme_preset": "industrial_zen", "sections": [ { "id": "sec_intro", "type": "rich_text", "label": "Hero", "order": 1, "enabled": true, "layout": { "col_span": 12, "row_span": 1, "min_height": "280px" }, "binding": { "source_type": "object", "object_name": "lead", "limit": 1, "sort": { "id": -1 } }, "props": { "html": "

Leads ativos: {{object.count}}

Ultimo lead: {{record.name}}

{{image:https://cdn.site/banner.jpg}}

" } }, { "id": "sec_cards", "type": "object_cards", "label": "Leads em destaque", "order": 2, "enabled": true, "layout": { "col_span": 12, "row_span": 1 }, "binding": { "source_type": "object", "object_name": "lead", "limit": 6, "sort": { "id": -1 } }, "props": { "title": "Top leads", "columns": 3, "image_field": "image", "title_field": "name", "description_field": "description", "cta_label": "Abrir" } } ] } ``` ## Fluxo de Runtime e Persistencia ### Runtime em pagina custom 1. Normaliza pagina base para V2 (`ensurePageSchemaV2`). 2. Carrega draft do `localStorage` (chave v2). 3. Se v2 nao existir, tenta chave legacy. 4. Concatena base + draft para `cmsRuntimePage`. 5. Renderiza com `CoreCmsRenderer`. 6. Ao salvar draft: - grava payload com `version: 2` - remove chave legacy ### Payload salvo no localStorage ```json { "version": 2, "updated_at": "2026-02-26T12:34:56.000Z", "page": { "layout_mode": "flow_vertical", "theme_preset": "industrial_zen", "sections": [] } } ``` ## Binding com Objetos (Query Mapping) Contrato de binding para `source_type: object`: - `object_name` define endpoint base. - `filters` vira query plana. - `sort` vira `$sort[field]=1|-1`. - `limit` vira `$limit`. - `projection` vira `$select=campo1,campo2`. Exemplo: ```ts binding = { source_type: 'object', object_name: 'lead', filters: { status: 'open', owner_id: '{{route.params.id}}' }, sort: { created_at: -1 }, limit: 10, projection: ['id', 'name', 'status'] } ``` Request gerada: `/api/v1/data/lead?status=open&owner_id=123&$sort[created_at]=-1&$limit=10&$select=id,name,status` ## Grid 12 Colunas + Rows (Sprint 1.5) Implementacao atual: - `CoreCmsRenderer` usa grid `grid-cols-12`. - Cada secao aplica: - `gridColumn: span X / span X` ou `start / span X` - `gridRow: span Y / span Y` ou `start / span Y` - Inspector controla: - `col_span`, `row_span` - `col_start`, `row_start` - `min_height` - Presets rapidos no inspector: `12/1`, `6/1`, `4/1`, `8/2`. Observacao: - O posicionamento na grade ainda e configurado por formulario (nao por drag espacial). - O reorder de secoes continua vertical. ## Pontos Fortes Atuais - Abstracao generica: a pagina e schema-driven, sem branch por app. - Reuso de objetos: secoes conectam em qualquer objeto via metadados. - Composicao visual: palette + stack + inspector + preview no mesmo fluxo. - Migrao suave: legado html e convertido para secao `rich_text`. - Seguranca de contrato: API valida shape de pages/secoes antes de persistir. ## Gaps para ficar "CMS real" (mais faceis agora) Prioridade P0/P1 de baixo custo tecnico: 1. Sanitizacao de HTML no `rich_text` antes de render (`v-html` hoje aceita html bruto). 2. Blocos mistos em rich text: - insercao visual de "chips de objeto" (campo dinamico) - seletor de imagem do app/asset object (alem de URL) 3. `object_table` renderer reaproveitando tabela dinamica. 4. `kpi_strip` renderer com agregacoes simples (`count`, `sum`, `avg`). 5. Toolbar de rich text moderna (evitar dependencia total de `document.execCommand`). ## Diferencial FastApp (Abstracao + IA) Direcao recomendada para agentes IA no CMS: 1. "Pilot mode": - agente cria/reordena secoes por prompt - gera bindings com base em objetos e relacoes existentes 2. "Data-aware content": - agente sugere tokens (`{{record.*}}`, `{{object.count}}`) conforme schema - propoe card/list/table mais aderente ao tipo de objeto 3. "Layout copilot": - agente ajusta `col_span/row_span` para responsividade - aplica presets visuais por intencao (landing, dashboard, catalogo) 4. "Safe patch": - agente escreve patch em `sections[]` validado por contrato server-side ## Guia Rapido para Adicionar Novo Tipo de Secao Exemplo: `object_table` 1. Garantir o tipo em `app/types/schema.ts` (ja existe). 2. Criar componente `app/components/core/cms/CoreCmsSectionObjectTable.vue`. 3. Registrar no `SECTION_REGISTRY` de `CoreCmsRenderer.vue`. 4. Adicionar template em `CoreCmsSectionPalette.vue`. 5. Expor props no `CoreCmsSectionInspector.vue`. 6. Definir template default em `createCmsTemplateSection` (`app/utils/cms-page.ts`). 7. Validar comportamento com binding via `useCmsBinding`. ## Checklist de Validacao - Criar pagina nova no Architect e confirmar defaults `layout_mode/theme_preset/sections`. - Adicionar secoes `rich_text`, `object_list`, `object_cards`. - Reordenar por drag e por botoes. - Alterar grid no inspector e validar preview. - Conectar secao a objeto real e validar fetch. - Salvar draft em pagina custom e recarregar browser. - Testar migracao da chave legacy `fastapp:cms:*`. - Enviar `PATCH /api/app/:id` com payload invalido e validar erro `400`. ## Conclusao O CMS V2 ja saiu do modo "html editavel simples" e entrou em um modelo composavel, orientado a schema, com binding de objetos, grid de 12 colunas e persistencia local versionada. A base para evolucao com IA ja esta pronta, especialmente no eixo de geracao/edicao automatica de `sections[]`. --- # 🏗️ Arquitetura de Componentes — Padrão Dinâmico vs Concreto Source file: COMPONENT_ARCHITECTURE.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/component-architecture Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/component-architecture # 🏗️ Arquitetura de Componentes — Padrão Dinâmico vs Concreto ## 📚 Princípio: Abstração Soberana A estrutura de componentes do Fastapp segue a **Escada de Abstração** definida em [ANTIGRAVITY_GUIDELINES.md](./ANTIGRAVITY_GUIDELINES.md). A divisão de pastas reflete a intenção de separação entre o motor universal e as necessidades específicas: ``` components/ ├── core/ → DINÂMICOS (genéricos, reutilizáveis em qualquer contexto) │ ├── (Navigation) BuilderHub.vue, AppMenu.vue │ └── (Data) DynamicCRUD, DynamicForm, DynamicTable, DynamicList... ├── fastapp/ → CONCRETOS (Ferramentas do Arquiteto) ├── crm/ → CONCRETOS (específicos do CRM) ├── sosplantao/ → CONCRETOS (específicos do SosPlantão) ├── central-filtros/ → CONCRETOS (específicos do Central Filtros) └── lead/ → CONCRETOS (específicos do Lead) ``` ## ✅ Componentes Dinâmicos em `core/` **Características**: - ✓ Genéricos e abstratos - ✓ Não dependem de domínio específico - ✓ Reutilizáveis em múltiplos contextos - ✓ Aceitam dados via props/slots - ✓ Emitem eventos genéricos **Exemplos Atuais**: ### 1. **DynamicList.vue** ✅ - **Propósito**: Renderizar listas de dados com opcional Drag & Drop e Seleção - **Props**: `schema`, `data`, `sortable`, `selectable`, `selectableMode` ('single' | 'multiple'), `layout` ('list' | 'grid') - **Slots**: `#item` (para renderização customizada por linha) - **Eventos**: `reorder`, `edit`, `delete`, `update`, `select` - **Uso**: Qualquer coleção que precise de visualização em lista/grid ou seleção - **Contextos**: - Listas de CRUD - Seletores de registros - Dashboards - Editors com slots customizados ("DIY" Pattern) **Padrão de Uso**: ```vue ``` **Pattern Avançado (Slots)**: ```vue ``` ### 2. **DynamicCRUD.vue** ✅ [EVOLVED] - **Propósito**: Orquestrador soberano de coleções de dados (List + Table + Form + Tabs). - **Orquestração de Interface**: - **Wizard Mode**: Suporta renderização de formulários em passos (`group_render_mode: 'wizard'`) em modo full-page. - **Nested CRUD**: Gerencia automaticamente abas de relações HasMany com suporte a: - `initialViewMode`: Define se a aba abre como Tabela, Kanban, etc. - `mode="modal"`: Garante que o CRUD filho use modais para evitar conflitos de sidebar. - **Capacidades**: - Auto-limpeza de propriedades (ex: oculta `location` em tabelas via `show_in_list`). - Suporte a `crud_mode: 'split' | 'page' | 'modal'`. ### 3. **DynamicForm.vue** ✅ - **Propósito**: Renderizar formulários dinamicamente baseado em schema - **Props**: `properties`, `initialValues`, `compact`, `showActions`, `loading` - **Eventos**: `submit`, `change`, `cancel` - **Uso**: Standard Forms, Sidebars, Modais ### 4. **RelationList.vue** ✅ - **Propósito**: Gerenciar relacionamentos 1:N Embedded (JSONB) - **Pattern**: `storage: 'document_embed'` - **Props**: `schema`, `modelValue`, `disabled` - **Uso**: Listas de itens simples dentro de um objeto pai (ex: emails, telefones) ### 5. **DynamicTable.vue** ✅ - **Propósito**: Renderizar tabelas dinamicamente - **Props**: `schema`, `data` - **Eventos**: similares ao DynamicList ### 6. **BiWidget.vue** ✅ [NEW] - **Propósito**: Componente "Plug-and-Play" para visualização de métricas BI. - **Capacidades**: - Auto-inferência de tipo de gráfico (Donut, Line, KPI, Leaderboard). - Suporte a séries temporais ponderadas (Financial Weighting). - Seleção dinâmica de granularidade (Dia, Semana, Mês, Ano). - Interatividade "Click-to-Filter" integrada. - **Props**: `metric` (blueprint gerado pela API), `total`. ### 7. **DynamicFilter.vue** ✅ [EVOLVED] - **Propósito**: Painel de filtros reativo que governa a URL do sistema. - **Capacidades**: - Geração dinâmica de campos baseado no Schema. - Suporte a operadores complexos (between, in, like). - Saída em formato **Flattened** (field[op]=val). - Sincronização automática com `route.query`. --- ## 🎯 Componentes Concretos em Subpastas **Características**: - ✓ Específicos de um domínio/feature - ✓ Podem depender de stores, APIs do domínio - ✓ Implementam lógica customizada - ✓ Encapsulam regras de negócio - ✓ Podem usar componentes dinâmicos ### **components/fastapp/PropertyListEditor.vue** ✅ - **Propósito**: Editor especializado para reordenar propriedades de objetos do Schema - **Props**: `properties` (array de PropSchema) - **Eventos**: `update`, `reorder` - **Dependências**: draggable, PropSchema type - **Contexto**: Exclusivamente no Schema Manager - **Responsabilidades**: - Gerir edição inline de propriedades - Drag & Drop de propriedades - Adição/remoção de propriedades - Validação de metadados **Padrão de Uso**: ```vue ``` ### **components/crm/Kanban.vue** ✅ - **Propósito**: Kanban board específico do CRM - **Dependências**: leadStore, LeadCard - **Contexto**: CRM leads pipeline ### **components/crm/LeadCard.vue** ✅ - **Propósito**: Card específico para exibir um lead no Kanban - **Contexto**: CRM --- ## 🏗️ Padrão de Decisão **Quando criar componente em `core/`?** ``` ✓ Pode ser usado em 2+ contextos? ✓ Não depende de domínio específico? ✓ Funciona com dados genéricos via props? ✓ Emite eventos genéricos? SE SIM → core/ ``` **Quando criar componente em subfolder específica?** ``` ✓ É específico de um feature/domínio? ✓ Encapsula lógica de negócio? ✓ Pode usar stores do domínio? ✓ É interna daquele feature? SE SIM → fastapp/, crm/, lead/, etc. ``` --- ## 📋 Estrutura Proposta (Pós-Refactor) ``` app/ ├── components/ │ ├── core/ ← DINÂMICOS │ │ ├── BuilderHub.vue ✅ Sovereign Navigation (top bar contextual) │ │ ├── AppMenu.vue ✅ Sidebar colapsável (route-driven) │ │ ├── DynamicList.vue ✅ genérico, reutilizável │ │ ├── DynamicForm.vue ✅ genérico, reutilizável │ │ ├── DynamicTable.vue ✅ genérico, reutilizável │ │ ├── DynamicFields.vue ✅ genérico, Ontology v3 │ │ ├── PrimitiveEditor.vue ✅ genérico, reutilizável │ │ ├── RelationList.vue ✅ Pattern: Embedded (JSONB) │ │ ├── DynamicIntegratedList.vue ✅ Pattern: Physical (Relation tables) │ │ ├── RelationLookup.vue ✅ Pattern: Physical (Foreign Key) │ │ ├── AssetUpload.vue ✅ Pattern: semantic=asset │ │ ├── MapRenderer.vue ✅ Pattern: spatial_type=point │ │ ├── BiWidget.vue ✅ Engine de Visualização BI (Chart.js) │ │ └── DynamicFilter.vue ✅ Filtro Universal Soberano (URL-driven) │ │ │ ├── fastapp/ ← ARCHITECT TOOLS │ │ ├── AgentChat.vue ✅ Chat AI streaming com contexto │ │ ├── FastNode.vue ✅ Node customizado Vue Flow │ │ ├── PropertyListEditor.vue ✅ específico (Schema Manager) │ │ ├── SchemaPropertyManager.vue ✅ específico (v3 Schema Editor) │ │ └── ... │ │ │ ├── crm/ ← CONCRETOS DO CRM │ │ ├── Kanban.vue ✅ específico (CRM) │ │ ├── LeadCard.vue ✅ específico (CRM) │ │ └── ... │ │ │ └── lead/ ← CONCRETOS DO LEAD │ └── ... │ └── pages/ └── fastapp/ └── example-dynamic-components.vue ← KITCHEN SINK (Playground Oficial) ``` --- ## 🔄 Padrão de Integração ### Fluxo Correto **Schema Manager**: ``` schema.vue (página) ↓ usa [PropertyListEditor] (concreto em fastapp/) ↓ que encapsula DynamicList (dinâmico em core/) → para futura reutilização ``` **CRM**: ``` leads.vue (página) ↓ usa [Kanban] (concreto em crm/) ↓ que contém [LeadCard] (concreto em crm/) ↓ que poderia usar DynamicList (dinâmico em core/) com :sortable="true" ``` **Forma Correta**: ```vue ``` --- ## ❌ Anti-Patterns ### ❌ Evitar ```vue ``` ### ❌ Evitar Duplicação ```javascript // ❌ NÃO faça: // components/core/PropertyListEditor.vue (genérico) // components/fastapp/PropertyListEditor.vue (concreto) // → Conflita! Use apenas este: components/fastapp/ ``` ### ❌ Evitar Lógica Específica em Core ```vue ``` --- ## ✅ Boas Práticas ### 1️⃣ **Componente Genérico em Core** ```vue ``` ### 2️⃣ **Componente Concreto em Feature** ```vue ``` ### 3️⃣ **Usar Concreto Dentro de Página** ```vue ``` --- ## 🚀 Próximo Passo Seguindo esse padrão, você pode: 1. ✅ **Usar DynamicList** em múltiplos contextos com `sortable` prop 2. ✅ **Criar specializations** (como PropertyListEditor) quando precisar 3. ✅ **Manter core/** limpo e genérico 4. ✅ **Reutilizar lógica** de reordenação via DynamicList 5. ✅ **Encapsular domínio** em pastas específicas (fastapp/, crm/, lead/) --- ## 📚 Referência Rápida | Lugar | Tipo | Exemplo | Reutilizável | |-------|------|---------|--------------| | `components/core/` | Dinâmico | DynamicList, BuilderHub, AppMenu | ✅ Sim, em vários lugares | | `components/fastapp/` | Concreto | PropertyListEditor, AgentChat, FastNode | ❌ Apenas Ferramentas do Arquiteto | | `components/crm/` | Concreto | Kanban | ❌ Apenas CRM | | `pages/fastapp/` | Página | schema-v3.vue, diagram.vue, agent.vue | ❌ Apenas essas rotas | --- > [!NOTE] > O `BuilderHub.vue` e `AppMenu.vue` vivem em `core/` porque são genéricos: não conhecem nenhum domínio específico. Eles consomem `systemStore` para navegação, não para lógica de negócio. O `AgentChat.vue` e `FastNode.vue` vivem em `fastapp/` porque são específicos das ferramentas do arquiteto. --- **Data**: 22/02/2026 **Status**: ✅ Atualizado com Sovereign Navigation & Architect Tool Chain --- # 📣 Sistema de Comunicados — Manual Tecnico Source file: COMUNICADO_SYSTEM.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/comunicado-system Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/comunicado-system # 📣 Sistema de Comunicados — Manual Tecnico > Painel de configuracao de notificacoes/alertas baseado em eventos. E-mail nesta primeira fase, WhatsApp (via WAHA) na proxima. > Segue o padrao do Fastapp Engine: o painel **e** um Object em `app.objects[]`. --- ## 1. Conceito > "Quero receber um e-mail toda vez que alguem criar uma task nova no MEU app." O usuario configura **regras de comunicado** no painel. Cada regra descreve: - **Quando**: qual objeto monitorar + qual evento (create/update/delete) + filtro opcional - **Para onde**: canal (email/whatsapp) + destinatario (email ou telefone) - **O que**: assunto + mensagem com placeholders `{{record.}}` Quando um registro do objeto monitorado e criado/atualizado/excluido, o motor le as regras ativas e dispara as notificacoes. --- ## 2. Posicionamento Arquitetural ```mermaid graph TB subgraph "Metadata Layer (App JSON)" OBJ_CFG["app.objects.comunicado_config
(regras configuradas)"] OBJ_TASK["app.objects.task_item
(registros monitorados)"] end subgraph "Engine Layer" POST["POST /api/v1/data/:app/:object
(index.post.ts)"] DISPATCHER["dispatchComunicados()
(2a fase)"] end subgraph "Infrastructure Layer" EMAIL["server/utils/email.ts
(2a fase)"] WAHA["server/utils/waha.ts
(ja existe)"] end POST -->|ao criar task| DISPATCHER DISPATCHER -->|le regras| OBJ_CFG DISPATCHER -->|canal=email| EMAIL DISPATCHER -->|canal=whatsapp| WAHA style OBJ_CFG fill:#0891b2,color:#fff style DISPATCHER fill:#7c3aed,color:#fff style WAHA fill:#25D366,color:#000 ``` **Decisao chave**: o painel de configuracao e um Object normal, nao um sistema separado. Isso significa: - Persistencia: tabela `Record` (storage: `generic`) — zero DDL - UI: gerada automaticamente pelo `CoreDynamicCRUD` - API: `/api/v1/data/:app/comunicado_config` (CRUD ja pronto pelo motor) - Permissoes: passa pelo RBAC padrao - Snapshot: incluido no `static-manifest.ts` --- ## 3. Definicao do Object `comunicado_config` Localizada em [`schemas/comunicado-config-object.json`](./schemas/comunicado-config-object.json). | Atributo | Valor | |---|---| | `name` | `comunicado_config` | | `category` | `configuration` | | `nature` | `physical` | | `storage` | `generic` (tabela `Record`) | | `crud_mode` | `modal` | | `ui_mode` | `list` | | `key_property` | `id` | | `label_property` | `name` | ### Properties | Propriedade | Tipo | Funcao | |---|---|---| | `name` | string (required) | Nome amigavel da regra | | `is_active` | boolean | Liga/desliga sem precisar excluir | | `trigger_object` | foreign_key -> object (required) | Dropdown com todos os objects de todos os apps (alimentado por `systemStore.getLookupData('object')`). Valor salvo = `o.name`. | | `trigger_event` | enum: create/update/delete | Quando disparar | | `trigger_filter` | json | Filtro adicional. Ex: `{"status":"TODO","prioridade":"ALTA"}` | | `scope_app_id` | FK app | Restringe a registros cujo `app_origem_id` coincide | | `channel` | enum: email/whatsapp/both | Canal de envio | | `recipient_email` | string (semantic: email) | Destinatario quando canal = email | | `recipient_phone` | string (semantic: phone) | Destinatario quando canal = whatsapp ou both | | `waha_session` | string | Session WAHA usada para enviar | | `subject` | string | Assunto (suporta placeholders) | | `message_template` | textarea (required) | Corpo da mensagem (suporta placeholders) | | `last_dispatched_at` | datetime | Telemetria — preenchida pelo dispatcher | | `dispatch_count` | number | Telemetria — contador | ### Placeholders `{{record.}}` — substituido pelos campos do registro que disparou o evento. Ex: numa regra para `task_item`: ``` Subject: Nova task: {{record.titulo}} Body: Foi criada a task "{{record.titulo}}" com prioridade {{record.prioridade}}. Status atual: {{record.status}} ``` --- ## 4. Como instalar em um App ### Opcao A — Script (recomendado) ```bash # Apenas no app task-board: node scripts/add-comunicado-config-to-app.mjs task-board # Em todos os apps: node scripts/add-comunicado-config-to-app.mjs --all ``` O script ([`scripts/add-comunicado-config-to-app.mjs`](./scripts/add-comunicado-config-to-app.mjs)) faz, de forma idempotente: 1. Carrega o schema de `schemas/comunicado-config-object.json` 2. Adiciona/atualiza em `app.objects[]` 3. Garante que existe um module `Configuracoes` em `app.modules[]` referenciando o object (e o motor gera o item de menu automaticamente em `//configuracoes/comunicado_config`) 4. Limpa entradas legadas em `app.pages[]` deixadas por versoes anteriores do script (que causavam o erro "App comunicados nao encontrada no manifesto") 5. Persiste via `prisma.app.update` > **Por que nao adicionar em `app.pages[]`?** > O item de sidebar vem do `modules[].objects[]` — adicionar em `pages[]` cria duplicacao e, se o `path` for absoluto, conflita com a rota dinamica `[app]/index.vue`. Apos rodar, recarregue o app — o item "Comunicados" aparece no menu lateral em Configuracoes. ### Opcao B — Manual via Schema Manager 1. Abra `/fastapp/schema-v3?app=` 2. Importe o JSON de `schemas/comunicado-config-object.json` 3. Adicione module/page conforme padrao --- ## 5. Roadmap — Fases ### Fase 1 — Painel (✓ entregue) - [x] Object schema `comunicado_config` - [x] Script de migracao (Add to App) - [x] Documentacao ### Fase 2 — Dispatcher + Email (✓ entregue) - [x] `server/utils/email.ts` — wrapper SMTP (Nodemailer, Gmail por padrao, SSL/TLS) - [x] `server/utils/comunicado-dispatcher.ts` — le regras, filtra (trigger_object/event, trigger_filter, scope_app_id), renderiza template, dispara - [x] Hook fire-and-forget em `server/api/v1/data/[app]/[object]/index.post.ts` (4 caminhos: external, native delegate, native table, generic Record) - [x] Hook em `[id].patch.ts` para evento `update` (mesmos 4 caminhos) - [x] Hook em `[id].delete.ts` para evento `delete` (mesmos 4 caminhos; passa o `existing` lido antes do delete para o template ter acesso aos campos) - [x] `GET /api/email/verify` — health check do SMTP sem enviar - [x] `POST /api/email/test` — envia e-mail de teste para um destinatario - [x] Telemetria — `last_dispatched_at` e `dispatch_count` atualizados na propria regra #### Configuracao de SMTP (Gmail) 1. Ativar **Verificacao em 2 etapas**: https://myaccount.google.com/security 2. Gerar **Senha de app**: https://myaccount.google.com/apppasswords (cole sem espacos) 3. `.env`: ```env SMTP_HOST=smtp.gmail.com SMTP_PORT=465 SMTP_USER=seuemail@gmail.com SMTP_PASS=abcdefghijklmnop # 16 chars da senha de app SMTP_FROM=seuemail@gmail.com ``` 4. Validar: `curl http://localhost:3000/api/email/verify` → `{ ok: true, configured: true }` 5. Enviar teste: `curl -X POST http://localhost:3000/api/email/test -H "Content-Type: application/json" -d '{"to":"voce@dominio.com"}'` ### Fase 3 — WhatsApp (✓ entregue) - Reaproveita `server/utils/waha.ts` - O dispatcher decide canal pelo campo `channel` - Opcoes de canal: `email`, `whatsapp` e `both` (envia pelos dois canais) - `recipient_phone` aceita multiplos numeros separados por `;`, `,` ou quebra de linha, sem mascara de telefone - Se uma regra antiga estiver como `email`, mas tiver `recipient_phone` preenchido, o dispatcher tambem envia WhatsApp - `waha_session` usa `default` quando vazio ### Fase 4 — UI Refinada - View kanban-like agrupando por canal/objeto - Preview de mensagem com placeholders renderizados - Teste de envio manual ("Enviar teste agora") - Painel de telemetria (taxa de entrega, ultimos disparos) --- ## 6. Como funciona o gatilho (vista geral, fase 2) ```mermaid sequenceDiagram participant User participant API as POST /api/v1/data/
:app/task_item participant DB as createRecord() participant Dispatcher as dispatchComunicados() participant Rules as app.objects.
comunicado_config participant Email as email.ts participant WAHA as waha.ts User->>API: cria task API->>DB: insert Record DB-->>API: novo registro API->>Dispatcher: (objectName="task_item", event="create", record) Dispatcher->>Rules: filtra is_active + trigger_object + trigger_event Dispatcher->>Dispatcher: aplica trigger_filter Dispatcher->>Dispatcher: aplica scope_app_id (se setado) par para cada regra ativa alt channel = email Dispatcher->>Email: send(to, subject, body) else channel = whatsapp/both Dispatcher->>WAHA: sendText(session, chatId, text) end end Dispatcher->>Rules: incrementa dispatch_count + last_dispatched_at API-->>User: registro criado ``` **Princípio**: o dispatcher e fire-and-forget (nunca bloqueia o response da API). Falhas viram log + telemetria, nao quebram a criacao do registro. --- ## 7. Exemplo Completo (caso do usuario) > "Quero receber alerta no email gestor@empresa.com toda vez que alguem criar uma task nova para o app task-board." Apos rodar `node scripts/add-comunicado-config-to-app.mjs task-board`, navegar ate `/task-board/configuracoes/comunicado_config` e criar: ```json { "name": "Alerta de nova task — gestor", "is_active": true, "trigger_object": "task_item", "trigger_event": "create", "trigger_filter": null, "scope_app_id": 25, "channel": "email", "recipient_email": "gestor@empresa.com", "subject": "Nova task: {{record.titulo}}", "message_template": "Uma nova task foi criada:\n\nTitulo: {{record.titulo}}\nPrioridade: {{record.prioridade}}\nStatus: {{record.status}}" } ``` Quando a fase 2 estiver implementada, isso bastara — sem codigo customizado no app. --- **Status**: Fase 1, Fase 2 e Fase 3 entregues. WhatsApp via WAHA ativo no dispatcher. **Branch**: `feat/Panel-Comunication` --- # 🧬 DATA TAXONOMY — A Semântica do Dado Source file: DATA_TAXONOMY.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/data-taxonomy Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/data-taxonomy # 🧬 DATA TAXONOMY — A Semântica do Dado Este documento define os eixos de classificação semântica que permitem ao motor Fastapp reagir de forma inteligente à natureza dos dados. No motor Anti-Gravity, a semântica governa a infraestrutura. Atualizado para a **Ontologia v3**. --- ## 🏗️ Os 3 Eixos da Taxonomia Semântica ### 1. Categoria Semântica (`object.category`) Define o "comportamento de vida" do dado no ecossistema and impacta diretamente como o gerador de código e o motor de cache operam. | Categoria | Descrição | Comportamento Automático (Behavior) | | :--- | :--- | :--- | | **master** | Dados mestres e estáveis (ex: Corretoras, Usuários). | O motor prioriza caches agressivos, dropdowns globais e otimiza buscas por nome/label. | | **transactional** | Eventos e registros de fluxo com alta volatilidade (ex: Leads, Transações). | Ativa automaticamente índices por data, logs de auditoria e filtros de período/time-scales. | | **configuration** | Parâmetros de ajuste do sistema ou do usuário (ex: Settings). | O motor gera interfaces simplificadas de "Settings", ocultando listagens densas e focando em editores diretos. | ### 2. Natureza Arquitetural (`object.nature`) Define a "física" do dado, ou seja, onde ele reside fisicamente no backend. - **physical**: Possui uma tabela própria no DB com ID único global, sendo plenamente referenciável por qualquer outro objeto. - **embedded**: Vive dentro do JSON de um objeto pai (Document-based). Não possui tabela própria. - **virtual**: Calculado em runtime (ex: saldo total, status derivado). ### 3. Orquestração Logística e Roteirização (`object.routing_type`) [NEW] Define como o motor interpreta o dado em um contexto geográfico e de transporte. - **waypoint**: O dado representa um ponto de parada ou serviço (ex: Local de Entrega, Checkpoint). Ativa o calculo de ETAs e janelas de serviço. - **route**: O dado representa um trajeto completo ligando múltiplos waypoints. Ativa a visualização de linhas de desejo e trajetos otimizados. ### 4. Origem da API (`app.*` e `object.*`) Define como o objeto resolve a fonte de dados em runtime. - **Default**: `provider = local` (usa `/api/v1/data/:object` com storage interno Fastapp). - **App-level override**: `app.api_base_url` + `app.provider = external-api` (ou `app.is_api_data_source = true`). - **Object-level override**: `object.api_url` (tem precedência sobre qualquer config do app). - **Compatibilidade legado**: `isApiDataSource` e `_legacy.source_isApiDataSource` continuam aceitos. --- ## 🛰️ Tipologia de Recursos e Espaço ### Tipos de Recurso (`object.resource_type`) Classifica entidades para algoritmos de alocação de recursos finitos. - **human**: Técnicos, motoristas, profissionais (possuem agenda e especialidade). - **mobile_asset**: Veículos, equipamentos móveis (possuem posição GPS e capacidade). - **fixed_asset**: Salas, ferramentas fixas (possuem disponibilidade local). ### Tipos Espaciais (`property.spatial_type`) Define a geometria do dado para o motor GIS. - **point**: Coordenadas geográficas simples (Lat/Long). Ativa o `CoreMapRenderer`. - **polygon**: Áreas de cobertura ou cercas eletrônicas (Geofencing). Ativa buscas por contenção. --- ## 🎨 Os 2 Novos Eixos da Ontologia v3 ### 4. Semântica de Campo (`property.semantic`) Define a **natureza semântica** de um campo individual, ativando renderização especializada. | Semantic | Renderização Automática | Exemplo | | :--- | :--- | :--- | | `asset` | Upload de arquivo com preview | Foto do produto, documento PDF | | `money` | Máscara monetária (R$ 1.234,56) | Preço, salário | | `percentage` | Slider ou input com sufixo % | Margem, desconto | | `phone` | Máscara de telefone + link `tel:` | WhatsApp, comercial | | `email` | Validação + link `mailto:` | Email principal | | `url` | Link clicável externo | Website, LinkedIn | | `color` | Color picker nativo | Cor do tema, cor de status | | `cpf` / `cnpj` | Máscara de documento | CPF, CNPJ | ### 5. Topologia de Apresentação (`module.topology`) Define a **dinâmica de navegação** de um módulo ou objeto no app. | Topology | Comportamento | Exemplo | | :--- | :--- | :--- | | `focal` | Dashboard central com métricas e visão consolidada | Módulo de Logistica com mapa | | `connected` | Lista que se conecta a detalhes (master-detail) | Pedidos → Itens | | `hierarchical` | Árvore navegável (tree view) | Categorias → Subcategorias | ## ⛓️ Restrições de Governança (`object.geo_constraint`) Define regras de negócio espaciais automatizadas. - **geofencing**: Garante que uma ação só ocorra dentro de um polígono definido. - **area_of_action**: Vincula recursos a territórios específicos, impedindo alocação fora da zona permitida. --- ## ⛓️ Relacionamentos e Persistência (`object.relations`) ... (Inalterado) ... --- ## 🏗️ Reação do Motor (Behaviors) A taxonomia permite a **Escada de Abstração**: 1. **L1 (Atômico)**: Tipos `location` ou `area` ativam automaticamente o seletor de mapa. 2. **L2 (Padrões)**: Objetos com `routing_type: 'waypoint'` ativam o `ui_mode: 'dispatch_map'`. 3. **L3 (Orquestração)**: O motor implementa a **Exclusão Geotemporal** — impede que um recurso seja alocado em dois locais se o tempo de deslocamento calculado (via Routes API) for insuficiente. ## 📈 6. Extensões Analíticas (Ontologia v3) [NEW] Define como o motor interpreta o dado para geração de insights, métricas e visualizações de BI. ### Propriedades Analíticas (`property`) | Atributo | Tipo | Descrição | Comportamento Reativo | | :--- | :--- | :--- | :--- | | `aggregation` | `enum` | [sum, avg, min, max, count, distinct, none] | Define a estatística primária. `money` assume `sum`, `percentage` assume `avg`. | | `target` | `number` | Valor de meta ou baseline. | Ativa o indicador de progresso e barra de performance no `BiWidget`. | ### Eixos de Análise (`object`) | Atributo | Tipo | Descrição | Exemplo | | :--- | :--- | :--- | :--- | | `temporal_axis` | `string` | Campo de data usado como referência de tempo principal. | `closed_at` em vendas, `created_at` default. | | `temporal_resolution` | `enum` | [day, week, month, year, auto] | Define a granularidade padrão dos gráficos de série temporal. | | `target_property` | `string` | Campo que define o valor de meta para este objeto. | `meta_mensal` em `broker`. | ### 🔗 Contribuição Dimensional (`relation`) | Atributo | Tipo | Descrição | Comportamento Reativo | | :--- | :--- | :--- | :--- | | `contribution_property` | `string` | Campo do objeto filho que deve ser somado no agrupamento. | `valor` em `sale` agrupado por `broker`. | --- --- > [!IMPORTANT] > A taxonomia é o que transforma JSON morto em uma aplicação viva. Toda alteração nestes atributos deve seguir o **Protocolo FADAP**. --- > "Na arquitetura Anti-Gravity, os dados descrevem não apenas o que são, mas como devem se comportar. A Ontologia v3 estende isso para *como devem parecer*, *como devem navegar* e *como devem ser medidos*." --- # Docker Commands Source file: DOCKER_RUN.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/docker-run Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/docker-run # Docker Commands Run these commands from `g:\FastApp` in PowerShell: ```powershell docker build -t fastapp-laravel-api ./laravel-api docker build -t fastapp-nuxt ./lead-nuxt docker network create fastapp-net docker run -d --name laravel-api --network fastapp-net -p 8000:8000 --env-file ./laravel-api/.env fastapp-laravel-api docker run -d --name lead-nuxt --network fastapp-net -p 3000:3000 -p 3001:3001 --env-file ./lead-nuxt/.env -e NUXT_PUBLIC_API_BASE_URL=http://laravel-api:8000 -e NUXT_PUBLIC_SOCKET_URL=http://localhost:3001 fastapp-nuxt ``` Notes: - `lead-nuxt` now runs in **development mode** (`nuxt dev`) inside Docker. - Socket server is exposed on `3001` for real-time sync between browser tabs. Access: - Nuxt: `http://localhost:3000` - Laravel API: `http://localhost:8000` Stop both containers: ```powershell docker rm -f lead-nuxt laravel-api ``` --- # Resumo de Implementação: Reordenação Nativa Drag & Drop Source file: DRAG_DROP_SUMMARY.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/drag-drop-summary Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/drag-drop-summary # Resumo de Implementação: Reordenação Nativa Drag & Drop ## 📋 O Que Foi Implementado ### Componentes Criados/Modificados ``` app/ ├── components/ │ └── core/ │ ├── DynamicList.vue ✅ MELHORADO (adicionado Drag & Drop) │ └── PropertyListEditor.vue ✨ NOVO (editor especializado de propriedades) │ └── pages/ ├── fastapp/ │ ├── schema.vue ✅ MODIFICADO (integração de PropertyListEditor) │ └── example-dynamic-list.vue ✨ NOVO (exemplo de uso) ``` ## 🎯 Funcionalidades Implementadas ### 1. ✅ **DynamicList.vue** - Drag & Drop Nativo - **Integração Vuedraggable**: Componente `` envolvendo a lista - **Prop Condicional**: `sortable` (default: `false`) para ativar/desativar - **Drag Handle**: Ícone `⋮⋮` com classe `.drag-handle` - **Badges de Taxonomia**: Exibi `category`, `nature`, `status` - **Evento `reorder`**: Emitido ao finalizar arraste com a nova lista - **Animações CSS**: Transições suaves e visuais - **Backward Compatible**: Funciona sem a prop `sortable` **Arquivo**: [DynamicList.vue](app/components/core/DynamicList.vue) ### 2. ✨ **PropertyListEditor.vue** - Editor de Propriedades - **Componente Especializado**: Para editar metadados (propriedades de objetos) - **Drag & Drop**: Com seletor handle `.drag-handle` - **Edição Inline**: Nome, label, tipo, layout_grid, flags - **Checkboxes**: `required`, `show_in_list`, `show_in_form` - **Adição/Remoção**: Com confirmação de ação - **Indicador de Ordem**: Número serial de cada propriedade - **Eventos**: `update` (edição) e `reorder` (reordenação) **Arquivo**: [PropertyListEditor.vue](app/components/core/PropertyListEditor.vue) ### 3. ✅ **schema.vue** - Integração no Schema Manager - **Importação**: Componente `PropertyListEditor` importado - **Substituição**: Lista inline de propriedades substituída por editor visual - **Handlers**: Funções `onPropertyUpdate` e `onPropertyReorder` - **Sincronização**: Estado `isDirty` marcado como `true` ao reordenar - **Feedback**: Toast notifica usuário após reordenação **Arquivo**: [schema.vue](app/pages/fastapp/schema.vue) ## 🎨 Interface Visual ### Antes (sem reordenação) ``` PROPRIEDADES (4) ┌──────────────────────────────────────┐ │ [Name ] [Label] [Type] [Layout] │ │ [Email ] [Label] [Type] [Layout] │ │ [Phone ] [Label] [Type] [Layout] │ │ [Status ] [Label] [Type] [Layout] │ └──────────────────────────────────────┘ ``` ### Depois (com Drag & Drop) ``` PROPRIEDADES (4) [+ Adicionar] ┌──────────────────────────────────────────────────┐ │ ⋮⋮ [Name ] [Label] [Type] [L-Grid] ✓ ✓ ❌ │ ← Arrastável │ ⋮⋮ [Email ] [Label] [Type] [L-Grid] ✓ ✓ ❌ │ ← Reordena │ ⋮⋮ [Phone ] [Label] [Type] [L-Grid] ✓ ✓ ✓ │ ← Animado │ ⋮⋮ [Status] [Label] [Type] [L-Grid] 🔲 ✓ ❌ │ └──────────────────────────────────────────────────┘ |__ Handle visual |___ Checkboxes de flags ``` ## 📊 Fluxo de Dados ``` USER INTERACTION (arraste de propriedade) ↓ ↓ emit('reorder', localData.value) ↓ @reorder="onPropertyReorder" [PropertyListEditor.vue] ↓ onPropertyReorder(reorderedProperties) [schema.vue] ↓ editingObject.value.properties = reorderedProperties isDirty.value = true ↓ toast.add({ ... }) [notifica usuário] ↓ Botão "Salvar" habilitado ↓ saveChanges() [envia para API] ↓ API atualiza manifest JSON ``` ## 🔧 Configuração Técnica ### Vuedraggable Options ```javascript { animation: 200, // ms de duração group: "properties", // grupo para restricionar ghostClass: "ghost", // classe do elemento arrastado dragClass: "drag", // classe durante arraste handle: ".drag-handle", // seletor do handle easing: "cubic-bezier(1, 0, 0, 1)" // easing suave } ``` ### CSS Classes Aplicadas ```css .drag-list-move /* Transição entre posições */ .ghost /* Elemento semitransparente durante arraste */ .drag /* Elemento em drag state (escala + sombra) */ .drag-handle /* Cursor grab/grabbing */ .drag-active /* Container durante arraste */ ``` ## ✨ Destaques da Implementação ✅ **Type-Safe**: Tipagem completa TypeScript ✅ **Reativo**: Usa ref() e computed() do Vue 3 ✅ **Performático**: Computed properties para otimização ✅ **Acessível**: Checkboxes com labels e títulos ✅ **Responsivo**: Layout adapta em mobile/desktop ✅ **Documentado**: Comentários e código bem estruturado ✅ **Exemplos**: Arquivo de exemplo incluído ✅ **Backward Compatible**: Props opcionais ## 📝 Eventos Emitidos ### DynamicList.vue ```typescript emit('reorder', localData: any[]) // Nova ordem emit('edit', item: any) // Editar item emit('delete', item: any) // Deletar item emit('update', item: any) // Atualizar item emit('refresh') // Refresh lista ``` ### PropertyListEditor.vue ```typescript emit('update', { // Edição individual index: number, property?: PropSchema, action?: string, deletedIndex?: number }) emit('reorder', reorderedProperties: PropSchema[]) // Nova ordem ``` ## 🧪 Casos de Teste - ✓ Arrastar propriedade para baixo - ✓ Arrastar propriedade para cima - ✓ Adicionar nova propriedade - ✓ Remover propriedade (com confirmação) - ✓ Editar propriedade durante arraste - ✓ isDirty marca true após reordenação - ✓ isDirty marca false após salvar - ✓ Botão Salvar habilitar/desabilitar - ✓ Toast notifica reordenação - ✓ Ordem persiste no banco ## 📚 Documentação - **[IMPLEMENTATION_DRAG_DROP.md](IMPLEMENTATION_DRAG_DROP.md)**: Documentação técnica completa - **[example-dynamic-list.vue](app/pages/fastapp/example-dynamic-list.vue)**: Exemplos de uso - **Inline Comments**: Comentários explicativos no código ## 🚀 Próximos Passos 1. Testar formulário com as propriedades reordenadas 2. Verificar persistência no banco de dados 3. Adicionar validações customizadas se necessário 4. Integrar com CRM.vue para refletir ordem em formulários 5. Implementar Undo/Redo se necessário ## 📦 Dependências - ✅ `vuedraggable@4.0.1` (já instalado no projeto) - ✅ Vue 3.5.28+ - ✅ TypeScript (para type safety) - ✅ Tailwind CSS (para estilos) - ✅ PrimeVue (para components) --- **Data de Implementação**: 17 de Fevereiro de 2026 **Status**: ✅ Completo e Pronto para Testes --- # 🔌 FADAP PROTOCOL — O Motor de Sincronização Source file: FADAP_PROTOCOL.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/fadap-protocol Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/fadap-protocol # 🔌 FADAP PROTOCOL — O Motor de Sincronização O **FADAP Protocol** (Fastapp Data & Architecture Protocol) rege a sincronia entre as três camadas do sistema: Metadados, Manifesto e Storage. --- ## 🧩 O Problema das Três Camadas 1. **Desejo (Metadata Layer)**: O JSON editado no Schema Manager (`App.objects`). 2. **Percepção (Manifest Layer)**: O arquivo estático `static-manifest.ts` para performance. 3. **Realidade (Storage Layer)**: As tabelas físicas e colunas no PostgreSQL. O FADAP garante que a **Realidade** siga o **Desejo**. --- ## 🔄 O Ciclo de Sincronização (Fadap Sync) Sempre que uma mudança estrutural ocorre, o motor executa: 1. **Metadados (Desejo - Sovereign Patch)**: O JSON editado via `PATCH /api/app/[id]`. É a semente de toda mudança. 2. **Manifesto (Percepção - Snapshot Sync)**: Gerado via `POST /api/system/snapshot`. O motor bloqueia execuções de DDL se o manifesto não estiver em sincronia. 3. **Storage (Realidade - DDL Automation)**: O motor Nuxt analisa a tabela física e executa migrações (`ALTER TABLE`). **Este passo ocorre automaticamente através da API, nunca manualmente.** > [!WARNING] > A **Realidade** deve sempre seguir o **Desejo** através da API. Edições manuais no banco ou no manifesto causam "Esquizofrenia de Arquitetura", onde o motor não consegue mais prever o comportamento do dado. --- ## 🛠️ Heurísticas de Mapeamento (DDL Generator) O motor traduz tipos de metadados para tipos SQL reais: | Tipo Meta | SQL (Postgres) | Motivo | | :--- | :--- | :--- | | `string`, `enum` | `TEXT` | Flexibilidade máxima. | | `number` | `DOUBLE PRECISION` | Precisão decimal. | | `boolean` | `BOOLEAN` | Nativo. | | `array` / `json` | `JSONB` | Performance em dados semi-estruturados. | | `date` / `datetime`| `TIMESTAMP TZ` | Melhor prática global. | --- ## 🧬 Ontologia v3 e o FADAP Com a Ontologia v3, o FADAP sincroniza não apenas campos e tabelas, mas também: - **Semântica de campo** (`semantic: asset | money | phone`): persistida no JSON de `objects` - **Topologia de módulo** (`topology: focal | connected`): persistida no JSON de `modules` - **Temporal type** (`temporal_type: event`): persistida para ativar agendas automáticas > [!TIP] > O FADAP garante que as extensões semânticas da Ontologia v3 viagem do **Agent → Architect → Snapshot → Motor** sem perda de informação. É o protocolo que habilita a **Auto-Evolução**. --- > "O Protocolo Fadap é a garantia de que o sistema é evoluível sem medo de quebra de banco de dados. Ele é o elo entre a intenção (Agent) e a realidade (Storage)." --- # FAQ Reordenação Drag & Drop (Perguntas Frequentes) Source file: FAQ_DRAG_DROP.md HTML: https://creator.fastapp.cloud/fastapp/public-docs/page/repo/faq-drag-drop Markdown: https://creator.fastapp.cloud/fastapp/public-docs/raw/repo/faq-drag-drop # FAQ - Reordenação Drag & Drop (Perguntas Frequentes) ## ❓ Perguntas sobre Funcionalidade ### P: Como ativo a reordenação no meu componente? **R**: Adicione a prop `sortable="true"` ao DynamicList: ```vue ``` ### P: Qual é a diferença entre DynamicList e PropertyListEditor? **R**: - **DynamicList.vue**: Componente genérico para exibir coleções de dados com reordenação opcional - **PropertyListEditor.vue**: Componente especializado para editar propriedades de objetos (metadados) com suporte completo a inline-editing ### P: O que é o "drag-handle"? **R**: É o ícone `⋮⋮` (seis pontos) que aparece no início de cada linha quando `sortable="true"`. Você deve clicar/arrastar nele para mover a linha de posição. ### P: Preciso atualizar a API quando reordenar? **R**: Não imediatamente. O componente emite o evento `reorder` com a nova ordem. Você deve: 1. Capturar o evento 2. Marcar como "dirty" (isDirty = true) 3. Aguardar o usuário clicar "Salvar" 4. Então enviar para a API ### P: Como funciona a sincronização com o estado "dirty"? **R**: ```typescript @reorder="(newList) => { isDirty = true; // Marca como modificado dataList = newList; // Atualiza dados locais toast.add({ severity: 'info', summary: 'Alteração pendente' }); }" ``` ### P: Posso reordenar dentro de um grupo específico? **R**: Sim. Use a propriedade `group` no componente: ```javascript const dragOptions = { group: "meu-grupo", // Restringe a qual grupo pode arrastar // ... } ``` ### P: O que acontece se o usuário sair sem salvar? **R**: Dois comportamentos: 1. **PropertyListEditor**: Detecta isDirty e avisa ("Existem alterações não salvas") 2. **DynamicList**: Sem gestão de dirty, você controla no componente pai --- ## ❓ Perguntas sobre UI/UX ### P: Como faço o handle aparecer apenas ao passar o mouse? **R**: Atualmente ele aparece sempre. Se quiser mudar, adicione CSS: ```css .drag-handle { opacity: 0.3; /* Invisível */ } .record-card:hover .drag-handle { opacity: 1; /* Visível ao passar mouse */ } ``` ### P: Posso customizar o ícone do handle? **R**: Sim! Edite em DynamicList.vue ou PropertyListEditor.vue: ```vue ``` ### P: Qual é a cor durante o arraste? **R**: Configurada em CSS no `.drag` class: ```css .drag { opacity: 1; transform: rotate(2deg) scale(1.02); box-shadow: 0 5px 25px rgba(99, 102, 241, 0.3); /* Azul índigo */ } ``` ### P: Posso mudar a duração da animação? **R**: Sim, no `dragOptions`: ```javascript const dragOptions = { animation: 200, // ms (mude aqui) // ... } ``` ### P: Como funciona no mobile? **R**: Funciona normalmente, mas considere: - Handle talvez seja pequeno (aumentar em mobile) - Arraste de toque é suportado - Recomenda-se aumentar padding em telas pequenas --- ## ❓ Perguntas sobre Dados ### P: Os dados são salvos automaticamente ao reordenar? **R**: Não. Você deve: 1. Capturar evento `reorder` 2. Atualizar estado local 3. **Manualmente** chamar API ao clicar "Salvar" Exemplo: ```typescript function handleReorder(newOrder) { localData.value = newOrder; // Local isDirty.value = true; // Marcar como pendente // Não salva ainda! } ``` ### P: Como garanto que a ordem é única? **R**: A ordem é determinada pelo índice no array. Vue mantém a reatividade automaticamente. ### P: E se duas propriedades tiverem o mesmo nome? **R**: Isso causaria conflito. Implemente validação: ```typescript function validatePropertyName(newName) { const exists = editingObject.properties.some(p => p.name === newName); if (exists) { toast.add({ severity: 'error', summary: 'Nome já existe' }); return false; } return true; } ``` ### P: Como desfaço uma reordenação? **R**: Três opções: 1. **Sem salvar**: Recarregue a página (dados não salvos são perdidos) 2. **Com salvar**: Reordene novamente manualmente 3. **Undo avançado**: Implemente stack de mudanças (ver roadmap) ### P: Posso reordenar entre múltiplas listas? **R**: Apenas se as listas tiverem o mesmo `group`: ```typescript // Lista A const dragOptionsA = { group: "shared" }; // Lista B const dragOptionsB = { group: "shared" }; // Agora itens podem ir de A para B e vice-versa ``` --- ## ❓ Perguntas sobre Performance ### P: Qual é o limite de propriedades que posso reordenar? **R**: Teoricamente ilimitado, mas: - **< 50**: Muito rápido - **50-200**: Rápido - **200+**: Considere virtualização (ainda não implementada) ### P: Há lag ao arrastar muitos itens? **R**: Se houver, verifique: 1. Número de computed properties 2. Watchers profundos 3. Tamanho dos dados renderizados 4. Performance do navegador (DevTools > Performance) ### P: Como otimizo a renderização? **R**: ```typescript // ✅ BOM: Computed para dados filtrados const visibleProperties = computed(() => { return properties.value.filter(p => p.show_in_list); }); // ❌ EVITE: Lógica no template
``` ### P: Devo usar `v-key="item.id"` ou `v-key="index"`? **R**: Sempre `item.id` se disponível. O índice muda ao reordenar, causando re-renders desnecessários. --- ## ❓ Perguntas sobre Integração ### P: Como integro com dados do backend? **R**: ```typescript // 1. Fetch dos dados const properties = ref([]); onMounted(async () => { properties.value = await $fetch('/api/object/lead/properties'); }); // 2. Componente com sortable // 3. Handler function onReorder(newOrder) { isDirty = true; // Salvar mais tarde com API call } ``` ### P: Como funciona com Pinia store? **R**: ```typescript // store/object.ts const properties = ref([]); function setProperties(newProperties) { properties.value = newProperties; } function reorderProperties(newOrder) { properties.value = newOrder; isDirty = true; // Marcar store como dirty // Salvar quando necessário } ``` ### P: Como sincronizo com Sistema de Manifesto? **R**: O Schema Manager já faz isso. Seu objeto é: ```typescript editingObject.value.properties = reorderedProperties; // Atualiza referência isDirty.value = true; // Marca para salvar ``` --- ## ❓ Perguntas sobre Debugging ### P: Como vejo quais eventos estão sendo disparados? **R**: Adicione logs no handler: ```typescript function onReorder(newOrder) { console.log('[REORDER EVENT]', newOrder); console.log('[ORDER NAMES]', newOrder.map(p => p.name)); } ``` ### P: Como verifico o estado drag durante animação? **R**: Use DevTools: 1. Abra Elements/Inspector 2. Selecione um item durante arraste 3. Veja classe `.drag` sendo aplicada ### P: Como verifico se isDirty está sendo marcado? **R**: ```typescript watch(() => isDirty.value, (newVal) => { console.log('[DIRTY CHANGED]', newVal); }); ``` ### P: Por que o evento reorder é emitido múltiplas vezes? **R**: Verifique se você tem múltiplos watchers: ```typescript // ❌ PROBLEMA: Watcher duplicado watch(properties, () => { emit('reorder', properties.value); // Emite sempre que muda }); // ✅ SOLUÇÃO: Emita apenas no @end do draggable @end="onDragEnd" ``` --- ## ❓ Perguntas sobre Erros Comuns ### P: "Cannot read property 'name' of undefined" **R**: Propriedade está null. Verifique: ```typescript // ✅ BOM: Validação const propName = property?.name || 'Unknown'; // ❌ EVITE: Sem checar const propName = property.name; // Erro se property = null ``` ### P: Array não atualiza após reordenar **R**: Você está mutando diretamente? Use Vue.set: ```typescript // ❌ ERRADO properties[0] = newValue; // Vue não detecta // ✅ CORRETO properties.value[0] = newValue; // Reativo // ou properties.value = [...properties.value]; // Novo array ``` ### P: Drag & Drop não funciona **R**: Verifique: 1. `vuedraggable` está importado? 2. Prop `sortable="true"` foi adicionado? 3. Handle `.drag-handle` existe no template? 4. Browser suporta drag & drop? ### P: Estilos não aplicam durante arraste **R**: Você está importando o CSS de `.drag`? ```vue ``` --- ## ❓ Perguntas sobre Acessibilidade ### P: Como faço reordenação acessível via teclado? **R**: Isso ainda não foi implementado. Você pode: 1. Adicionar botões "Mover Para Cima"/"Mover Para Baixo" 2. Usar Shift + Setas para reordenar (custom) 3. Implementar ARIA labels Exemplo de botões: ```vue