# OutDo: referência de configuração, completa > Referência gerada do código, versão 17f3e0bc59d9. 112 páginas, em português de Portugal. > Índice com URLs: https://docs.out-do.app/llms.txt --- # API REST A API REST do OutDo é documentada em OpenAPI: ## [Abrir a referência OpenAPI](/reference/api/openapi) Essa página desenha, aqui no site, o `openapi.json` comitado: endereço base, todas as rotas, corpos e respostas. O mesmo documento é servido ao vivo pelo próprio serviço, em [https://docs-api.out-do.app](https://docs-api.out-do.app) (desenvolvimento: [https://docs-api.dev.out-do.app](https://docs-api.dev.out-do.app)), onde reflete a versão que está de pé nesse ambiente. Esta página não duplica a referência: diz só o que é preciso saber antes de a abrir. ## Autenticar Dois tipos de credencial, no mesmo cabeçalho: ```http Authorization: Bearer ``` - Uma **chave de API** da organização, que começa por `outdo_sk_`. É a credencial de um agente ou de uma integração. - Um **JWT de utilizador** do Supabase, que é o que a aplicação usa. Uma chave só vê o que a organização dela vê: as políticas de segurança da base de dados continuam a mandar, e o scope nunca alarga o que elas negam. ## Scopes | Scope | O que autoriza | |---|---| | `read` | Ler linhas e estrutura. | | `write` | Criar, alterar e apagar linhas. | | `structure` | Criar e alterar estrutura: tabelas, colunas, vistas, rails, módulos e automações. | Os scopes escolhem-se na cunhagem da chave, e o `structure` é **aditivo**: só vale acompanhado de `write`. Uma chave com `structure` e sem `write` é recusada à cunhagem, com um 422, em vez de nascer inútil: o perfil de acesso sintético de uma chave deriva os verbos de `read` e de `write`, logo uma chave só com `structure` nasceria sem permissão de ver e a base negava-lhe tudo. ## Automações As rotas `/v1/workflows-v2` do OpenAPI criam e versionam automações. O envelope da definição, o ciclo rascunho até ativo e dois exemplos completos estão em [Automações (WorkflowV2)](/reference/workflows-v2). ## Limites que poupam tempo - Uma organização em plano gratuito não cunha chaves de API. - A escrita de estrutura é escrita a sério: um agente com `structure` cria tabelas e colunas a fundo. Construir primeiro em desenvolvimento é a regra. --- # Referência Esta secção descreve, campo a campo, a configuração JSON de tudo o que se pode construir no OutDo: os componentes de uma coluna, as vistas, os passos e os gatilhos das automações, e as entidades de estrutura. É pública e não precisa de credenciais. As páginas de cada tipo **nascem do código**: um gerador lê as declarações de campo do `outdo_library` e escreve-as durante o build do site. Cada página diz no fim de que versão das declarações nasceu. Não se editam à mão: a edição desaparece no build seguinte. ## Como ler uma página Cada página tem uma tabela com seis colunas: | Coluna | O que diz | |---|---| | Chave | O nome exato da chave no JSON. Distingue maiúsculas. | | Tipo | `string`, `integer`, `number`, `boolean`, `enumeration`, `uuid`, `expression`, `list`, `map` ou `json`. Uma lista diz também de que são os elementos. | | Obrigatório | `sim` quando a config é inválida sem a chave. | | Omissão | O valor que a plataforma usa quando a chave não vem. `-` significa que não há omissão declarada. | | Descrição | Para que serve. Marca `Opaco` quando o caminho transporta dados do utilizador e nenhum resolvedor lhe toca, e `Descontinuado` quando sai numa versão futura. | | Referência | Se o valor aponta para outra coisa: a que tipo aponta e em que forma. | Os campos compostos (um mapa dentro de outro, ou uma lista de objetos) têm sub-tabela própria, com o caminho no título: `options[]` são os elementos da lista `options`. O bloco `Exemplo JSON` de cada página é sintetizado, não copiado de uma organização real: leva **os campos obrigatórios e os que têm omissão declarada**, e mais nada. É o mínimo que funciona, não um inventário. ## Envelopes: quando a config é uma lista de um Duas configs da plataforma não são um objeto, são uma **lista com um único elemento**, e ler `config` em vez de `config[0]` é o erro mais comum a quem escreve um template à mão: - `View.config` é `[ { ... } ]`. - `Rail.config` é `[ { ... } ]`. As páginas dessas keys levam um aviso em cima. Todas as outras configs (`Featurecolumn.config`, `trigger_config`, `graph_config`) são um mapa. ## Nomes contra uuids A plataforma identifica as coisas por `uuid`, e a maior parte das configs guarda uuids. Num template isso não serve: o uuid de uma tabela da organização de origem não existe no destino. Por isso a coluna **Referência** diz sempre a **forma**: - `uuid`: só aceita um identificador. - `nome`: só aceita o nome técnico (por exemplo o `name` de uma coluna). - `uuid ou nome`: aceita os dois, e o resolvedor tenta o uuid primeiro. Quando a referência é a uma coluna, a forma vem acompanhada de **a que tabela pertence**: ``coluna de `linkedFeatureId` (uuid)`` quer dizer que a coluna é da tabela indicada na chave `linkedFeatureId` da mesma config. ## A gramática das referências simbólicas Num pacote de template, as referências viajam como **strings simbólicas**. Só estas são referências, e tudo o mais que comece por `$` é texto normal: ```text ^\$(workspace|currentUser|organization|[fcvrmw]_[a-z0-9_]+)$ ``` Os prefixos das letras: `f_` tabela (feature), `c_` coluna, `v_` vista, `r_` rail, `m_` módulo, `w_` workflow. Mais três nomes fixos: `$workspace`, `$currentUser` e `$organization`. Um valor de linha como `"$100"` **não** é referência, e é por isso que a gramática é fechada e não "tudo o que começa por dólar". ## Idioma e locales A referência é gerada **só em português de Portugal**. O site tem uma versão inglesa, e `/en/reference/**` serve exatamente estas mesmas páginas, sem tradução. É deliberado: a alternativa, traduzir centenas de páginas geradas a cada mudança de campo, produziria uma tradução sempre atrasada face ao código. ## Para agentes - [`/llms.txt`](pathname:///llms.txt): índice curto, com URLs absolutos e uma linha por página. - [`/llms-full.txt`](pathname:///llms-full.txt): todas as páginas desta secção, concatenadas em Markdown. - [API REST](/reference/api/) e [MCP](/reference/mcp/): como autenticar e onde bater. --- # MCP O OutDo publica um servidor MCP (Model Context Protocol) com transporte Streamable HTTP, um endpoint por ambiente: ```text https://ai.out-do.app/mcp https://ai.dev.out-do.app/mcp ``` A lista de ferramentas, com os argumentos de cada uma, é gerada do código e vive em [Ferramentas MCP](/reference/mcp/ferramentas). As quatro ferramentas de automações (`list_workflows_v2`, `get_workflow_v2`, `validate_workflow_v2`, `create_workflow_v2`) têm contexto próprio em [Automações (WorkflowV2)](/reference/workflows-v2), incluindo os dois passos que só existem na API REST. ## Autenticar Há duas formas de credencial, e **a superfície de ferramentas não é a mesma nas duas**: o `tools/list` da ligação é que manda, e a página [Ferramentas MCP](/reference/mcp/ferramentas) diz, por ferramenta, quais a alcançam. ### Chave de API, sozinha É a forma que interessa a um agente externo: a mesma chave `outdo_sk_` da API REST, no `Authorization`, sem mais nada. ```http Authorization: Bearer outdo_sk_... ``` A sessão de chave tem as ferramentas de leitura, as escritas de linhas (`create_rows`, `update_row`, `delete_row`) e as dezoito de estrutura: `apply_template`, `create_column`, `create_feature`, `create_module`, `create_rail`, `create_view`, `create_workflow_v2`, `get_template`, `get_template_job`, `get_workflow_v2`, `list_modules`, `list_rails`, `list_templates`, `list_views`, `list_workflows_v2`, `suggest_template_mappings`, `update_view` e `validate_workflow_v2`. Não tem `generate_report`: essa registra consumo por utilizador (uma chave não é uma pessoa) e chama rotas de configuração de IA que uma chave pode não alcançar. A chave não é resolvida no servidor MCP: segue para o `outdo_api_data`, que é o único sítio a resolver identidade e scopes. Quem governa o que a sessão pode fazer são os **scopes da chave** (`read`, `write`, `structure`), exatamente como na API REST, e uma escrita de estrutura sem o scope `structure` é recusada lá. ### Chave de serviço mais JWT de utilizador É a forma com a identidade de um utilizador concreto: a chave de serviço é um segredo do lado do servidor e o JWT diz por quem a ligação trabalha. ```http Authorization: Bearer X-OutDo-Service-Key: ``` A sessão de utilizador tem as ferramentas de leitura e o `generate_report`. As escritas de linhas só aparecem se o deploy tiver `MCP_ALLOW_WRITES` ligado, e as ferramentas de estrutura nunca aparecem: um JWT não traz scopes com que as limitar, pelo que a estrutura constrói-se com uma chave de API (aqui ou pela API REST). Todos os acessos ficam limitados às RLS do utilizador. ## O que um agente deve ler primeiro 1. [Como ler a referência](/reference/): envelopes, formas das referências e a gramática dos símbolos. 2. [`/llms.txt`](pathname:///llms.txt): índice de tudo, com URLs absolutos. 3. A ferramenta `get_definitions`, que devolve as mesmas declarações que geram estas páginas, em JSON. --- # Formato do pacote (v2) Um pacote de template tem **duas metades, guardadas em sítios diferentes**: - o **manifesto**, um objeto JSON na coluna `manifest` da tabela `Template`; - as **linhas**, uma entrada por tabela na tabela `TemplatePayload`. A separação não é cosmética. As streams de `Template` do PowerSync são `SELECT *`, logo o manifesto de um template `system` desce para todos os dispositivos de todos os clientes. A `TemplatePayload` não entra em nenhuma sync rule: lê-se e escreve-se por HTTP, com a RLS espelhada do `Template` pai. Guardar as linhas dentro do manifesto punha dados de um workspace a descer para quem nunca os pediu. A versão 2 acrescenta `source`, `items[]`, `dependencies[]`, `unresolved[]` e `redacted[]` ao manifesto que já existia, e continua a ler a versão 1 sem conversão: a ausência de `templateVersion` lê-se como `"1"`. ## O ficheiro: o envelope `{manifest, payloads}` Fora da base, as duas metades viajam juntas num só ficheiro `.json`: o objeto de topo tem o `manifest` e o array `payloads`, uma entrada por item `rows` — e cada entrada é a **entrada do exportador**, o mesmo objeto que fica na coluna `rows` da `TemplatePayload` (ver [As linhas](#as-linhas-templatepayload)) e não a linha da tabela. É este envelope que o botão **Importar pacote (.json)…** lê e o que o `infra/scripts/dump_template_package.sh` escreve. O `payloads` pode faltar (lê-se como vazio) e um manifesto solto no topo, sem envelope, também se aceita; um ficheiro sem `templateVersion` não é um pacote e segue como plano. ```json { "manifest": { "templateVersion": "2", "id": "frota", "name": "frota", "label": "Frota", "scope": "workspace", "semver": "1.0.0", "items": [{ "uid": "u_0009", "kind": "rows", "count": 1 }] }, "payloads": [ { "featureRef": "f_viaturas", "itemUid": "u_0009", "count": 1, "rows": [{ "uid": "u_r001", "data": { "matricula": "AA-00-AA" } }] } ] } ``` ## As duas camadas do manifesto O manifesto é a união de duas camadas que ninguém mistura: - a **identidade de catálogo** — `id`, `name`, `label`, `description`, `icon`, `color`, `vocabulary`, `category`, `scope`, `variables[]`, `blocks[]`, `tags[]`, `semver`, `visibility` — escrita por quem publica o template; - o **pacote** — `templateVersion`, `source`, `items[]`, `dependencies[]`, `unresolved[]`, `redacted[]`, `plan` — escrito pelo exportador. `scope` é um de `organization`, `workspace`, `module`, `feature`; `visibility` é um de `system`, `org`, `public`. ```json { "templateVersion": "2", "id": "erp-oficina", "name": "erp_oficina", "label": "ERP de oficina", "scope": "workspace", "visibility": "org", "semver": "1.0.0", "variables": [{ "key": "nome_oficina", "label": "Nome da oficina" }], "source": { "workspaceName": "Oficina", "generatedAt": "2026-09-12T18:02:00Z", "definitionsVersion": "2026.09.1" }, "items": [ { "uid": "u_0001", "kind": "feature", "ref": "f_viaturas", "label": "Viaturas" }, { "uid": "u_0002", "kind": "column", "ref": "c_viaturas_matricula", "label": "Matrícula", "parent": "u_0001" }, { "uid": "u_0003", "kind": "column", "ref": "c_viaturas_fornecedor", "label": "Fornecedor", "parent": "u_0001" }, { "uid": "u_0005", "kind": "view", "ref": "v_viaturas_documentos", "label": "Documentos", "parent": "u_0001" }, { "uid": "u_0007", "kind": "workflow", "ref": "w_ocr_compras", "label": "OCR de compras", "stepIds": ["s_ler", "s_resolve"] }, { "uid": "u_0009", "kind": "rows", "parent": "u_0001", "count": 128, "dataClass": "transactional" } ], "dependencies": [ { "uid": "u_0011", "kind": "feature", "ref": "f_fornecedores", "form": "uuid", "required": true, "resolution": "import", "detail": "blueprint", "description": "Tabela de onde se escolhem as linhas.", "identity": { "name": "fornecedores", "label": "Fornecedores", "columns": [ { "uid": "u_0012", "ref": "c_fornecedores_nif", "name": "nif", "label": "NIF", "type": "text", "defaultComponent": "textfield" } ] }, "usedBy": [ { "uid": "u_0003", "targets": "u_0011", "path": "linkedFeatureId", "reason": "Tabela de onde se escolhem as linhas." } ], "blueprint": { "steps": [] } } ], "unresolved": [ { "uid": "u_0005", "path": "[0].workflowV2Id", "kind": "workflowV2", "form": "uuid", "sourceLabel": "OCR de compras", "reason": "ref_adiante", "action": "chave esvaziada" } ], "redacted": [ { "uid": "u_0007", "path": "connectionVariables", "reason": "campo declarado `secret`: pode transportar segredos do inquilino de origem, logo sai redigido" } ], "plan": { "planVersion": "1", "id": "u_0000", "summary": "Estrutura do workspace \"Oficina\" (1 tabela, 1 coluna, 1 automação, linhas de 1 tabela)", "target": { "workspaceId": "$workspace" }, "metadata": { "source": "export", "generatedAt": "2026-09-12T18:02:00Z" }, "externalRefs": ["f_fornecedores", "c_fornecedores_nif"], "steps": [] } } ``` O `source` tem **três campos e mais nada**: o nome do workspace de origem, o instante da exportação e a versão das declarações com que o pacote foi escrito. Nenhum identificador de organização ou de workspace entra aqui. ## `items[]` — o que vai em cheio Cada item tem um `uid` estável (um `u_` seguido de um UUID v4) que é a chave por que o `unresolved[]`, o `redacted[]`, os steps do plano e as entradas de `TemplatePayload` lhe apontam. | Chave | O que diz | |---|---| | `uid` | A identidade do item dentro do pacote. | | `kind` | Um de `feature`, `column`, `view`, `module`, `rail`, `workflow`, `rows`. | | `ref` | O `$ref` que o plano declara para ele. Ausente **exatamente** quando o `kind` é `rows`. | | `label` | O rótulo de origem, para quem lê o pacote. | | `parent` | O `uid` do item pai quando o pai também viaja: a tabela de uma coluna ou de uma vista, o módulo de um rail, a tabela de um `rows`. | | `count` | Só em `rows`: quantas linhas a entrada de payload leva. | | `dataClass` | Só em `rows`: `reference` ou `transactional`. | | `stepIds` | Só em `workflow`: os `id` dos passos do grafo, que ficam **estáveis**. | O `kind` de um item não se lê na letra do `ref`: a gramática de referências partilha o prefixo `w_` entre workspace e workflow, e é por isso que cada item leva o seu `kind`. **`dataClass`** é derivado e nunca perguntado: uma tabela que alguma coluna de ligação do pacote (`linked_select`, `auto_match`) de **outra** tabela aponta é tabela de domínio (`reference`), e as linhas dela são a proposta natural; uma tabela que nenhuma ligação dessas aponta é `transactional`, e as linhas dela são dados de um cliente — uma vista, um separador de rail ou um gatilho de automação dizem onde a tabela aparece e quem lhe mexe, não que as linhas de outra apontem as dela. O exportador escreve **sempre** um dos dois — tem o fecho, logo tem sempre resposta — e não diz por item de onde tirou a classe nem onde estão as linhas: a classe é derivada e as linhas estão **sempre** na `TemplatePayload`. Quem **lê** trata qualquer outro valor (um `dataClass` escrito à mão ou vindo de uma versão anterior do formato) como não sendo `reference`, que é a única classe que muda o que o ecrã de seleção propõe. **`stepIds`** existe para uma razão concreta: os tokens `{{vars.steps..…}}` dentro de um grafo apontam para esses `id` e não se regeneram na importação. ## `dependencies[]` — o que vai descrito Uma dependência é uma entidade que o pacote **usa e não leva**. Um nível só, e uma entrada por **entidade-raiz**: uma coluna nunca é dependência, a tabela dela é — com a coluna em `identity.columns`. Cinco referências à mesma tabela dão uma dependência, não cinco. | Chave | O que diz | |---|---| | `uid` | A identidade da dependência dentro do pacote. | | `kind` | O tipo de entidade, no vocabulário das referências: `feature`, `view`, `module`, `rail`, `workflow`, `workflowV2`, `connection`, `timerProfile`, `channel`. Nunca `column`. | | `ref` | O `$ref` simbólico pelo qual as configs do pacote a nomeiam. | | `form` | `uuid` ou `name`, e é a forma **efetiva** e não a declarada: um campo que aceita id ou nome conta como `uuid` se casou por id e como `name` se casou por nome. | | `required` | `false` só quando **todos** os usos estão em campos não obrigatórios e com valor por omissão. | | `resolution` | A proposta do exportador: `import`, `map` ou `skip`. | | `detail` | `blueprint` quando há `blueprint`, `identity` quando não. | | `description` | A frase que o assistente de importação mostra a quem decide. | | `identity` | Como se reconhece a entidade no destino: `name`, `label` e as colunas usadas. | | `usedBy[]` | Cada uso: que item a usa, em que caminho, e porquê. | | `blueprint` | Os steps que a reconstroem. Só para `kind: feature`. | A **`form`** decide o que o destino pode fazer: uma dependência de forma `name` pode ser satisfeita por um nome igual, uma de forma `uuid` não. Numa dependência de forma `name` a config **mantém o nome** em vez de um `$ref` — o `ref` existe para a dependência se poder nomear em `externalRefs` e em `usedBy`. É o caso de `connection` e de `timerProfile`, cujos refs levam o próprio tipo por prefixo (`connection_`, `timerprofile_`) porque a gramática de refs só cobre as letras `f`, `c`, `v`, `r`, `m` e `w`. Um `channel` é de forma `uuid` e a config leva mesmo o `$ref`, logo tem de bater a gramática: o ref dele é `m_`, pela mesma regra do `w_`, que já serve workspace e workflow — o tipo lê-se no `kind` e nunca na letra. Atenção à assimetria de vocabulário: um item de automação tem `kind: workflow`, mas uma dependência de automação pode ter `kind: workflowV2` — o item descreve o que viaja, a dependência descreve a referência que a apontou. A **`resolution`** é uma proposta e nunca uma decisão; quem decide é o destino. A regra é fechada: - `map` quando o `kind` nunca se reconstrói — `connection`, `mailbox`, `channel`, `timerProfile` levam segredos ou estado do inquilino; - `map` quando a `form` é `name` — o nome é o que o destino sabe procurar; - `import` quando há `blueprint`, `map` quando não há. O exportador **nunca propõe `skip`**: é uma escolha de quem importa. E `skip` deixa a chave de referência **vazia**, nunca com o uuid de origem, e carimba o item no relatório final como quebrado de propósito. Um uuid morto seria uma coluna que existe, não liga e não se queixa. Quem esvazia é o **executor**, no momento de aplicar: reescreve o plano e as linhas antes do primeiro step, e cada campo que ficou vazio sai no relatório do job com a razão `dependencia_saltada` e o `ref` da dependência que o causou. Uma dependência de **canal** (`kind: channel`) nasce de um passo `notify` com `scopeType: channel`: viaja com a `identity` do canal de origem (`name`, e `label` quando o há — nunca os membros), sem `blueprint`, e sempre `required: true` — a omissão vazia do `scopeId` não é recurso nenhum, e um aviso sem canal não se publica. O `map` oferece os canais **com nome** da organização de destino (uma conversa direta não tem nome e não se mapeia); o `skip` deixa o `scopeId` vazio, sai no relatório com `dependencia_saltada`, e a automação chega ao destino por publicar — quem a quiser ativa escolhe o canal lá e publica-a. A **`identity`** leva `name`, `label` e **só as colunas efetivamente referenciadas**, cada uma com `uid`, `ref`, `name`, `label`, `type` e `defaultComponent`. Mandar a tabela toda era mandar o esquema de uma organização para dentro de um pacote que vai para outra. O **`usedBy[]`** tem `uid` (o item que usa), `targets` (o `uid` da própria dependência), `path` (o caminho dentro da config desse item) e `reason` — que é a descrição declarada do campo que a referência ocupa. A `description` da dependência é a `reason` do uso com mais peso: primeiro os usos de forma `uuid`, depois a ordem de aparição. Gera-se sempre, nunca se escreve à mão. O **`blueprint`** só existe para `kind: feature`: as vistas e as automações de uma dependência não viajam. Leva um `create_feature` e um `create_column` por coluna da `identity`, com os refs já cunhados, e a `order` é a da **criação** (1, 2, 3, …) e não a da tabela de origem — o blueprint cria só as colunas referenciadas, logo prometer a ordem da origem era mentir. ```json { "steps": [ { "uid": "u_0011", "ref": "f_fornecedores", "tool": "create_feature", "args": { "name": "fornecedores", "label": "Fornecedores" } }, { "uid": "u_0012", "ref": "c_fornecedores_nif", "tool": "create_column", "args": { "featureId": "$f_fornecedores", "name": "nif", "label": "NIF", "type": "text", "defaultComponent": "textfield", "order": 1 } } ] } ``` O `detail` é derivado e gravado à mesma, porque é o que um leitor humano vê primeiro. Quem **constrói** um pacote tem de o manter coerente: `detail` é `blueprint` se e só se `blueprint` existir, e um pacote em que os dois discordem é **recusado** na leitura em vez de corrigido em silêncio. ## As resoluções, no pedido de aplicação Quem aplica um pacote decide, dependência a dependência, o que acontece no destino. A decisão viaja no corpo do pedido (`POST /apply/templates/{id}` no executor, `POST /v1/templates/{id}/apply` na API, `apply_template` no MCP), num mapa indexado pelo `$ref` da dependência — o cifrão é tolerado, porque quem escreve o mapa à mão copia-o do plano: ```json { "workspaceId": "…", "includeRows": true, "resolutions": { "f_clientes": {"action": "map", "id": "", "columns": {"c_clientes_nif": ""}}, "f_artigos": {"action": "import"}, "f_zonas": {"action": "skip"} } } ``` | Ação | O que faz | |---|---| | `import` | Aplica o `blueprint` da dependência: ela passa a ser criada pelo próprio plano. Sem `blueprint` é recusado, com o nome do ref. | | `map` | Liga o `$ref` a uma entidade que **já existe** no destino. O `id` é obrigatório. | | `skip` | Esvazia tudo o que a dependência segurava e relata cada campo. Nada fica a apontar para um id da organização de origem. | O **`columns`** é opcional e só faz sentido dentro de um `map`: mapeia, uma a uma, as colunas da `identity` da dependência (`` para o id dela no destino). As que ficarem de fora continuam por ligar — mapear a tabela não adivinha as colunas. Uma coluna por ligar que o **plano use** é recusada antes de o job nascer, com **422** `mapping_columns_incomplete` e o `ref` da coluna na resposta: o plano pedia um `$c_*` que ninguém semeou e isso rebentava lá dentro da transação da estrutura, sem dizer a quem chamou o que corrigir. Uma coluna da `identity` que o plano não use não é recusada — não falta a ninguém. Um id mapeado tem de ser uma tabela do **workspace de destino** ou uma `shared` da organização dele, e a coluna tem de ser da **tabela** que a mesma resolução mapeou. É a mesma fronteira que as sugestões oferecem: aceitar aqui o que o assistente nunca propõe deixava mapear para fora do destino. As `shared` entram porque vivem noutro workspace da mesma organização por desenho. Um id fora daí é recusado com `mapping_feature_not_found` ou `mapping_column_not_found`, os dois com o `ref` na resposta — uma coluna da organização certa mas de outra tabela era uma ligação plantada no sítio errado. O `skip` esvazia **três** coisas, pela regra do exportador (escalar vira `""`, chave de mapa **desaparece**): as ocorrências do `$ref` da dependência nos args dos steps; as ocorrências dos `$ref` das colunas da `identity` dela; e as **células das linhas** das colunas de ligação que a apontavam — que não têm `$ref` nenhum, porque o exportador guarda a célula com o valor de origem. Nenhum step se larga: largar um fazia desaparecer o rail inteiro. ## Os modos de linhas, no mesmo pedido Ao lado das resoluções, e não dentro delas: as resoluções respondem às dependências e os modos às **linhas**, e misturá-los dava um vocabulário com duas gramáticas. O mapa é indexado pelo `featureRef` da tabela (o cifrão é tolerado): ```json { "includeRows": true, "rowsModes": {"f_artigos": "missingByKey", "f_movimentos": "none"} } ``` | Modo | O que faz | |---|---| | `all` | Insere todas as linhas do pacote. É a **omissão**: um `featureRef` que não esteja no mapa fica com ele. | | `missingByKey` | Insere só as linhas cuja chave ainda não existe no destino. Exige a chave **verificada** no pacote (`keyColumn` com `keyUnique: true`). | | `none` | Não insere linha nenhuma dessa tabela. | O `includeRows: false` é o interruptor **global** e ganha sempre: com ele não se lê modo nenhum. Um `missingByKey` numa tabela sem chave verificada é recusado com **422** `rows_mode_without_key` e o `ref` na resposta — adivinhar a chave duplicava linhas do cliente em silêncio. A comparação é a mesma que decidiu o `keyUnique` na origem: o valor da célula em **cru**, sem `trim` e sem distinguir maiúsculas. Duas réguas para a mesma chave davam "já existe" de um lado e "falta" do outro. As linhas deixadas de fora contam-se no relatório do job, por tabela, em `rows[].existing`: ```json {"rows": {"f_artigos": {"inserted": 419, "updated": 0, "skipped": 0, "existing": 31}}} ``` O `existing` é do que o modo filtrou **nesta** passagem; o `skipped` continua a ser o que uma passagem anterior já tinha escrito. A pré-visualização da app não adianta este número: as linhas do destino podem nem estar sincronizadas no dispositivo, e um número que às vezes está certo é pior do que nenhum. Uma linha deixada de fora continua a ser o **alvo** das ligações: o `refs` de outra tabela que a aponte pelo `uid` liga à linha que **já está** no destino, e não ao uuid da organização de origem que a célula trazia. ## A segunda passagem das ligações à própria tabela Uma coluna que aponta outra linha da **mesma** tabela (uma tarefa-mãe, uma categoria-pai) não se resolve no lote: o alvo entra no mesmo lote ou num a seguir, e só aí tem id. A célula entra **vazia** e a tabela faz uma **segunda passagem** quando o último lote dela fecha, a escrever só essas colunas. As células ficam no ledger do job: uma retoma continua onde ficou, e reescrevê-las dá o mesmo valor. As que continuarem sem alvo no fim ficam vazias, com a entrada `row_ref_dropped` de sempre — e uma coluna multi-seleção resolve-se **inteira** ou fica vazia, como no lote. Quantas células ela ligou conta-se no relatório, por tabela, em `rows[].linked`. A chave só aparece quando houve o que adiar: ```json {"rows": {"f_tarefas": {"inserted": 120, "updated": 0, "skipped": 0, "existing": 0, "linked": 4}}} ``` ## As três fases do executor Aplicar é **estrutura**, depois **linhas**, depois **publicar**. A estrutura corre numa transação só; as linhas, em lotes, cada um com o seu ledger; e só no fim é que as automações com `published` são promovidas a versão ativa. A ordem não é arranjo: uma automação publicada na fase 1 escuta as tabelas que a fase 2 enche, e o pacote chegava com as automações já corridas sobre as linhas de exemplo. As que esperam ficam no ledger, em `pendingPublishes`, e saem de lá na mesma transação que as promove: uma retoma depois das linhas e antes da promoção publica-as na mesma, e reaplicar o pacote não as publica outra vez. Quantas foram promovidas está no relatório, em `published` — numa reaplicação é zero. ## O job, o lease e o 409 Aplicar um pacote é um **job** (`TemplateApplyJob`): o pedido devolve **202** com `{jobId, status}` e o progresso lê-se em `GET /v1/template-jobs/{id}`. Quem o corre segura um **lease** — `lease_owner` e `locked_until` na linha — que vale **60 segundos** e se renova a cada lote de linhas e, na fase da estrutura, pelo menos a cada 20 segundos. Sessenta segundos e não cinco minutos porque o TTL é o tempo que quem retoma espera depois de o executor morrer: um executor abatido a meio deixava o job preso até à expiração, com os pedidos a responderem 202 e nada a acontecer durante minutos. O lease toma-se quando **ninguém o tem**, quando **já expirou**, ou quando é do **próprio owner** — um executor que volte ao mesmo job não pode ficar à espera de si mesmo. Um lease vivo de outro nunca se toma, e quem o mede é o relógio da base. Enquanto ele está vivo, o pedido é **409** `job_active` — e isso vale também para um pedido que traz `jobId`, que é uma retoma: dar-lhe 202 era prometer uma corrida que morria no lease, em silêncio. ```json {"error": "job_active", "jobId": "…", "status": "rows", "lockedUntil": "…"} ``` O `lockedUntil` é o instante até ao qual o job está preso. Sai também no `GET /v1/template-jobs/{id}` da API (`locked_until`) e no `detail` do 409 dela: um prazo no futuro é alguém a trabalhar no job; um prazo no passado, ou nenhum, é um job livre para retomar com o `job_id` na mão. ### O que o job guarda das linhas que inseriu O ledger guarda, por tabela do pacote, o id de **todas** as linhas que a aplicação inseriu. Ficam de fora as que o modo por chave deixou passar por já estarem no destino, as repetidas de uma chave que o pacote traz duas vezes e as de uma atualização — nenhuma dessas foi criada aqui, e desfazê-las era mexer em dado que já lá estava. Quantas ficaram guardadas conta-se no relatório, por tabela, em `rows[].recorded`, e é esse o número que se pode desfazer: ```json {"rows": {"f_tarefas": {"inserted": 30, "updated": 0, "skipped": 0, "existing": 0, "recorded": 30}}} ``` O `recorded` é o **total** guardado e o `inserted` é o desta passagem: numa retoma são dois números diferentes, e por isso têm nomes diferentes. A chave só aparece quando há ids guardados — um job aplicado antes de o executor os começar a guardar não os pode reconstruir, e as ações que os usam recusam-no com nome em vez de responderem zero. ## `unresolved[]` — o que aponta para fora Toda a entrada diz o que o exportador **fez**, não o que ele gostaria de fazer. Um step nunca se larga por uma referência que não resolve: a chave esvazia-se e o buraco fica nomeado aqui. ```json { "uid": "u_0009", "path": "rows[].data.fornecedor", "kind": "rows", "form": "uuid", "reason": "tabela_alvo_sem_linhas", "action": "valor mantido", "count": 2 } ``` O `path` é o caminho dentro da config do item (`linkedValueColumn`, `views[0].featureId`, `rows[].data.fornecedor`). O das células de linhas não leva índice de propósito: a situação é da **coluna** e conta-se **uma vez**, por mais linhas que a repitam — uma tabela de 5000 linhas dava 5000 entradas iguais e o painel de fecho ficava ilegível. O `count` é opcional e diz **quantas linhas** a entrada agregada cobre, para a agregação não apagar a grandeza; falta nas entradas que não se agregam, que é o caso de toda a chave de config. O `ref` é opcional e só o **executor** o escreve, nas entradas de `dependencia_saltada`: é o `$ref` da dependência que deixou o campo vazio, e sem ele o relatório dizia que um campo ficou vazio sem dizer por causa de quem. O `required` é opcional, só o **executor** o escreve e só quando é `true`: diz que a dependência saltada era **obrigatória**, que é o que separa um pacote incompleto de um pacote apenas por preencher. O `source` é opcional e só o **relatório do job** o escreve, com o valor `package`: marca as entradas que vieram do manifesto — o pacote já as trazia — e distingue-as das que a aplicação produziu. O `sourceLabel` é opcional e é o **rótulo** da entidade na origem quando se conhece — **nunca o id**; falta quando o alvo não se conhece. O `kind` é o tipo da referência, mais o valor `rows` para o caso das células de linhas — que não é um tipo de referência. A `form` aqui é a **declarada**, logo pode ser `uuidOrName`, ao contrário da de uma dependência. O `unresolved[]` do **relatório do job** tem esta forma e nenhuma outra, venham as entradas do pacote, da reescrita das dependências saltadas ou da fase das linhas: duas gramáticas no mesmo campo obrigavam quem o lê a saber de qual das duas é cada linha. As do pacote entram na criação do job, marcadas com `source: package`: sem elas, o que o manifesto já trazia por resolver via-se na pré-visualização e sumia do relatório final. As da fase das linhas levam o `uid` da entrada de linhas (ou a chave do step que as trouxe), `kind: rows`, `form: uuid`, o `path` da coluna (`rows[].data.`) ou `rows[]` quando a situação é da tabela inteira, e o `count` das linhas que a entrada cobre. ### `reason` | Valor | O que significa | |---|---| | `inexistente` | O que a referência aponta já não existe na origem. | | `fora_da_selecao` | O alvo existe na origem mas ficou fora da seleção, e a chave não tem declaração que a transforme em dependência (os pais de um item e os dois defaults de navegação). | | `nao_exportavel` | O alvo existe mas não é entidade que um template possa levar: um ficheiro, uma caixa de correio, uma **pessoa** por id, ou um perfil de timer guardado por id. Um canal não entra aqui: viaja como dependência a mapear. | | `envelope_indeterminado` | Um token de coluna (um `{{record.x}}` num passo) cuja tabela não se determina estaticamente. | | `ref_adiante` | O alvo viaja, mas o step que o declara corre **depois** do step que o usa: um `$ref` ali era um erro de plano, não uma tradução. Só sobra para os tipos que não têm step de atualização no fim do plano. Numa tabela, numa coluna ou numa vista a chave viaja no `update_feature`/`update_column`/`update_view`. | | `sem_ref_cunhado` | O alvo foi classificado mas não ficou com referência no pacote. | | `tabela_alvo_sem_linhas` | A célula liga a uma linha de uma tabela que viaja, mas cujas **linhas** não foram escolhidas. | | `dependencia_saltada` | Quem importa resolveu a dependência como `skip`: o campo ficou vazio de propósito. Nasce na **aplicação** e não no exportador, e é a única que traz `ref`. | | `row_ref_dropped` | A célula ligava a uma linha que não entrou no destino (a tabela dela ficou em `none`, o lote que a trazia falhou, ou a tabela foi resolvida como `map` e a coluna de valor do destino não conhece aquele valor): a célula é **esvaziada**, porque o que lá estava era o valor da linha na organização de origem. Nasce na aplicação. Uma ligação à **própria tabela** não conta aqui enquanto a tabela não fechar: essa fica para a segunda passagem, e só sai nomeada se nem aí tiver alvo. | | `feature_ref_unresolved` | Ninguém ligou o `$ref` da tabela: as linhas dessa unidade não entraram. Nasce na aplicação. | | `payload_cycle` | Duas entradas de linhas apontam-se uma à outra: entram pela ordem de entrada e a célula que não resolver fica vazia, com a entrada `row_ref_dropped` dela. Nasce na aplicação. | ### `action` | Valor | O que significa | |---|---| | `chave esvaziada` | A chave ficou com `""`. É a omissão, e é o que acontece a tudo o que se reescreve — ou seja, ao que a declaração identifica por `uuid`. | | `valor mantido` | O valor ficou intacto. É o caso de um **nome** (e de um token, que é um nome dentro de texto livre): reescrevê-lo partia o que continua válido no destino. | | `chave omitida` | A chave nem saiu no step. É o caso dos dois defaults de navegação, `defaultRailId` e `defaultModuleId`. | ## `redacted[]` — o que saiu redigido Uma entrada por campo declarado `secret` cujo valor foi limpo, com `uid`, `path` e `reason`. A `reason` é texto livre, para ler: o que importa é que o valor **não está no pacote**. Um campo `secret` pode transportar um segredo da organização de origem, logo nunca sai — mesmo que isso deixe o pacote incompleto. ## `plan` — os steps | Chave | O que diz | |---|---| | `planVersion` | `"1"`. | | `id` | A identidade do plano. | | `summary` | A frase do ecrã de revisão. Conta **itens** e não steps: um utilizador conta tabelas, não `create_column`. As linhas contam-se por tabela ("linhas de 2 tabelas"). | | `target.workspaceId` | **Sempre** `$workspace`. Um pacote aplica-se no workspace de destino, e o id do de origem não entra no pacote. | | `metadata.source` | `export`. | | `externalRefs` | Os refs que o plano **usa e não declara**: o da entidade-raiz de cada dependência **e** os das colunas dela. Não é igual ao conjunto das dependências, de propósito. | | `steps[]` | Os passos, pela ordem de aplicação. | Cada step tem um `uid` próprio, e os que criam uma entidade referível têm também `ref` — o `$ref` que os steps seguintes podem usar. Os `update_module`, `update_workspace`, `update_feature`, `update_column` e `update_view` não declaram ref nenhum: não criam nada. ```json { "uid": "u_0002", "ref": "c_viaturas_matricula", "tool": "create_column", "args": { "featureId": "$f_viaturas", "name": "matricula", "label": "Matrícula", "type": "text", "defaultComponent": "textfield", "order": 1 } } ``` ### A ordem, e porquê Os steps saem por ordem de **dependência** e não de conveniência: 1. `create_feature` 2. `create_column` — as colunas referem features 3. `create_view` — as vistas referem features e colunas 4. `create_workflow_v2` — as automações referem tudo o que é dados 5. `create_module` 6. `create_rail` — os rails referem módulos e vistas 7. `update_module` 8. `update_workspace` 9. `update_feature` — a config da tabela, agora que as colunas e as automações existem 10. `update_column` — a config da coluna, pela mesma razão 11. `update_view` — a config da vista, pela mesma razão Os cinco `update_*` ficam no fim porque as chaves que levam apontam para coisas criadas **depois** dos pais: a ordem dos rails e o rail por omissão de um módulo, a ordem dos módulos e o módulo por omissão do workspace, a coluna que uma tabela usa para notificar, a automação que o botão de uma coluna dispara, a automação para onde uma vista de documentos encaminha os carregamentos. Os três últimos só existem quando há chave adiantada a levar, e a `config` deles **substitui a inteira**, nunca funde: quem exporta tem a config completa em mão, e uma fusão profunda no destino era uma segunda semântica para o mesmo campo. A do `update_view` viaja no mesmo envelope de um elemento que o `create_view` escreve. ```json { "uid": "u_0031", "tool": "update_column", "args": { "columnId": "$c_pedido_criar_ordem", "config": { "buttonLabel": "Criar ordem", "workflowV2Id": "$w_criar_ordem" } } } ``` ```json { "uid": "u_0032", "tool": "update_view", "args": { "viewId": "$v_compras_documentos", "config": [{ "workflowV2Id": "$w_ocr_compras" }] } } ``` Dentro do balde dos `create_column` a ordem é **topológica**, não a da origem: uma relação entre duas tabelas (a coluna de A a apontar uma coluna de B) é a referência mais comum do produto, e pela ordem de origem metade delas apontava para a frente e saía esvaziada. Um ciclo genuíno — as mesmas duas colunas a apontarem uma para a outra — não tem ordem que sirva as duas pontas: aí uma das pontas viaja vazia no `create_column` e completa no `update_column` do fim do plano. O que **continua** `ref_adiante` é o que não tem step de atualização que o leve: qualquer referência adiantada de um item que não seja tabela, coluna ou vista. **As linhas não são steps.** Não há `insert_rows` num plano exportado: as linhas viajam no payload e aplicam-se numa segunda fase da importação. ### As ferramentas que um plano pode nomear `create_workspace`, `create_module`, `create_rail`, `create_feature`, `create_column`, `create_view`, `create_workflow_v2`, `insert_row`, `insert_rows`, `update_row`, `bulk_update_rows`, `update_module`, `update_workspace`, `update_feature`, `update_column`, `update_view`. Um nome fora desta lista é recusado como ferramenta desconhecida. O `create_workflow_v2` é a única que está documentada e que o cliente **ainda não executa**. Os args são: ```json { "uid": "u_0007", "ref": "w_ocr_compras", "tool": "create_workflow_v2", "args": { "workspaceId": "$workspace", "name": "ocr_compras", "label": "OCR de compras", "triggerConfig": { "type": "record.event", "config": { "featureId": "$f_viaturas" } }, "graphConfig": { "steps": [] }, "isDraft": true, "published": true } } ``` O gatilho vai à parte do grafo porque o `featureId` de um gatilho `record.event` não vive no grafo. O `isDraft` é sempre `true`: a automação nasce como rascunho, que nunca dispara. O `published` é opcional e só vai quando a automação de origem tinha uma versão ativa — a promoção do rascunho fica para **depois das linhas** (ver «As três fases do executor»), e a automação importada dispara como a original. Sem ele, fica rascunho à espera de quem a publique. **`isActive` nunca vai nos args**: ativar é promover o rascunho e não escrever uma coluna. ### A auto-verificação Antes de entregar o pacote, o exportador mede no plano montado as mesmas três regras que o validador aplica: - nenhum `$ref` é usado antes de alguém o declarar — os builtins (`$workspace`) e os `externalRefs` contam como declarados desde o primeiro step; - nenhum `$ref` é declarado duas vezes; - nenhum `$ref` usado fica sem declaração nem entrada em `externalRefs`. Um ref conta como "usado" quando uma string é, **ela inteira**, uma referência — e as chaves de mapa contam, porque há chaves que são refs. Medir com outra régua (um `contains` de `$`, por exemplo) aprovava planos que o validador recusa. ## As linhas: `TemplatePayload` Uma linha da tabela `TemplatePayload` por cada item de `kind: rows`, com `template_id`, `kind` (hoje só `rows`), `item_uid`, `feature_ref`, `row_count` e `rows` — um **objeto** jsonb, não um array. Há `UNIQUE (template_id, item_uid)`: reexportar o mesmo template faz upsert, não duplica. A tabela não tem `organization_id` (o inquilino é o do `Template` pai) e **não entra em nenhuma sync rule**. O conteúdo da coluna `rows`: ```json { "featureRef": "f_viaturas", "itemUid": "u_0009", "count": 2, "keyColumn": "matricula", "keyUnique": true, "columns": ["matricula", "fornecedor"], "rows": [ { "uid": "u_r001", "data": { "matricula": "AA-00-AA", "fornecedor": "cccccccc-0000-4000-8000-000000000404" }, "refs": { "fornecedor": { "rowUid": "u_r101", "featureRef": "f_fornecedores", "valueColumn": "id" } } }, { "uid": "u_r002", "data": { "matricula": "BB-11-BB", "fornecedor": "ACME, Lda" } } ] } ``` As regras que a forma carrega: - o `data` é indexado por **nome de coluna**, como a linha de origem, e é **sempre dado**: nenhum token `$` entra lá. Um valor que já comece por `$` na origem fica como está — é o que impede `"preco": "$100"` de ser lido como uma referência; - o `data` guarda **sempre** o valor de origem, inclusive quando há `refs`: é o recurso de quem importa se a tabela ligada for mapeada ou saltada; - a **identidade da linha não é dado**: a chave de `data` cujo valor é o `id` da linha de origem — a coluna `id` automática — sai de `data`, sai de `columns` e nunca é `keyColumn`. Quem identifica a linha dentro do pacote é o `uid`, e os uuids da organização de origem não viajam; - o sidecar **`refs`** é opcional e existe por célula, não por linha. Só aparece quando a coluna é de ligação (`linked_select` ou `auto_match`), o valor casa com uma linha da tabela ligada, e as **linhas** dessa tabela também viajam. Cada entrada tem `rowUid` (o `uid` da linha alvo dentro do pacote), `featureRef` (o `$ref` da tabela dela) e `valueColumn` (o **nome** da coluna de valor no alvo); - a célula de uma ligação **não guarda a chave primária** da linha alvo: guarda o valor da coluna que a `config.linkedValueColumn` nomeia — a coluna `id` da tabela alvo, no caso normal, ou uma coluna de negócio como o `nipc`. É por isso que a procura é pelo valor dessa coluna, com a chave primária como recurso (a célula de uma linha criada pela API leva o uuid formatado que a base cunha, e não a chave primária da linha), e é por isso que o destino escreve na célula o valor de `valueColumn` da linha alvo **dele**. Um sidecar sem `valueColumn` é de um pacote anterior a esta regra e o destino escreve-lhe o id da linha, como antes; - uma tabela que receba linhas e tenha coluna de identidade (`default_component: id`) recebe a identidade do **destino**: a célula que venha vazia é cunhada à entrada da linha — um uuid ou o número seguinte da sequência, conforme o `idType` da coluna — e é esse valor, o que ficou escrito, que as células de ligação de outras tabelas guardam; - uma coluna de ligação com `isMultiSelect` — uma coluna `fornecedores`, ao lado da `fornecedor` do exemplo — guarda uma **lista** de ids, e a entrada da célula passa a ser `{ "rows": [ ... ] }` com o mesmo par `rowUid`/`featureRef` por elemento, pela ordem da célula. O que manda é a forma do valor e não a config, e os elementos que nenhuma linha alvo guarda — etiquetas, valores soltos — não entram e ficam só em `data`: ```json { "uid": "u_r003", "data": { "matricula": "CC-22-CC", "fornecedores": ["cccccccc-0000-4000-8000-000000000404", "ACME, Lda"] }, "refs": { "fornecedores": { "rows": [{ "rowUid": "u_r101", "featureRef": "f_fornecedores", "valueColumn": "id" }] } } } ``` - se a tabela ligada viaja mas as linhas dela não, não há `refs`: o valor fica em `data` e a situação conta-se em `unresolved[]` com a razão `tabela_alvo_sem_linhas` e a ação `valor mantido` — **uma entrada por coluna**, e não por linha nem por elemento: mil linhas ligadas à mesma tabela são uma situação, não mil. A entrada leva o `count` das linhas que cobre. Quem aplica não escreve esse valor às cegas: se a tabela ligada for uma dependência resolvida como `map`, o valor procura-se na coluna de identidade da tabela do destino — existe, fica como veio; não existe, a célula é **esvaziada** e a situação conta-se em `row_ref_dropped`. Só as ligações pela coluna de identidade: o valor de uma coluna de negócio (um nome, um `nipc`) continua a valer no destino, e procurá-lo na identidade esvaziava-o; - se a tabela ligada não tem `$ref` cunhado no pacote, também não há `refs`: um `featureRef` nulo era uma ligação que o destino não sabia seguir. O valor fica em `data` com a ação `valor mantido`, e a razão diz qual dos dois casos é — `inexistente` se a tabela já não existe na origem, `sem_ref_cunhado` se existe e ninguém lhe cunhou referência. Também aqui a entrada é **uma por coluna**; - `columns` são os nomes das colunas **declaradas** que alguma linha traz, pela ordem da tabela — é o que deixa o destino pré-visualizar sem adivinhar; - `keyColumn` é a coluna de texto por que o destino pode casar as linhas, e `keyUnique` é o resultado da verificação na origem. As candidatas ordenam-se pelo que a tabela **declara** sobre elas: primeiro a coluna **obrigatória**, depois a de texto livre marcada **única** na config, depois a que tem um nome de chave conhecido (`code`, `codigo`, `ref`, `referencia`, `sku`, `nif`, `email`, `slug`, sem distinguir maiúsculas), e só então qualquer coluna de texto, pela ordem da tabela. Em todas manda a verificação: os valores têm de ser **todos preenchidos e distintos** nas linhas exportadas, e uma candidata preferida que não cumpra cede à seguinte. Uma coluna de **ligação** nunca é candidata, em preferência nenhuma: a célula guarda o id ou o valor de outra tabela, que não identifica esta linha. Nula quando nenhuma serve: oferecer "acrescentar as que faltam" sem ter verificado a chave era duplicar linhas do cliente; - o limite por entrada é **5000 linhas ou 4 MiB de JSON**. Não é o exportador que recusa: quem recusa é o ecrã de seleção, que é quem pode oferecer escolher menos linhas. ## Promoção a `system` Um template só se promove a `system` — a visibilidade que desce para todos os clientes — quando passa as cinco regras, todas medidas de uma vez para quem promove saber tudo o que falta: 1. `templateVersion` é `"1"` ou `"2"`, e declarado: um manifesto sem a chave não se promove, mesmo que a leitura lhe assuma `"1"`; 2. o JSON inteiro não contém `"organization_id"` nem `"workspace_id"`; 3. todo o item de `kind: rows` tem a sua entrada em `TemplatePayload`; 4. o `count` do item é igual ao `row_count` do payload; 5. nenhum payload sobra sem item `rows` que o declare. ## O que nunca viaja - **Identificadores da origem.** Toda a referência declarada vira `$ref` ou fica vazia e nomeada em `unresolved[]`. Um uuid de outra organização dentro de um pacote é uma fuga, e um uuid morto numa config é pior: aplica-se sem se queixar. A única exceção é o valor de uma célula de ligação — ou a lista deles, num multi-select — que fica em `data`: ali é **dado** e não referência, e o sidecar `refs` é o que o torna resolúvel. Pela mesma régua, o valor da coluna de identidade de uma linha viaja quando é diferente da chave primária dela: é o valor que as células de ligação guardam, e não um ponteiro para a origem. - **Identificadores de inquilino.** Nem `organization_id` nem `workspace_id`, em circunstância nenhuma: a organização de destino deriva-se do workspace validado, do lado do servidor. O `source` do pacote leva três campos e o nome do workspace de origem é um deles — o id não. - **Segredos.** Todo o campo declarado `secret` sai limpo e nomeado em `redacted[]`. Ligações e caixas de correio viajam por nome ou entram nas dependências com `resolution: map`. - **O `id` e o `feature_id` de uma linha.** O payload copia o `data` campo a campo e nunca a linha em bloco: copiar o mapa levava os dois identificadores da organização de origem sem ninguém notar. A identidade de uma linha dentro do pacote é o `uid` que o exportador lhe cunha. - **O estado de uma automação.** `isActive` nunca vai num pacote. --- # Automações (WorkflowV2) Uma automação do OutDo é uma **definição versionada**: um gatilho e uma cadeia de passos, em duas colunas JSON. Esta página diz o que cabe nessas colunas, que rotas e ferramentas as escrevem, e em que ordem. O vocabulário está gerado do código e não se repete aqui: [Passos](/reference/passos/) e [Gatilhos](/reference/gatilhos/), com os campos de cada `config`. ## As duas colunas `trigger_config` é o que dispara. `graph_config` é o que acontece a seguir. ```json { "trigger_config": { "type": "record.event", "config": {} }, "graph_config": { "steps": [ { "id": "stp_exemplo0001", "key": "feature.write", "config": {} } ] } } ``` | Chave | Obrigatória | O que é | |---|---|---| | `trigger_config.type` | sim | A key do gatilho, tal como aparece em [Gatilhos](/reference/gatilhos/). Vazia ou desconhecida é erro (`trigger_missing`, `trigger_unknown_key`). | | `trigger_config.config` | não | A config do gatilho. Cada gatilho valida a sua (`trigger_config_invalid`). | | `graph_config.steps` | sim na prática | A cadeia, por ordem de execução. Lista vazia passa com aviso (`graph_empty`). | | `steps[].key` | sim | A key do passo, de [Passos](/reference/passos/). Desconhecida é erro (`unknown_step_key`). | | `steps[].id` | não | Identidade estável do passo, `stp_` mais 12 alfanuméricos. Omitida, a app atribui uma ao abrir; repetida é erro (`duplicate_step_id`). É a chave de `{{vars.steps..}}`. | | `steps[].config` | depende do passo | A config do passo. | | `steps[].name` | não | Alias humano do cartão. Não substitui o `id`. | Não há nós, arestas nem coordenadas. A **ordem da lista é o fluxo**, e quem ramifica guarda os ramos **dentro** da config do passo de controlo, como listas de passos com a mesma forma: `then` e `else` no `ifElse`, as rotas no `switch` e no `agent.route`. Daí o caminho pontuado dos problemas, onde `0.then.0` é o primeiro passo do ramo verdadeiro do primeiro passo da raiz. ## Ids, nomes e referências A API não resolve nomes de tabelas nem símbolos: - **Tabelas por uuid**: `featureId`, `targetFeatureId`, de `GET /v1/features`. - **Colunas por nome técnico**: `targetColumn`, `columnName`, `filters[].column`, `watchedColumns`, `orderBy.column`. É o `name` de `GET /v1/features/{id}/columns`. - **Ligações por nome**: `connectionName`, que esta rota não cruza com as ligações da organização (um nome errado só falha em execução). As referências simbólicas `$f_…` e `$c_…` são a gramática dos **pacotes de template** (ver [Formato do pacote](/reference/package-format)) e nada em `/v1/workflows-v2` as resolve. ## A gramática dos valores Os campos de expressão aceitam tokens `{{…}}`, resolvidos em execução contra o envelope que viaja entre passos: | Token | O que devolve | |---|---| | `{{vars.x}}` | Uma variável do envelope. | | `{{vars.trigger.}}` | Uma coluna da linha que disparou (gatilhos `record.event` e disparo manual sobre uma linha). | | `{{vars.steps..}}` | Uma saída anunciada por um passo anterior. | | `{{record.}}` | A coluna do primeiro registo do conjunto corrente. | | `{{records.2.}}` | A coluna do registo no índice indicado. | | `{{sys.now}}`, `{{sys.today}}` | Data e hora, ou só a data, do relógio da execução. | Um token sozinho preserva o tipo do valor; embebido em texto, interpola. Um `{{vars.x}}` que nenhum passo anterior produza é erro (`unknown_var`), tal como um id inexistente (`unknown_step_ref`) ou uma saída não anunciada (`unknown_step_output`). ## Ciclo de vida Validar, criar como rascunho, publicar, e só então alguém ativa na aplicação. **A ativação não tem rota nem ferramenta**: é sempre uma decisão de uma pessoa. | Passo | REST | MCP | |---|---|---| | Listar as automações de um workspace | `GET /v1/workflows-v2?workspace_id=…` | `list_workflows_v2` | | Ler a que está em vigor | `GET /v1/workflows-v2/{workflow_id}` | `get_workflow_v2` | | Validar sem gravar | `POST /v1/workflows-v2/validate` | `validate_workflow_v2` | | Criar como rascunho | `POST /v1/workflows-v2` | `create_workflow_v2` | | Publicar o rascunho | `POST /v1/workflows-v2/{workflow_id}/apply` | sem equivalente | | Acrescentar uma versão ativa | `POST /v1/workflows-v2/{workflow_id}/versions` | sem equivalente | | Ativar | na aplicação | na aplicação | - Cada item da listagem é **uma versão**, e o `workflow_id` agrupa-as: é por ele que se endereça a automação. `active=true` filtra as que disparam; `false` não filtra nada de útil, porque uma versão superada também é inativa. - `POST /v1/workflows-v2` nasce rascunho, e um rascunho nunca dispara. Com `is_draft: false` cria e publica de uma vez, e o resultado fica **inativo**. - `apply` preserva o estado de ativação: uma pausada continua pausada, uma nova nasce inativa. Um 409 quer dizer que o rascunho ou a base dele se mexeram: recarregar e reconciliar, nunca repetir a chamada. - `versions` exige uma versão ativa; sem ela responde 409 a dizer para publicar primeiro. O que se omite no corpo mantém o valor da versão ativa. - Scopes como no resto da [API REST](/reference/api/): `validate` chega com `read`; `create`, `versions` e `apply` precisam de `write` mais `structure`. Um `Idempotency-Key` em qualquer POST torna a repetição segura, e no MCP o `create_workflow_v2` aceita `idempotency_key`. ## O que o validador verifica `POST /v1/workflows-v2/validate` não grava nada e responde sempre 200 com `{ok, issues}`. O `ok` é a ausência de **erros**: um aviso nunca bloqueia. Cada problema traz um `code` estável, a `severity`, o `path` pontuado e um `target` que diz onde se resolve, `trigger` ou `graph`. Cobre gatilho em falta, desconhecido ou que afinal é um passo; ids repetidos; keys desconhecidas; as precondições de cada passo e de cada gatilho; o encadeamento das formas do envelope; tokens para variáveis, passos ou saídas inexistentes; ciclos reativos, quando o grafo escreve na tabela que o gatilho observa; e auto-recursão, quando se passa `workflow_id` e uma sub-automação aponta ao próprio workflow. As rotas de escrita correm o mesmo validador antes de gravar, e um erro aí é um 422 com os códigos na mensagem. ## Exemplo A: reagir a uma mudança de estado Quando o `estado` de um documento de compra passa a `Validado`, escrever uma nota na própria linha. O corpo abaixo é o de `POST /v1/workflows-v2/validate`; para criar, acrescenta-se `name` e envia-se o mesmo para `POST /v1/workflows-v2`. ```json { "workspace_id": "a5a50556-ef07-449d-a556-077a2a310461", "trigger_config": { "type": "record.event", "config": { "modes": ["updated"], "featureId": "d174bd26-c7f0-46ed-a2e3-7bad133b28ce", "watchedColumns": ["estado"] } }, "graph_config": { "steps": [ { "id": "stp_ifestado0001", "key": "ifElse", "config": { "condition": { "subject": "var", "var": "{{vars.trigger.estado}}", "op": "eq", "value": "Validado" }, "then": [ { "id": "stp_escrever0001", "key": "feature.write", "config": { "mode": "updateTrigger", "targetFeatureId": "d174bd26-c7f0-46ed-a2e3-7bad133b28ce", "bindings": [ { "targetColumn": "notas", "value": "Validado em {{sys.today}}", "type": "text" } ] } } ], "else": [] } } ] } } ``` O que aqui é regra: - `watchedColumns` são **nomes** de coluna, e o gatilho só dispara quando uma delas muda de facto. - `mode: "updateTrigger"` escreve na linha que disparou, por isso o `targetFeatureId` tem de ser a mesma tabela do gatilho (`trigger_row_write_target_mismatch`). - Escrever numa coluna observada fecha um ciclo e é recusado (`reactive_cycle_column_overlap`): observa-se `estado`, escreve-se `notas`. - O ramo `else` pode ficar vazio; com os dois vazios o passo publica e não faz nada, e o validador avisa (`branches_all_empty`). ## Exemplo B: um resumo diário por email Todos os dias às 08:00 de Lisboa, ler as faturas por rever e enviar um email. ```json { "workspace_id": "a5a50556-ef07-449d-a556-077a2a310461", "trigger_config": { "type": "cron", "config": { "mode": "daily", "atTime": "08:00", "timezone": "Europe/Lisbon" } }, "graph_config": { "steps": [ { "id": "stp_lerfaturas01", "key": "feature.read", "config": { "featureId": "d174bd26-c7f0-46ed-a2e3-7bad133b28ce", "filterGroup": { "combinator": "and", "rules": [ { "id": "r1", "columnName": "estado", "operator": "equals", "value": "Aguarda revisão" } ] }, "limit": 100, "orderBy": { "column": "vencimento", "desc": false }, "mergeMode": "replace" } }, { "id": "stp_enviaremail1", "key": "email.send", "config": { "to": "compras@exemplo.pt", "subject": "Faturas por rever em {{sys.today}}", "body": "

A mais antiga é a {{record.numero}}, de {{record.fornecedor_nome}}, no valor de {{record.total}}.

", "attachFiles": false } } ] } } ``` O que aqui é regra: - O `cron` arranca com o envelope vazio, por isso alguma coisa tem de trazer registos antes do email. Nenhum passo está preso à primeira posição: com `mergeMode: "append"`, o `feature.read` junta uma segunda tabela a meio. - Os operadores do `filterGroup` são os do editor de filtros da aplicação (`equals`, `notEquals`, `contains`, `greaterThan`, `greaterOrEqual`, `lessThan`, `lessOrEqual`, `isEmpty`, `isNotEmpty`, `between`), e só as regras de topo com `and` chegam à leitura. - A cadeia termina num passo que entrega; sem isso o validador avisa que a automação processa e não faz nada (`chain_has_no_delivery`). Sem `connectionName`, o email sai pelo transporte da organização. --- # Componentes 29 keys declaradas. | Key | Nome | Descrição | |---|---|---| | [`auto_match`](./auto_match.md) | Correspondência automática | Liga a uma linha de outra tabela por semelhança de texto. | | [`barcode`](./barcode.md) | Código de barras | Código de barras ou QR, lido pela câmara ou escrito à mão; o valor guardado é o texto do código. | | [`checkbox`](./checkbox.md) | Caixa de verificação | Valor de dois estados (ligado/desligado). | | [`checklist`](./checklist.md) | Lista de tarefas | Lista de tarefas com progresso, grupos, prazos e responsáveis. | | [`counter`](./counter.md) | Contador | Compara as linhas de outra tabela que partilham um valor com esta, em fração, percentagem ou barra. | | [`createdAt`](./createdat.md) | Criado em | Data de criação da linha. | | [`createdBy`](./createdby.md) | Criado por | Quem criou a linha. | | [`date`](./date.md) | Data | Data, hora ou ambas, com seletor visual e limites. | | [`description`](./description.md) | Descrição | Editor de texto rico, com secções e barra de formatação opcionais. | | [`document`](./document.md) | Documento | Documento com extração por OCR/IA e mapeamento dos campos extraídos para colunas do cabeçalho e das linhas. | | [`execution`](./execution.md) | Botão de execução | Botão que corre uma automação ou abre um formulário. | | [`external_user`](./external_user.md) | Contas externas | Marca as contas externas da organização que veem este registo no portal. | | [`file`](./file.md) | Ficheiro | Carregamento de ficheiros para o bucket de anexos, com pré-visualização opcional. | | [`formula`](./formula.md) | Fórmula | Calcula um valor a partir de colunas desta tabela ou de outra. | | [`id`](./id.md) | Identificador | Identificador gerado pela app: uuid, ou uma sequência com prefixo, padrão e reinício por período. | | [`image`](./image.md) | Imagem | Imagem guardada como o `file` (o VALOR é o mesmo JSON de FileMetadata); esta config só escolhe a APRESENTAÇÃO por superfície. | | [`linked_select`](./linked_select.md) | Ligação a tabela | Escolhe uma ou mais linhas de outra tabela. | | [`linked_view`](./linked_view.md) | Vista de tabela ligada | Encaixa uma vista de outra tabela, filtrada pelo valor desta linha. | | [`lookup`](./lookup.md) | Valor de tabela ligada | Mostra um valor de uma linha ligada, sem o copiar. | | [`numericfield`](./numericfield.md) | Número | Campo numérico com casas decimais, sufixo e barra de progresso opcional. | | [`rating`](./rating.md) | Classificação | Classificação por ícones (estrelas, corações ou círculos), com meios passos opcionais. | | [`rollup`](./rollup.md) | Agregação de tabela ligada | Soma, conta ou calcula sobre as linhas ligadas a esta. | | [`select`](./select.md) | Lista | Menu de opções predefinidas, de escolha única ou múltipla. | | [`slider`](./slider.md) | Deslizador | Deslizador numérico num intervalo fechado, com passo opcional. | | [`subuser`](./subuser.md) | Operador | Atribui um operador (identidade de kiosk, autenticada por PIN) ao registo. | | [`tags`](./tags.md) | Etiquetas | Etiquetas livres; o valor guardado é uma lista de textos. | | [`textfield`](./textfield.md) | Texto | Campo de texto de uma linha, com validações e máscaras. | | [`timer`](./timer.md) | Temporizador | Cronómetro da linha, com perfil de campos, arredondamento e linha derivada ao parar. | | [`user`](./user.md) | Utilizador | Atribui um ou mais membros do workspace ao registo. | --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # auto_match **Correspondência automática** Liga a uma linha de outra tabela por semelhança de texto. - **Kind**: `component` - **Key**: `auto_match` - **Categoria**: `relação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `linkedFeatureId` | `uuid` | não | - | Tabela onde se procura a correspondência. | feature (uuid) | | `linkedValueColumn` | `string` | não | - | Coluna da tabela ligada cujo valor se guarda (uuid ou nome). | coluna de `linkedFeatureId` (uuid ou nome) | | `linkedLabelColumn` | `string` | não | - | Coluna da tabela ligada que se mostra (uuid ou nome). | coluna de `linkedFeatureId` (uuid ou nome) | | `linkedSearchColumn` | `string` | não | - | Coluna da tabela ligada onde se procura (uuid ou nome). | coluna de `linkedFeatureId` (uuid ou nome) | | `matchThreshold` | `number` | não | `0.7` | Semelhança mínima (0 a 1) para sugerir a linha. | - | | `autoConfirmThreshold` | `number` | não | `0.95` | Semelhança a partir da qual a ligação se confirma só. | - | | `showAddButton` | `boolean` | não | `false` | Deixa criar uma linha nova na tabela ligada. | - | | `showEditButton` | `boolean` | não | `false` | Deixa editar a linha correspondida na tabela ligada. | - | | `placeholder` | `string` | não | - | Texto mostrado enquanto nada está correspondido. | - | | `compact` | `boolean` | não | `false` | Desenha o campo na forma compacta (uma só linha). | - | | `normalizeAccents` | `boolean` | não | `false` | Ignora acentos e maiúsculas ao comparar ("José" = "jose"). | - | | `topSuggestions` | `integer` | não | - | Quantas sugestões oferecer; vazio ou 1 mostra só a melhor. | - | | `createWhenNoMatch` | `boolean` | não | `false` | Sem correspondência, oferece criar a linha com o texto escrito. | - | | `compositeColumns` | `list` de `map` | não | - | Colunas que, com os seus pesos, formam a pontuação da comparação. | - | | `creationMappings` | `list` de `map` | não | - | Que colunas desta tabela semeiam a linha nova criada na tabela ligada. | - | ### `compositeColumns[]` Cada elemento de `compositeColumns` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `string` | não | - | Coluna da tabela ligada a comparar (uuid ou nome). | coluna de `linkedFeatureId` (uuid ou nome) | | `weight` | `number` | não | - | Peso da coluna (0 a 1); 0 ou vazio exclui-a. | - | ### `creationMappings[]` Cada elemento de `creationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | - | Coluna da tabela ligada a preencher. | coluna de `linkedFeatureId` (uuid ou nome) | | `sourceField` | `string` | não | - | Coluna desta tabela de onde sai o valor. | coluna (uuid ou nome) | ## Exemplo JSON ```json { "matchThreshold": 0.7, "autoConfirmThreshold": 0.95, "showAddButton": false, "showEditButton": false, "compact": false, "normalizeAccents": false, "createWhenNoMatch": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # barcode **Código de barras** Código de barras ou QR, lido pela câmara ou escrito à mão; o valor guardado é o texto do código. - **Kind**: `component` - **Key**: `barcode` - **Categoria**: `texto` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `codeFormat` | `enumeration` | não | `"qr"` | Simbologia usada para desenhar o código. | - | | `allowScan` | `boolean` | não | `true` | Oferece a leitura pela câmara (só em móvel). | - | | `allowManual` | `boolean` | não | `true` | Permite escrever o valor à mão. Um dos dois (ler ou escrever) tem de estar ligado. | - | | `renderInCell` | `boolean` | não | `false` | Desenha o código na célula em vez de mostrar o texto, nas vistas de leitura. | - | | `isUnique` | `boolean` | não | `false` | Recusa guardar um valor já usado noutra linha. | - | | `uniqueErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor está repetido. | - | | `uniqueWith` | `list` de `string` | não | `[]` | Outras colunas que entram na mesma chave: o repetido passa a ser o conjunto, e não esta coluna sozinha. Vazio = só esta coluna. | - | | `caseInsensitive` | `boolean` | não | `false` | Ignora maiúsculas e minúsculas na verificação de unicidade. | - | | `trimWhitespace` | `boolean` | não | `true` | Corta os espaços do início e do fim antes de guardar. | - | ## Exemplo JSON ```json { "codeFormat": "qr", "allowScan": true, "allowManual": true, "renderInCell": false, "isUnique": false, "uniqueWith": [], "caseInsensitive": false, "trimWhitespace": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # checkbox **Caixa de verificação** Valor de dois estados (ligado/desligado). - **Kind**: `component` - **Key**: `checkbox` - **Categoria**: `escolha` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `label` | `string` | não | - | Rótulo ao lado da caixa; vazio usa o nome da coluna. | - | | `defaultValue` | `boolean` | não | - | Estado inicial de uma linha nova. | - | | `displayStyle` | `enumeration` | não | - | Forma de apresentação; vazio ou desconhecido vale "checkbox". | - | | `trueLabel` | `string` | não | - | Texto mostrado em vez do ícone quando está ligado. | - | | `falseLabel` | `string` | não | - | Texto mostrado em vez do ícone quando está desligado. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # checklist **Lista de tarefas** Lista de tarefas com progresso, grupos, prazos e responsáveis. - **Kind**: `component` - **Key**: `checklist` - **Categoria**: `lista` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `defaultItems` | `list` de `map` | não | `[]` | Tarefas que uma linha nova já traz. | - | | `showProgress` | `boolean` | não | `true` | Mostra o progresso da lista. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar tarefas. | - | | `allowEdit` | `boolean` | não | `true` | Permite editar tarefas; é também a omissão dos outros três interruptores nas configs antigas. | - | | `allowRemove` | `boolean` | não | `true` | Permite apagar tarefas. | - | | `allowCheck` | `boolean` | não | `true` | Permite marcar tarefas como feitas. | - | | `valueType` | `enumeration` | não | `"count"` | Forma do valor da célula: "3/10" ou "30%". | - | | `visualMode` | `enumeration` | não | `"valueOnly"` | Só o valor, ou uma barra de progresso com o valor por cima. | - | | `weightedProgress` | `boolean` | não | `false` | Pesa cada tarefa pelo seu weight em vez de contar uma por tarefa. | - | | `showAssignees` | `boolean` | não | `true` | Mostra o avatar do responsável nas linhas. | - | | `showDueDates` | `boolean` | não | `true` | Liga os prazos (chip nas linhas, data ao acrescentar). | - | ### `defaultItems[]` Cada elemento de `defaultItems` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | sim | - | Identificador da tarefa dentro da lista. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `description` | `string` | sim | - | Texto da tarefa. | - | | `isChecked` | `boolean` | não | `false` | Tarefa já feita. | - | | `dueDate` | `string` | não | - | Prazo da tarefa em ISO-8601; escrito mesmo quando vazio, para o JSON legado dar a volta byte a byte. | - | | `type` | `enumeration` | não | - | Presente só nos GRUPOS; ausente = tarefa. | - | | `assigneeId` | `uuid` | não | - | Utilizador responsável pela tarefa; é um dado, não uma referência de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `priority` | `enumeration` | não | - | Prioridade da tarefa; vazio = sem prioridade. | - | | `weight` | `integer` | não | - | Peso da tarefa no progresso pesado; vazio conta como 1 e um valor negativo conta como 0. | - | | `requiredToComplete` | `boolean` | não | `false` | A lista não chega a 100% enquanto esta tarefa estiver pendente. | - | ## Exemplo JSON ```json { "defaultItems": [], "showProgress": true, "allowAdd": true, "allowEdit": true, "allowRemove": true, "allowCheck": true, "valueType": "count", "visualMode": "valueOnly", "weightedProgress": false, "showAssignees": true, "showDueDates": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # counter **Contador** Compara as linhas de outra tabela que partilham um valor com esta, em fração, percentagem ou barra. - **Kind**: `component` - **Key**: `counter` - **Categoria**: `agregação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `sourceFeatureId` | `uuid` | não | - | Tabela cujas linhas se contam. | feature (uuid) | | `groupByColumnId` | `uuid` | não | - | Coluna da tabela de origem cujo valor define o grupo de linhas comparadas. | coluna de `sourceFeatureId` (uuid) | | `currentFeatureColumnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor do agrupamento. | coluna (uuid) | | `numeratorConditions` | `list` de `map` | não | - | Condições que uma linha cumpre para entrar no numerador. | - | | `denominatorConditions` | `list` de `map` | não | - | Condições que estreitam o denominador; vazio conta o grupo todo. | - | | `valueType` | `enumeration` | não | `"fraction"` | Mostra "3/10" ou "30%". | - | | `visualMode` | `enumeration` | não | `"valueOnly"` | Só o valor, ou uma barra de progresso com o valor. | - | | `aggregation` | `enumeration` | não | - | Como se deriva o numerador sobre as linhas que passam; vazio vale "count". | - | | `aggregationColumnId` | `uuid` | não | - | Coluna numérica da tabela de origem agregada por sum/avg/min/max. | coluna de `sourceFeatureId` (uuid) | | `conditionsLogic` | `string` | não | - | Como se combinam as condições das DUAS listas; vazio vale "and". | - | | `periodFilter` | `enumeration` | não | - | Janela de createdAt aplicada às linhas de origem antes de comparar; vazio vale "none". | - | | `enableDrilldown` | `boolean` | não | `true` | Clicar no contador abre os registos comparados. | - | ### `numeratorConditions[]` Cada elemento de `numeratorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | sim | - | Coluna da tabela de origem a filtrar. | coluna de `sourceFeatureId` (uuid) | | `operator` | `string` | sim | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `denominatorConditions[]` Cada elemento de `denominatorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | sim | - | Coluna da tabela de origem a filtrar. | coluna de `sourceFeatureId` (uuid) | | `operator` | `string` | sim | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "valueType": "fraction", "visualMode": "valueOnly", "enableDrilldown": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # createdAt **Criado em** Data de criação da linha. Só de leitura, sem configuração: o SystemFieldComponentConfigModel não escreve chave nenhuma. - **Kind**: `component` - **Key**: `createdAt` - **Categoria**: `sistema` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos _Sem campos declarados._ ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # createdBy **Criado por** Quem criou a linha. Só de leitura, sem configuração. - **Kind**: `component` - **Key**: `createdBy` - **Categoria**: `sistema` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos _Sem campos declarados._ ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # date **Data** Data, hora ou ambas, com seletor visual e limites. - **Kind**: `component` - **Key**: `date` - **Categoria**: `data` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `format` | `string` | não | - | Padrão de apresentação; vazio usa o padrão do dateType. | - | | `minDate` | `string` | não | - | Data mínima aceite, em ISO 8601. | - | | `maxDate` | `string` | não | - | Data máxima aceite, em ISO 8601. | - | | `dateType` | `enumeration` | não | `"date"` | O que se pede: data, hora, ou data e hora. | - | | `defaultValue` | `enumeration` | não | `"none"` | Como se calcula o valor das linhas novas. | - | | `customDefaultDate` | `string` | não | - | A data fixa usada quando defaultValue é "custom", em ISO 8601. | - | | `allowPastDates` | `boolean` | não | `true` | Aceita datas anteriores a hoje. | - | | `defaultRelativeDays` | `integer` | não | - | Dias a somar a hoje quando defaultValue é "relative". | - | | `businessDaysOnly` | `boolean` | não | `false` | Só deixa escolher dias úteis. | - | | `quickPresets` | `boolean` | não | `true` | Mostra os atalhos (hoje, amanhã, …) no seletor. | - | | `isUnique` | `boolean` | não | `false` | Recusa guardar um valor já usado noutra linha. | - | | `uniqueErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor está repetido. | - | | `uniqueWith` | `list` de `string` | não | `[]` | Outras colunas que entram na mesma chave: o repetido passa a ser o conjunto, e não esta coluna sozinha. Vazio = só esta coluna. | - | | `reminders` | `list` de `map` | não | `[]` | Lembretes disparados a partir da data desta coluna; vazio é nenhum. | - | ### `reminders[]` Cada elemento de `reminders` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `offsetDays` | `integer` | não | `0` | Dias a somar à data da célula; negativo é antes dela. | - | | `time` | `string` | não | `"09:00"` | Hora de parede HH:mm, no fuso do workspace da tabela. | - | | `to` | `map` | não | - | Quem é avisado: uma coluna de pessoas, ou pessoas fixas. | - | | `via` | `list` de `enumeration` | não | `["inApp"]` | Por onde chega o lembrete; o sino (inApp) está sempre presente. | - | | `condition` | `map` | não | - | Condição avaliada na linha antes de avisar; vazia avisa sempre. | - | | `repeat` | `enumeration` | não | `"none"` | Se o lembrete se repete de dia a dia enquanto a condição se mantiver. | - | ### `reminders[].to` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `userColumn` | `string` | não | - | O nome da coluna de pessoas de onde saem os destinatários. | coluna (nome) | | `users` | `list` de `uuid` | não | - | Ids de pessoas fixas, da organização de origem. | - | ### `reminders[].condition` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `reminders[].condition.rules[]` Cada elemento de `reminders[].condition.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `reminders[].condition.groups[]` Cada elemento de `reminders[].condition.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `reminders[].condition.groups[].rules[]` Cada elemento de `reminders[].condition.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "dateType": "date", "defaultValue": "none", "allowPastDates": true, "businessDaysOnly": false, "quickPresets": true, "isUnique": false, "uniqueWith": [], "reminders": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # description **Descrição** Editor de texto rico, com secções e barra de formatação opcionais. - **Kind**: `component` - **Key**: `description` - **Categoria**: `texto` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `placeholder` | `string` | não | - | Texto de sugestão mostrado no editor vazio. | - | | `showToolbar` | `boolean` | não | `true` | Mostra a barra de formatação acima do editor. | - | | `defaultValue` | `string` | não | - | Conteúdo inicial do editor nas linhas novas. | - | | `defaultSections` | `list` de `map` | não | `[]` | Secções predefinidas oferecidas em cada linha. | - | | `allowUserSections` | `boolean` | não | `true` | Deixa o utilizador acrescentar secções próprias. | - | | `maxCharacters` | `integer` | não | - | Limite brando de caracteres do texto simples (vazio = sem limite). | - | | `contentTemplates` | `list` de `map` | não | - | Modelos de texto que o utilizador pode inserir. | - | ### `defaultSections[]` Cada elemento de `defaultSections` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `title` | `string` | sim | - | Título da secção. | - | | `required` | `boolean` | não | `false` | A secção tem de estar preenchida para a descrição contar como completa. | - | | `startCollapsed` | `boolean` | não | `false` | A secção começa fechada na primeira abertura. | - | ### `contentTemplates[]` Cada elemento de `contentTemplates` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `name` | `string` | não | - | Nome do modelo, mostrado no menu "Inserir modelo". | - | | `text` | `string` | não | - | Texto simples inserido na posição do cursor. | - | ## Exemplo JSON ```json { "showToolbar": true, "defaultSections": [], "allowUserSections": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # document **Documento** Documento com extração por OCR/IA e mapeamento dos campos extraídos para colunas do cabeçalho e das linhas. - **Kind**: `component` - **Key**: `document` - **Categoria**: `ficheiro` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `buttonLabel` | `string` | não | - | Rótulo do botão de carregar. | - | | `hintText` | `string` | não | - | Texto de ajuda do campo. | - | | `allowedExtensions` | `list` de `string` | não | `["pdf","jpg","jpeg","png","bmp","gif","webp"]` | Extensões aceites. | - | | `maxFileSizeMB` | `integer` | não | - | Tamanho máximo do documento em MB; vazio = sem limite. | - | | `enableOCR` | `boolean` | não | `true` | Extrai o texto do documento por OCR. | - | | `enableAIProcessing` | `boolean` | não | `true` | Passa o texto extraído por um modelo de IA para o estruturar. | - | | `ocrProvider` | `enumeration` | não | `"google_ml_kit"` | Motor de OCR usado. | - | | `aiProvider` | `enumeration` | não | `"openai"` | Fornecedor do modelo que estrutura a extração. | - | | `openaiApiKey` | `string` | não | - | Chave de API do fornecedor de IA: é um SEGREDO da organização e nunca sai num template. **Segredo.** O exportador substitui este valor por vazio e nomeia o caminho em `redacted[]`: nunca sai num pacote de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `aiPrompt` | `string` | não | - | Instrução de extração escrita pelo utilizador; vazio usa a do tipo de documento. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `expectedStructure` | `json` | não | - | Estrutura JSON que se espera da extração, escrita pelo utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `autoProcess` | `boolean` | não | `false` | Processa o documento logo ao carregar, sem esperar pelo botão. | - | | `showPreview` | `boolean` | não | `true` | Mostra a pré-visualização do documento. | - | | `pdfRenderDPI` | `number` | não | `150` | Resolução a que as páginas do PDF são rasterizadas antes do OCR. | - | | `processAllPages` | `boolean` | não | `true` | Processa todas as páginas; falso processa só a primeira. | - | | `maxPagesToProcess` | `integer` | não | - | Máximo de páginas processadas; vazio = sem limite. | - | | `combinePageTexts` | `boolean` | não | `true` | Junta o texto de todas as páginas numa só extração. | - | | `saveDocument` | `boolean` | não | `true` | Guarda o documento original no bucket além da extração. | - | | `autoFillFields` | `boolean` | não | `true` | Preenche as colunas mapeadas com os valores extraídos. | - | | `headerMappings` | `map` | não | `{}` | Caminho na extração → coluna DESTA tabela que recebe o valor do cabeçalho. | - | | `linesMappings` | `map` | não | `{}` | Caminho dentro de cada linha extraída → coluna da tabela das linhas que recebe o valor. | - | | `linesTargetFeatureId` | `uuid` | não | - | Tabela onde se criam as linhas do documento; vazio só preenche o cabeçalho. | feature (uuid) | | `linesNumberColumnName` | `string` | não | - | Coluna da tabela das linhas que recebe o número de ordem. | coluna de `linesTargetFeatureId` (nome) | | `headerIdColumnName` | `string` | não | - | Coluna DESTA tabela que identifica o cabeçalho nas linhas. | coluna (nome) | | `linesHeaderIdColumnName` | `string` | não | - | Coluna da tabela das linhas que recebe o id do cabeçalho. | coluna de `linesTargetFeatureId` (nome) | | `autoMatchFields` | `map` | não | `{}` | Campo da linha → onde procurar o registo que lhe corresponde. | - | | `enableAutoMatching` | `boolean` | não | `false` | Liga o auto-match nos campos das linhas. | - | | `headerAutoMatchFields` | `map` | não | `{}` | Coluna do cabeçalho (por nome) → onde procurar o registo que lhe corresponde. | chave: coluna (nome) | | `enableHeaderAutoMatching` | `boolean` | não | `false` | Liga o auto-match nos campos do cabeçalho. | - | | `headerCreationMappings` | `map` | não | `{}` | Coluna do cabeçalho (as MESMAS chaves de headerAutoMatchFields) → o que a criação do registo em falta leva. | chave: coluna (nome) | | `lineCreationMappings` | `map` | não | `{}` | Campo da linha (as MESMAS chaves de autoMatchFields) → o que a criação do registo em falta leva. | - | | `ocrApiEndpoint` | `string` | não | - | URL de um serviço de OCR próprio; vazio usa o do produto. | - | | `useOcrForAllDocuments` | `boolean` | não | `false` | Força o OCR mesmo em documentos com texto embutido. | - | | `documentType` | `enumeration` | não | `"invoice"` | Editor usado na revisão: fatura (com linhas e totais) ou genérico. | - | | `requiredExtractionFields` | `list` de `string` | não | - | Caminhos da extração marcados como CRÍTICOS: em falta, o editor avisa antes de gravar (nunca bloqueia). Só na fatura. | - | ### `autoMatchFields{}` Cada entrada de `autoMatchFields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureId` | `uuid` | não | - | Tabela onde se procura a linha correspondente. | feature (uuid) | | `searchColumn` | `string` | não | - | Coluna dessa tabela onde se procura o texto extraído. | coluna de `featureId` (nome) | | `valueColumn` | `string` | não | - | Coluna dessa tabela cujo valor fica na célula do match. | coluna de `featureId` (nome) | | `displayColumn` | `string` | não | - | Coluna dessa tabela que se mostra ao utilizador. | coluna de `featureId` (nome) | | `renderType` | `string` | não | - | Reservado para a forma de render do campo; hoje só "textfield". | - | ### `headerAutoMatchFields{}` Cada entrada de `headerAutoMatchFields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureId` | `uuid` | não | - | Tabela onde se procura a linha correspondente. | feature (uuid) | | `searchColumn` | `string` | não | - | Coluna dessa tabela onde se procura o texto extraído. | coluna de `featureId` (nome) | | `valueColumn` | `string` | não | - | Coluna dessa tabela cujo valor fica na célula do match. | coluna de `featureId` (nome) | | `displayColumn` | `string` | não | - | Coluna dessa tabela que se mostra ao utilizador. | coluna de `featureId` (nome) | | `renderType` | `string` | não | - | Reservado para a forma de render do campo; hoje só "textfield". | - | ### `headerCreationMappings{}[]` Cada elemento de cada entrada de `headerCreationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | - | Coluna a preencher na tabela do auto-match deste campo do cabeçalho. uuid OU nome: buildCreationOverrides aceita os dois. | coluna da mesma chave de `headerAutoMatchFields` (uuid ou nome) | | `sourceField` | `string` | não | - | Caminho do valor na extração do documento (ex.: "supplier.taxId"). | - | ### `lineCreationMappings{}[]` Cada elemento de cada entrada de `lineCreationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | - | Coluna a preencher na tabela do auto-match deste campo da linha. uuid OU nome: buildCreationOverrides aceita os dois. | coluna da mesma chave de `autoMatchFields` (uuid ou nome) | | `sourceField` | `string` | não | - | Chave do valor dentro da linha extraída (ex.: "unit"). | - | ## Exemplo JSON ```json { "allowedExtensions": [ "pdf", "jpg", "jpeg", "png", "bmp", "gif", "webp" ], "enableOCR": true, "enableAIProcessing": true, "ocrProvider": "google_ml_kit", "aiProvider": "openai", "autoProcess": false, "showPreview": true, "pdfRenderDPI": 150, "processAllPages": true, "combinePageTexts": true, "saveDocument": true, "autoFillFields": true, "headerMappings": {}, "linesMappings": {}, "autoMatchFields": {}, "enableAutoMatching": false, "headerAutoMatchFields": {}, "enableHeaderAutoMatching": false, "headerCreationMappings": {}, "lineCreationMappings": {}, "useOcrForAllDocuments": false, "documentType": "invoice" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # execution **Botão de execução** Botão que corre uma automação ou abre um formulário. - **Kind**: `component` - **Key**: `execution` - **Categoria**: `ação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `workflowId` | `uuid` | não | - | Automação da primeira geração (tabela Workflow). | workflow (uuid) | | `executionId` | `uuid` | não | - | **Descontinuado.** Nome antigo do workflowId; ainda lido, já não escrito pela app. | workflow (uuid) | | `workflowV2Id` | `uuid` | não | - | Automação WorkflowV2 (o grupo de versões). | workflow V2 (uuid) | | `openFormFeatureId` | `uuid` | não | - | Tabela cujo formulário o botão abre. | feature (uuid) | | `openFormRowIdColumnId` | `uuid` | não | - | Coluna desta tabela que traz o id da linha a abrir. | coluna (uuid) | | `buttonLabel` | `string` | não | - | Texto do botão; vazio usa o rótulo da coluna. | - | | `buttonIcon` | `string` | não | - | Nome do ícone desenhado no botão (ex.: "play_arrow"). | - | | `confirmationMessage` | `string` | não | - | Pergunta de confirmação antes de executar; vazio não pergunta. | - | | `showInTable` | `boolean` | não | `true` | Mostra o botão nas vistas de tabela. | - | | `showInForm` | `boolean` | não | `true` | Mostra o botão nos formulários. | - | | `buttonVariant` | `enumeration` | não | - | Aspeto do botão; vazio vale "filled". | - | | `buttonColorRole` | `enumeration` | não | - | Papel de cor do tema aplicado ao botão; vazio vale "primary". | - | | `visibleWhen` | `map` | não | - | Regra única que decide se o botão aparece; sem regra, está sempre visível. | - | | `cooldownSeconds` | `integer` | não | - | Segundos em que o botão fica desativado depois de uma execução com sucesso; vazio ou 0 não espera. | - | | `paramsFromColumns` | `map` | não | - | Nome do parâmetro da automação → coluna desta tabela de onde sai o valor. As CHAVES são nomes de parâmetro e não são referências; os VALORES são colunas. | - | ### `visibleWhen` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | não | - | Coluna desta tabela avaliada na linha do contexto. | coluna (uuid) | | `operator` | `enumeration` | não | - | Comparação feita sobre o valor da coluna; operador desconhecido deixa o botão visível. | - | | `value` | `string` | não | - | Valor comparado nos operadores equals/notEquals: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "showInTable": true, "showInForm": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # external_user **Contas externas** Marca as contas externas da organização que veem este registo no portal. - **Kind**: `component` - **Key**: `external_user` - **Categoria**: `pessoas` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `placeholder` | `string` | não | - | Texto de sugestão mostrado sem nenhuma conta marcada. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # file **Ficheiro** Carregamento de ficheiros para o bucket de anexos, com pré-visualização opcional. - **Kind**: `component` - **Key**: `file` - **Categoria**: `ficheiro` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `hintText` | `string` | não | - | Texto de ajuda do campo. | - | | `buttonLabel` | `string` | não | - | Rótulo do botão de carregar; vazio usa o texto padrão. | - | | `allowedExtensions` | `list` de `string` | não | - | Extensões aceites; vazio aceita todas. | - | | `maxFileSizeMB` | `integer` | não | - | Tamanho máximo de cada ficheiro em MB; vazio = sem limite. | - | | `showPreview` | `boolean` | não | `true` | Mostra a pré-visualização do ficheiro carregado. | - | | `allowMultiple` | `boolean` | não | `false` | Guarda uma LISTA de ficheiros; falso mantém a forma legada de um só objeto. | - | | `maxFiles` | `integer` | não | - | Número máximo de ficheiros quando allowMultiple; vazio = sem limite. | - | | `displayMode` | `enumeration` | não | - | Apresentação no formulário; vazio vale "list". | - | | `storageFolder` | `string` | não | - | Subpasta dentro de feature_x/column_y/, passada a slug no upload. | - | ## Exemplo JSON ```json { "showPreview": true, "allowMultiple": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # formula **Fórmula** Calcula um valor a partir de colunas desta tabela ou de outra. - **Kind**: `component` - **Key**: `formula` - **Categoria**: `agregação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `type` | `enumeration` | não | `"sum"` | Que cálculo se faz; é ele que diz quais dos campos valem. | - | | `placeholder` | `string` | não | - | Texto mostrado enquanto não há resultado. | - | | `formula` | `expression` | não | - | Expressão avaliada no tipo "expression", com as colunas referidas por @nome. | - | | `sourceFeatureId` | `uuid` | não | - | Tabela onde o xlookup procura. | feature (uuid) | | `sourceColumn` | `string` | não | - | Coluna da tabela de origem onde se procura o valor do callerColumn. | coluna de `sourceFeatureId` (uuid ou nome) | | `sourceValueColumn` | `string` | não | - | Coluna da tabela de origem cujo valor o xlookup devolve, na linha que casou. | coluna de `sourceFeatureId` (uuid ou nome) | | `callerColumn` | `string` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor a procurar. | coluna (uuid ou nome) | | `conditionFeatureId` | `uuid` | não | - | Tabela cujas linhas o sumif/countif filtra. | feature (uuid) | | `conditionColumn` | `string` | não | - | Coluna da tabela da condição por onde se filtra. | coluna de `conditionFeatureId` (uuid ou nome) | | `conditionValue` | `string` | não | - | Valor fixo da condição: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `conditionValueColumn` | `string` | não | - | Coluna desta MESMA tabela (a anfitriã) que dá o valor dinâmico da condição, em vez do conditionValue. | coluna (uuid ou nome) | | `sumColumn` | `string` | não | - | Coluna da tabela da condição que o sumif soma. | coluna de `conditionFeatureId` (uuid ou nome) | | `additionalConditions` | `list` de `map` | não | - | Condições extra que as linhas da condição têm de passar. | - | | `concatenateColumns` | `list` de `string` | não | - | Colunas desta tabela cujos valores se concatenam. | - | | `concatenateSeparator` | `string` | não | - | Texto entre valores concatenados; vazio vale ", ". | - | | `concatenateMaxChars` | `map` | não | - | Máximo de caracteres por coluna concatenada, com o id da coluna na chave; sem entrada = sem limite. | chave: coluna (uuid) | | `operandColumns` | `list` de `string` | não | - | Colunas desta tabela operadas pelas contas simples (sum/subtract/multiply/divide). | - | | `arithmeticExpressionSteps` | `list` de `map` | não | - | Passos da expressão aritmética montada no construtor visual. | - | | `renderAsComponent` | `enumeration` | não | - | Tipo de componente com que o resultado é desenhado. É ele que diz como ler renderComponentConfig. | - | | `renderComponentConfig` | `json` | não | - | Config do componente nomeado por renderAsComponent. | config de componente cujo tipo vem de `renderAsComponent` ([índice](../componentes/index.md)) | | `resultFormat` | `enumeration` | não | - | Formatação do resultado quando não há renderAsComponent; vazio vale "none". | - | | `resultDecimalPlaces` | `integer` | não | - | Casas decimais do resultado formatado. | - | | `errorFallback` | `string` | não | - | Texto mostrado quando a avaliação falha ou não devolve nada. | - | | `showDependencies` | `boolean` | não | `true` | Mostra o bloco "Depende de:" no construtor. | - | | `formulaHistory` | `list` | não | - | As últimas configurações guardadas, para desfazer. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `additionalConditions[]` Cada elemento de `additionalConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | não | - | Coluna da tabela da condição a filtrar. | coluna de `conditionFeatureId` (uuid) | | `operator` | `string` | não | `"="` | Operador da comparação. | - | | `value` | `string` | não | - | Valor fixo da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `valueColumnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor a comparar, em vez do value. | coluna (uuid) | ### `arithmeticExpressionSteps[]` Cada elemento de `arithmeticExpressionSteps` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `type` | `enumeration` | sim | - | Se o operando é uma coluna ou um número fixo. | - | | `columnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã), quando type é "column". | coluna (uuid) | | `fixedValue` | `number` | não | - | Número fixo, quando type é "value": dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `operator` | `string` | não | - | Operador antes do operando; vazio no primeiro. | - | | `openParens` | `integer` | não | `0` | Quantos "(" abrem antes deste operando. | - | | `closeParens` | `integer` | não | `0` | Quantos ")" fecham depois deste operando. | - | ## Exemplo JSON ```json { "type": "sum", "showDependencies": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # id **Identificador** Identificador gerado pela app: uuid, ou uma sequência com prefixo, padrão e reinício por período. - **Kind**: `component` - **Key**: `id` - **Categoria**: `sistema` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `prefix` | `string` | não | - | Texto antes da sequência (ex.: "FAT-"). | - | | `suffix` | `string` | não | - | Texto depois da sequência. | - | | `placeholder` | `string` | não | - | Texto mostrado antes de o identificador ser gerado. | - | | `idType` | `enumeration` | não | `"incremental"` | uuid aleatório ou sequência crescente. | - | | `lastUsedId` | `integer` | não | - | Último número usado pela sequência: ESTADO interno escrito pela app, não configuração. | - | | `zeroPadding` | `integer` | não | - | Dígitos a que a sequência é alinhada com zeros (4 → "0001"). | - | | `pattern` | `string` | não | - | Padrão com fichas (\{seq\}, \{seq:N\}, \{YYYY\}, \{YY\}, \{MM\}, \{DD\}, \{prefix\}, \{suffix\}); quando preenchido substitui a concatenação simples. | - | | `resetPeriod` | `enumeration` | não | - | Período ao fim do qual a sequência volta a 1; vazio ou "none" nunca reinicia. | - | | `lastResetKey` | `string` | não | - | Período do último reinício (ex.: "2026-07"): ESTADO interno escrito pela app, não configuração. | - | | `isUnique` | `boolean` | não | `false` | Recusa guardar um valor já usado noutra linha. | - | | `uniqueErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor está repetido. | - | | `uniqueWith` | `list` de `string` | não | `[]` | Outras colunas que entram na mesma chave: o repetido passa a ser o conjunto, e não esta coluna sozinha. Vazio = só esta coluna. | - | | `caseInsensitive` | `boolean` | não | `false` | Ignora maiúsculas e minúsculas na verificação de unicidade. | - | | `trimWhitespace` | `boolean` | não | `true` | Corta os espaços do início e do fim antes de guardar. | - | ## Exemplo JSON ```json { "idType": "incremental", "isUnique": false, "uniqueWith": [], "caseInsensitive": false, "trimWhitespace": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # image **Imagem** Imagem guardada como o `file` (o VALOR é o mesmo JSON de FileMetadata); esta config só escolhe a APRESENTAÇÃO por superfície. - **Kind**: `component` - **Key**: `image` - **Categoria**: `ficheiro` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `defaultDisplay` | `enumeration` | não | `"inline"` | Apresentação nas superfícies sem regra própria. | - | | `tableDisplay` | `enumeration` | não | `"inline"` | Apresentação nas vistas de tabela. | - | | `formDisplay` | `enumeration` | não | `"inline"` | Apresentação nos formulários. | - | | `kanbanDisplay` | `enumeration` | não | `"inline"` | Apresentação nas superfícies de cartão (kanban, kiosk, POS, cards). | - | | `allowMultiple` | `boolean` | não | `false` | Guarda uma LISTA de imagens; falso mantém a forma legada de um só objeto. | - | | `maxFiles` | `integer` | não | - | Número máximo de imagens quando allowMultiple; vazio = sem limite. | - | | `maxFileSizeMB` | `number` | não | - | Tamanho máximo de cada imagem em MB; vazio = sem limite. | - | | `storageFolder` | `string` | não | - | Subpasta dentro de feature_x/column_y/, passada a slug no upload. | - | ## Exemplo JSON ```json { "defaultDisplay": "inline", "tableDisplay": "inline", "formDisplay": "inline", "kanbanDisplay": "inline", "allowMultiple": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # linked_select **Ligação a tabela** Escolhe uma ou mais linhas de outra tabela. - **Kind**: `component` - **Key**: `linked_select` - **Categoria**: `relação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `linkedFeatureId` | `uuid` | não | - | Tabela de onde se escolhem as linhas. | feature (uuid) | | `linkedValueColumn` | `uuid` | não | - | Coluna da tabela ligada cujo valor se guarda. | coluna de `linkedFeatureId` (uuid) | | `linkedLabelColumn` | `uuid` | não | - | Coluna da tabela ligada que se mostra ao utilizador. | coluna de `linkedFeatureId` (uuid) | | `isMultiSelect` | `boolean` | não | `false` | Permite escolher mais do que uma linha. | - | | `placeholder` | `string` | não | - | Texto mostrado enquanto nada está escolhido. | - | | `sortAlphabetically` | `boolean` | não | `true` | Ordena as opções por ordem alfabética. | - | | `showAddButton` | `boolean` | não | `false` | Deixa criar uma linha nova na tabela ligada. | - | | `showEditButton` | `boolean` | não | `false` | Deixa editar a linha escolhida na tabela ligada. | - | | `defaultValue` | `string` | não | - | Valor pré-escolhido. É um VALOR da coluna linkedValueColumn, não uma referência: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `enforceReferentialIntegrity` | `boolean` | não | `false` | Impede apagar a linha ligada enquanto estiver em uso. | - | | `onDeleteAction` | `enumeration` | não | `"restrict"` | O que fazer a esta coluna quando a linha ligada é apagada. | - | | `restrictMessage` | `string` | não | - | Mensagem mostrada quando a integridade impede apagar. | - | | `foreignKeyErrorMessage` | `string` | não | - | Mensagem mostrada quando a ligação é inválida. | - | | `filterConditions` | `list` de `map` | não | - | Condições que estreitam as opções oferecidas. | - | | `extraDisplayColumns` | `list` de `uuid` | não | - | Colunas extra da tabela ligada mostradas na escolha. | - | | `showPeek` | `boolean` | não | `false` | Mostra uma pré-visualização da linha ligada. | - | | `displayStyle` | `enumeration` | não | - | Estilo da superfície de escolha; vazio vale "dropdown". | - | | `creationMappings` | `list` de `map` | não | - | Que colunas desta tabela semeiam a linha nova criada na tabela ligada. | - | ### `filterConditions[]` Cada elemento de `filterConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | não | - | Coluna da tabela ligada a filtrar. | coluna de `linkedFeatureId` (uuid) | | `callerValueColumnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor a comparar. | coluna (uuid) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor fixo da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `creationMappings[]` Cada elemento de `creationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | - | Coluna da tabela ligada a preencher. uuid OU nome: buildCreationOverrides aceita os dois. | coluna de `linkedFeatureId` (uuid ou nome) | | `sourceField` | `string` | não | - | Coluna desta tabela de onde sai o valor. uuid, nome ou caminho pontuado. | coluna (uuid ou nome) | ## Exemplo JSON ```json { "isMultiSelect": false, "sortAlphabetically": true, "showAddButton": false, "showEditButton": false, "enforceReferentialIntegrity": false, "onDeleteAction": "restrict", "showPeek": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # linked_view **Vista de tabela ligada** Encaixa uma vista de outra tabela, filtrada pelo valor desta linha. - **Kind**: `component` - **Key**: `linked_view` - **Categoria**: `relação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `linkedFeatureId` | `uuid` | não | - | Tabela cuja vista se encaixa. | feature (uuid) | | `linkedViewType` | `enumeration` | não | - | Tipo da vista a desenhar. NÃO é uma referência: identifica a vista em par com o linkedViewName, que é esse sim a referência. | - | | `linkedViewName` | `string` | não | - | Nome da vista a desenhar, dentro da tabela ligada; lê-se em par com o linkedViewType. Vazio usa a vista por omissão. | vista de `linkedFeatureId` (nome) | | `linkedFilterColumnId` | `uuid` | não | - | Coluna da tabela ligada por onde a vista é filtrada. | coluna de `linkedFeatureId` (uuid) | | `callerValueColumnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor do filtro. | coluna (uuid) | | `extraFilterPairs` | `list` de `map` | não | - | Pares extra de filtro, além do par base; cada um acrescenta uma condição dinâmica à vista encaixada. | - | | `staticFilters` | `list` de `map` | não | - | Condições fixas sobre a tabela ligada, com o valor escrito pelo administrador em vez de vir desta linha. | - | | `collapsible` | `boolean` | não | `false` | Dá à vista encaixada um cabeçalho compacto que se abre e fecha. | - | | `startCollapsed` | `boolean` | não | `false` | Só com collapsible: começa fechada em vez de aberta. | - | ### `extraFilterPairs[]` Cada elemento de `extraFilterPairs` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `filterColumnId` | `uuid` | não | - | Coluna da tabela ligada a filtrar. | coluna de `linkedFeatureId` (uuid) | | `callerValueColumnId` | `uuid` | não | - | Coluna desta MESMA tabela (a anfitriã) de onde sai o valor a comparar. | coluna (uuid) | ### `staticFilters[]` Cada elemento de `staticFilters` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | não | - | Coluna da tabela ligada a filtrar. | coluna de `linkedFeatureId` (uuid) | | `value` | `string` | não | - | Valor fixo da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "collapsible": false, "startCollapsed": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # lookup **Valor de tabela ligada** Mostra um valor de uma linha ligada, sem o copiar. - **Kind**: `component` - **Key**: `lookup` - **Categoria**: `relação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `relationColumnId` | `uuid` | não | - | Coluna de relação desta tabela que faz a ligação. | coluna (uuid) | | `targetColumnId` | `uuid` | não | - | Coluna a mostrar, da tabela ligada por relationColumnId. A feature é INDIRETA: vem da coluna de relação. | coluna de `relationColumnId` (uuid) | | `emptyText` | `string` | não | - | Texto mostrado quando não há valor ligado; vazio vale "—". | - | | `renderAsComponent` | `enumeration` | não | - | Tipo de componente com que o valor é desenhado. É ele que diz como ler renderComponentConfig. | - | | `renderComponentConfig` | `json` | não | - | Config do componente nomeado por renderAsComponent. | config de componente cujo tipo vem de `renderAsComponent` ([índice](../componentes/index.md)) | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # numericfield **Número** Campo numérico com casas decimais, sufixo e barra de progresso opcional. - **Kind**: `component` - **Key**: `numericfield` - **Categoria**: `número` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `decimalPlaces` | `integer` | não | - | Casas decimais a mostrar (vazio = inteiro). | - | | `isUnique` | `boolean` | não | `false` | Recusa guardar um valor já usado noutra linha. | - | | `uniqueErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor está repetido. | - | | `uniqueWith` | `list` de `string` | não | `[]` | Outras colunas que entram na mesma chave: o repetido passa a ser o conjunto, e não esta coluna sozinha. Vazio = só esta coluna. | - | | `suffix` | `enumeration` | não | `"none"` | Símbolo mostrado depois do valor. | - | | `visualMode` | `enumeration` | não | `"valueOnly"` | Mostra só o valor ou uma barra de progresso com o valor. | - | | `minValue` | `number` | não | - | Mínimo do intervalo (alimenta a barra de progresso). | - | | `maxValue` | `number` | não | - | Máximo do intervalo (alimenta a barra de progresso). | - | | `thousandsSeparator` | `boolean` | não | `true` | Agrupa os milhares na apresentação (pt_PT). Ligado por omissão para não mudar o que as colunas já mostravam. | - | | `prefixText` | `string` | não | - | Texto fixo mostrado antes do valor (ex.: "Ref."). | - | | `stepperEnabled` | `boolean` | não | `false` | Mostra os botões +/- para somar e subtrair. | - | | `stepValue` | `number` | não | `1` | Incremento de cada toque nos botões +/-. | - | | `rounding` | `enumeration` | não | - | Arredondamento aplicado ao guardar (vazio comporta-se como none). | - | | `allowNegative` | `boolean` | não | `true` | Permite escrever valores negativos. | - | | `enforceMinMax` | `boolean` | não | `false` | Faz de minValue/maxValue uma validação, e não só o intervalo da barra de progresso. | - | | `minMaxErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor sai do intervalo. | - | | `customUnit` | `string` | não | - | Unidade própria mostrada depois do valor (ex.: "kg", "m²"); só vale quando suffix é none. | - | | `isCurrency` | `boolean` | não | - | **Descontinuado.** Legado: valia o mesmo que suffix = currency. Ainda se lê, já não se escreve. | - | ## Exemplo JSON ```json { "isUnique": false, "uniqueWith": [], "suffix": "none", "visualMode": "valueOnly", "thousandsSeparator": true, "stepperEnabled": false, "stepValue": 1, "allowNegative": true, "enforceMinMax": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # rating **Classificação** Classificação por ícones (estrelas, corações ou círculos), com meios passos opcionais. - **Kind**: `component` - **Key**: `rating` - **Categoria**: `número` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `maxRating` | `integer` | não | `5` | Número de ícones mostrados, limitado ao intervalo 3-10. | - | | `allowHalf` | `boolean` | não | `false` | Permite escolher meios passos (ex.: 3,5). | - | | `iconStyle` | `enumeration` | não | - | Família do ícone; vazio ou desconhecido vale "star". | - | | `showValue` | `boolean` | não | `false` | Mostra o valor numérico ao lado dos ícones. | - | | `defaultValue` | `number` | não | - | Valor aplicado às linhas NOVAS. Vazio = sem omissão. | - | ## Exemplo JSON ```json { "maxRating": 5, "allowHalf": false, "showValue": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # rollup **Agregação de tabela ligada** Soma, conta ou calcula sobre as linhas ligadas a esta. - **Kind**: `component` - **Key**: `rollup` - **Categoria**: `agregação` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `sourceFeatureId` | `uuid` | não | - | Tabela cujas linhas se agregam. | feature (uuid) | | `sourceRelationColumnId` | `uuid` | não | - | Coluna da tabela de origem que aponta para esta linha. | coluna de `sourceFeatureId` (uuid) | | `aggregation` | `enumeration` | não | - | Operação de agregação; vazio vale "count". | - | | `aggregationColumnId` | `uuid` | não | - | Coluna da tabela de origem sobre a qual se agrega. | coluna de `sourceFeatureId` (uuid) | | `conditions` | `list` de `map` | não | - | Condições que estreitam as linhas agregadas. | - | | `conditionsLogic` | `string` | não | - | Como se combinam as condições; vazio vale "and". | - | | `periodFilter` | `enumeration` | não | - | Janela de createdAt aplicada às linhas agregadas; vazio vale "none". | - | | `emptyText` | `string` | não | - | Texto mostrado quando não há linhas para agregar. | - | ### `conditions[]` Cada elemento de `conditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnId` | `uuid` | sim | - | Coluna da tabela de origem a filtrar. | coluna de `sourceFeatureId` (uuid) | | `operator` | `string` | sim | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # select **Lista** Menu de opções predefinidas, de escolha única ou múltipla. - **Kind**: `component` - **Key**: `select` - **Categoria**: `escolha` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `options` | `list` de `map` | não | `[]` | As opções oferecidas, por ordem de apresentação. | - | | `isMultiSelect` | `boolean` | não | `false` | Permite escolher mais do que uma opção. | - | | `placeholder` | `string` | não | - | Texto de sugestão mostrado sem nada escolhido. | - | | `defaultOptionId` | `string` | não | - | Id da opção (ver options) aplicada às linhas novas. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `minSelections` | `integer` | não | - | Mínimo de opções a escolher (só com isMultiSelect). | - | | `maxSelections` | `integer` | não | - | Máximo de opções a escolher (só com isMultiSelect). | - | | `allowOther` | `boolean` | não | `false` | Oferece "Outro…" e aceita texto livre como valor. | - | ### `options[]` Cada elemento de `options` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da opção, guardado na célula; nas opções vindas da API é o próprio texto. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `label` | `string` | sim | - | Texto mostrado da opção. | - | | `color` | `string` | não | - | Cor da opção em hex "#RRGGBB"; vazio = sem cor. | - | | `icon` | `enumeration` | não | - | Nome curado do ícone da opção; vazio = sem ícone. | - | ## Exemplo JSON ```json { "options": [], "isMultiSelect": false, "allowOther": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # slider **Deslizador** Deslizador numérico num intervalo fechado, com passo opcional. - **Kind**: `component` - **Key**: `slider` - **Categoria**: `número` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `minValue` | `number` | não | `0` | Limite inferior do deslizador. | - | | `maxValue` | `number` | não | `100` | Limite superior do deslizador. | - | | `stepValue` | `number` | não | - | Incremento entre valores escolhíveis (vazio = contínuo). | - | | `showValue` | `boolean` | não | `true` | Mostra o valor numérico ao lado do deslizador. | - | | `suffix` | `string` | não | - | Unidade acrescentada ao valor mostrado (ex.: "%", "kg"). | - | | `defaultValue` | `number` | não | - | Valor aplicado às linhas NOVAS. Vazio = sem omissão. | - | ## Exemplo JSON ```json { "minValue": 0, "maxValue": 100, "showValue": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # subuser **Operador** Atribui um operador (identidade de kiosk, autenticada por PIN) ao registo. - **Kind**: `component` - **Key**: `subuser` - **Categoria**: `pessoas` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `placeholder` | `string` | não | - | Texto de sugestão mostrado sem ninguém atribuído. | - | | `filterGroupId` | `uuid` | não | - | Grupo de subusers a que o seletor se limita; vazio = todos os operadores ativos. | - | | `lockToCurrentOperator` | `boolean` | não | `false` | Fixa o operador em sessão e impede mudar a atribuição. | - | ## Exemplo JSON ```json { "lockToCurrentOperator": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # tags **Etiquetas** Etiquetas livres; o valor guardado é uma lista de textos. - **Kind**: `component` - **Key**: `tags` - **Categoria**: `texto` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `allowNew` | `boolean` | não | `true` | Escrever um valor que não é sugestão cria uma etiqueta nova. | - | | `suggestFromExisting` | `boolean` | não | `true` | Sugere as etiquetas já usadas nesta coluna nas outras linhas. | - | | `predefinedTags` | `list` de `string` | não | `[]` | Sugestões fixas definidas na configuração, sempre oferecidas. | - | | `maxTags` | `integer` | não | - | Máximo de etiquetas por célula (vazio = sem limite). | - | | `normalizeLowercase` | `boolean` | não | `false` | Passa cada etiqueta a minúsculas antes de a guardar. | - | ## Exemplo JSON ```json { "allowNew": true, "suggestFromExisting": true, "predefinedTags": [], "normalizeLowercase": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # textfield **Texto** Campo de texto de uma linha, com validações e máscaras. - **Kind**: `component` - **Key**: `textfield` - **Categoria**: `texto` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `hintText` | `string` | não | - | Texto de sugestão mostrado no campo vazio. | - | | `autofocus` | `boolean` | não | `false` | Coloca o cursor neste campo ao abrir o formulário. | - | | `isUnique` | `boolean` | não | `false` | Recusa guardar um valor já usado noutra linha. | - | | `uniqueErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor está repetido. | - | | `uniqueWith` | `list` de `string` | não | `[]` | Outras colunas que entram na mesma chave: o repetido passa a ser o conjunto, e não esta coluna sozinha. Vazio = só esta coluna. | - | | `caseInsensitive` | `boolean` | não | `false` | Ignora maiúsculas e minúsculas na verificação de unicidade. | - | | `trimWhitespace` | `boolean` | não | `true` | Corta os espaços do início e do fim antes de guardar. | - | | `minLength` | `integer` | não | - | Número mínimo de caracteres aceites. | - | | `maxLength` | `integer` | não | - | Número máximo de caracteres aceites. | - | | `pattern` | `string` | não | - | Expressão regular que o valor tem de cumprir. | - | | `patternErrorMessage` | `string` | não | - | Mensagem a mostrar quando o valor não cumpre o padrão. | - | | `semanticType` | `enumeration` | não | - | Natureza do conteúdo, que escolhe o teclado e a validação. Exclusivo com inputMask. | - | | `multiline` | `boolean` | não | `false` | Permite várias linhas de texto. | - | | `maxLines` | `integer` | não | - | Linhas visíveis quando multiline está ligado (3 por omissão em execução). | - | | `showCharacterCount` | `boolean` | não | `false` | Mostra o contador de caracteres sob o campo. | - | | `inputMask` | `enumeration` | não | - | Máscara de introdução portuguesa. Exclusivo com semanticType. | - | | `prefixText` | `string` | não | - | Texto fixo mostrado antes do valor. | - | | `suffixText` | `string` | não | - | Texto fixo mostrado depois do valor. | - | | `textTransform` | `enumeration` | não | - | Transformação aplicada ao texto enquanto se escreve. | - | | `autocompleteFromExisting` | `boolean` | não | `false` | Sugere valores já existentes nesta coluna. | - | ## Exemplo JSON ```json { "autofocus": false, "isUnique": false, "uniqueWith": [], "caseInsensitive": false, "trimWhitespace": true, "multiline": false, "showCharacterCount": false, "autocompleteFromExisting": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # timer **Temporizador** Cronómetro da linha, com perfil de campos, arredondamento e linha derivada ao parar. - **Kind**: `component` - **Key**: `timer` - **Categoria**: `tempo` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `label` | `string` | não | - | Etiqueta do temporizador a correr; vazio usa o rótulo da coluna. | - | | `contextFieldsToCapture` | `list` de `string` | não | `[]` | Colunas desta tabela copiadas para o histórico ao arrancar; anterior ao featureColumnMap, que é o caminho de hoje. | - | | `categoryFromField` | `string` | não | - | **Descontinuado.** Coluna desta tabela cujo valor virava a categoria; hoje a origem escreve-se em fieldSources.category. | coluna (nome) | | `timerProfileId` | `uuid` | não | - | Perfil que define o esquema de campos do temporizador; sem perfil, a coluna comporta-se como antes. | perfil de timer (uuid) | | `fieldSources` | `map` | não | - | Origem de cada campo do esquema do perfil (label, category, notes, custom_1..3) nesta coluna. | - | | `promptBeforeStart` | `boolean` | não | `false` | Abre o diálogo de arranque antes de contar o tempo. | - | | `showHistoryButton` | `boolean` | não | `true` | Mostra o botão de histórico no formulário. | - | | `linkFeatureId` | `uuid` | não | - | Tabela que recebe uma linha nova ao parar; vazio só alimenta as tabelas de temporizador. | feature (uuid) | | `featureColumnMap` | `map` | não | - | Mapeamento para a tabela de destino: que coluna recebe o quê ao parar. As chaves de auto e host são nomes de colunas dessa tabela. | - | | `roundingMinutes` | `integer` | não | - | Arredonda a duração ao múltiplo de minutos mais próximo ao parar; vazio ou 0 não arredonda. | - | | `countdownMinutes` | `integer` | não | - | Conta para trás a partir destes minutos em vez de mostrar o tempo decorrido. | - | | `dailyGoalMinutes` | `integer` | não | - | Objetivo diário mostrado como "Hoje: X / Y" no formulário; nunca bloqueia nada. | - | | `startWorkflowV2Id` | `uuid` | não | - | Automação WorkflowV2 disparada quando arranca. | workflow V2 (uuid) | | `stopWorkflowV2Id` | `uuid` | não | - | Automação WorkflowV2 disparada quando para; independente da de arranque. | workflow V2 (uuid) | ### `fieldSources{}` Cada entrada de `fieldSources` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mode` | `enumeration` | sim | - | De onde vem o valor: coluna da linha, valor fixo, pergunta ao iniciar, ou campo escondido. | - | | `column` | `string` | não | - | Coluna desta tabela lida no modo "host". | coluna (nome) | | `value` | `string` | não | - | Valor escrito na configuração no modo "fixed": dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `featureColumnMap` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `auto` | `map` | não | - | Coluna de destino → campo do temporizador que a preenche. Pelo menos uma entrada liga a criação da linha. | chave: coluna de `linkFeatureId` (nome) | | `host` | `map` | não | - | Coluna de destino → coluna DESTA tabela de onde se copia o valor, lido na linha ao arrancar. | chave: coluna de `linkFeatureId` (nome) | | `ask_at_start` | `list` de `string` | não | - | Colunas da tabela de destino que o utilizador preenche no diálogo de arranque. | - | | `history_label_field` | `string` | não | - | Título de cada entrada no histórico: "auto:<campo>" ou "field:<coluna de destino>"; vazio mostra a duração. | - | ## Exemplo JSON ```json { "contextFieldsToCapture": [], "promptBeforeStart": false, "showHistoryButton": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # user **Utilizador** Atribui um ou mais membros do workspace ao registo. - **Kind**: `component` - **Key**: `user` - **Categoria**: `pessoas` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `allowMultiple` | `boolean` | não | `false` | Permite atribuir mais do que um utilizador. | - | | `showAvatar` | `boolean` | não | `true` | Mostra a fotografia do utilizador ao lado do nome. | - | | `displayFormat` | `enumeration` | não | - | Como se escreve o utilizador; vazio ou desconhecido vale "name". | - | | `placeholder` | `string` | não | - | Texto de sugestão mostrado sem ninguém atribuído. | - | | `defaultToCurrentUser` | `boolean` | não | `false` | Pré-preenche as linhas novas com quem está em sessão. | - | | `maxSelections` | `integer` | não | - | Máximo de utilizadores a atribuir (só com allowMultiple). | - | | `notifyOnAssign` | `boolean` | não | `false` | Notifica quem entra ou sai deste campo. | - | | `notifyOnRowChange` | `boolean` | não | `false` | Notifica quem está neste campo quando a linha muda. | - | | `notifyOnMessage` | `boolean` | não | `false` | Notifica quem está neste campo de comentários e conversa no registo. | - | | `channels` | `list` de `enumeration` | não | `["inApp"]` | Por onde chegam os avisos desta coluna; o sino (inApp) está sempre presente. | - | | `rowChangeColumns` | `list` de `string` | não | `[]` | Colunas que contam como "a linha mudou"; vazio = qualquer coluna. | - | ## Exemplo JSON ```json { "allowMultiple": false, "showAvatar": true, "defaultToCurrentUser": false, "notifyOnAssign": false, "notifyOnRowChange": false, "notifyOnMessage": false, "channels": [ "inApp" ], "rowChangeColumns": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # Vistas 21 keys declaradas. | Key | Nome | Descrição | |---|---|---| | [`calendar`](./calendar.md) | Calendário | Registos dispostos num calendário pelas suas datas. | | [`cards`](./cards.md) | Cartões | Linhas em cartões, com as colunas a mostrar escolhidas uma a uma e cores por regra. | | [`chat`](./chat.md) | Chat | Conversas sobre linhas de mensagem: grupos, respostas em fio, reações e recibos de leitura. | | [`daily_timesheet`](./daily_timesheet.md) | Folha de horas diária | Folha de horas diária (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). | | [`dashboard`](./dashboard.md) | Dashboard | Painel de widgets - KPIs, gráficos, listas e tabelas -, cada um com a sua feature e os seus filtros. | | [`document`](./document.md) | Documentos | Explorador de ficheiros sobre uma feature: árvore de agrupamento à esquerda, pré-visualização, e encaminhamento do upload para uma automação. | | [`form`](./form.md) | Formulário | Um registo de cada vez, com os campos dispostos em secções, linhas e abas. | | [`gantt`](./gantt.md) | Cronograma | Barras temporais por registo num cronograma com zoom. | | [`kanban`](./kanban.md) | Kanban | Cartões em colunas por estado, movidos por arrastar. | | [`kiosk`](./kiosk.md) | Kiosk | Balcão para operação rápida por subutilizadores: login de operador, separadores com vistas embebidas, botões de automação e marcação de turno. | | [`list`](./list.md) | Lista | Linhas numa lista compacta, com imagem, títulos, data e caixa de verificação escolhidos coluna a coluna. | | [`map`](./map.md) | Mapa | Registos com coordenadas dispostos como marcadores num mapa. | | [`monthly_timesheet`](./monthly_timesheet.md) | Folha de horas mensal | Folha de horas mensal (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). | | [`pivot`](./pivot.md) | Tabela dinâmica | Linhas agregadas em prateleiras de linhas, colunas e valores, com totais e percentagens. | | [`record`](./record.md) | Record | Mestre-detalhe: à esquerda um seletor de linhas desta feature, à direita a vista de detalhe que a linha escolhida filtra. | | [`report`](./report.md) | Report | Relatório autónomo: um documento HTML escrito pela IA (ou um template de PDF) desenhado sobre dados ao vivo, sem rede. | | [`sidebyside`](./sidebyside.md) | Lado a lado | Duas features lado a lado para comparar, conciliar e passar linhas de um lado para o outro. | | [`table`](./table.md) | Tabela | Grelha de linhas e colunas, com agrupamento, filtros, somas de rodapé e cores por regra. | | [`timesheet`](./timesheet.md) | Folha de horas | Registo de horas por dia, semana ou mês. | | [`weekly_timesheet`](./weekly_timesheet.md) | Folha de horas semanal | Folha de horas semanal (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). | | [`workload`](./workload.md) | Capacidade | Carga e capacidade dos recursos ao longo do tempo, com sinalização de sobrecarga. | --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # calendar **Calendário** Registos dispostos num calendário pelas suas datas. - **Kind**: `view` - **Key**: `calendar` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `startDateField` | `string` | não | - | Coluna da data de início do evento. | coluna (nome) | | `endDateField` | `string` | não | - | Coluna da data de fim do evento. | coluna (nome) | | `titleField` | `string` | não | - | Coluna do título do evento. | coluna (nome) | | `labelField` | `string` | não | - | **Descontinuado.** Nome antigo do titleField; ainda lido como recurso, já não escrito pela app. | coluna (nome) | | `subtitleField` | `string` | não | - | Coluna do subtítulo do evento. | coluna (nome) | | `notesField` | `string` | não | - | Coluna das notas do evento. | coluna (nome) | | `defaultViewMode` | `enumeration` | não | `"week"` | Modo em que o calendário abre. | - | | `timeScale` | `map` | não | `{"endHour":18,"intervalMinutes":30,"startHour":8}` | Faixa de horas desenhada e o passo da grelha. | - | | `weekStartsOn` | `integer` | não | `1` | Primeiro dia da semana, 1 = segunda-feira. | - | | `defaultEventDurationMinutes` | `integer` | não | `60` | Duração dada a um evento novo criado por toque no calendário. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `baseFilters` | `json` | não | - | **Descontinuado.** Filtros de base no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `baseFilterTypes` | `json` | não | - | **Descontinuado.** Operadores dos filtros de base no formato legado: nome da coluna → operador. Só lido, a par de baseFilters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `sortRules` | `list` de `map` | não | `[]` | Ordenação dos eventos do mesmo intervalo, por prioridade. | - | | `searchableColumns` | `list` de `string` | não | - | Colunas onde a pesquisa do calendário procura. | - | | `quickCreateFields` | `list` de `string` | não | - | Colunas mostradas na criação rápida, abaixo das datas. | - | | `disabledViewModes` | `list` de `enumeration` | não | `[]` | Modos escondidos do selector. Guarda-se o conjunto DESLIGADO (e não o permitido) para um modo novo da app ficar disponível sem tocar nas configs antigas. | - | | `allDayEvents` | `boolean` | não | `false` | Desenha todos os eventos na faixa de dia inteiro. | - | | `dynamicRenderConfig` | `json` | não | - | Configuração livre do desenho dinâmico do evento. | - | ### `timeScale` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `startHour` | `integer` | sim | - | Primeira hora desenhada (omissão de leitura: 8). | - | | `endHour` | `integer` | sim | - | Última hora desenhada (omissão de leitura: 18). | - | | `intervalMinutes` | `integer` | sim | - | Minutos de cada linha da grelha (omissão de leitura: 30). | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `sortRules[]` Cada elemento de `sortRules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | sim | - | Coluna por que se ordena, POR NOME. | coluna (nome) | | `ascending` | `boolean` | sim | - | Sentido da ordenação (omissão de leitura: true). | - | | `priority` | `integer` | sim | - | Ordem de aplicação da regra, do menor para o maior. | - | ## Exemplo JSON ```json [ { "defaultViewMode": "week", "timeScale": { "endHour": 18, "intervalMinutes": 30, "startHour": 8 }, "weekStartsOn": 1, "defaultEventDurationMinutes": 60, "sortRules": [], "disabledViewModes": [], "allDayEvents": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # cards **Cartões** Linhas em cartões, com as colunas a mostrar escolhidas uma a uma e cores por regra. - **Kind**: `view` - **Key**: `cards` - **Categoria**: `grelha` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `displayFields` | `list` de `string` | não | - | Colunas desenhadas dentro do cartão; vazio mostra todas. | - | | `groupBy` | `string` | não | - | Coluna por que se agrupam os cartões. | coluna (nome) | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordena, por ordem. | - | | `sortWithinGroups` | `string` | não | - | **Descontinuado.** Nome antigo, de uma só coluna e sem sentido, do sortedColumns; ainda lido, já não escrito pela app. | coluna (nome) | | `sortDirections` | `map` | não | - | Nome da coluna → sentido da ordenação. | chave: coluna (nome) | | `actionMode` | `enumeration` | não | `"editForm"` | O que acontece ao tocar num cartão. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `allowSelection` | `boolean` | não | `false` | Permite selecionar cartões. | - | | `showSearchButton` | `boolean` | não | `true` | Mostra o botão de pesquisa. | - | | `showFilterButton` | `boolean` | não | `true` | Mostra o botão de filtros. | - | | `showGroupButton` | `boolean` | não | `true` | Mostra o botão de agrupamento. | - | | `facetPanelState` | `json` | não | - | Estado do painel de filtros facetados, por utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "actionMode": "editForm", "allowAdd": true, "allowSelection": false, "showSearchButton": true, "showFilterButton": true, "showGroupButton": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # chat **Chat** Conversas sobre linhas de mensagem: grupos, respostas em fio, reações e recibos de leitura. - **Kind**: `view` - **Key**: `chat` - **Categoria**: `conversa` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `userColumn` | `string` | não | - | Coluna do autor da mensagem, POR NOME. | coluna (nome) | | `messageColumn` | `string` | não | - | Coluna do corpo da mensagem, POR NOME. | coluna (nome) | | `dateColumn` | `string` | não | - | Coluna da data/hora da mensagem, POR NOME. | coluna (nome) | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtro de base no formato legado: nome da coluna → texto procurado (aplicado como `contains`). Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `sortAscending` | `boolean` | não | `true` | Ordem cronológica: da mais antiga para a mais recente. | - | | `conversationColumn` | `string` | não | - | Coluna que liga cada mensagem a uma conversa ou grupo, POR NOME. Sem ela, a vista mostra todas as mensagens numa só conversa. | coluna (nome) | | `chatTypeColumn` | `string` | não | - | Coluna que distingue conversa individual de grupo, POR NOME. | coluna (nome) | | `chatParticipantsColumn` | `string` | não | - | Coluna com a lista de participantes, POR NOME. | coluna (nome) | | `chatNameColumn` | `string` | não | - | Coluna com o nome da conversa ou do grupo, POR NOME. | coluna (nome) | | `attachmentsColumn` | `string` | não | - | Coluna dos ficheiros anexados à mensagem, POR NOME. | coluna (nome) | | `threadColumn` | `string` | não | - | Coluna com o id da mensagem-mãe, POR NOME: é ela que faz os fios de resposta. | coluna (nome) | | `reactionsColumn` | `string` | não | - | Coluna com o JSON das reações (emoji → utilizadores), POR NOME. | coluna (nome) | | `readReceiptsColumn` | `string` | não | - | Coluna com o JSON dos recibos de leitura (utilizador → momento), POR NOME. | coluna (nome) | | `mentionsEnabled` | `boolean` | não | `true` | Liga as menções com @. | - | | `reactionsEnabled` | `boolean` | não | `true` | Liga as reações às mensagens. | - | | `threadsEnabled` | `boolean` | não | `false` | Liga os fios de resposta. | - | | `readReceiptsEnabled` | `boolean` | não | `false` | Liga os recibos de leitura. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "sortAscending": true, "mentionsEnabled": true, "reactionsEnabled": true, "threadsEnabled": false, "readReceiptsEnabled": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # daily_timesheet **Folha de horas diária** Folha de horas diária (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). - **Kind**: `view` - **Key**: `daily_timesheet` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `modes` | `list` de `enumeration` | não | `["daily","weekly","monthly","stats"]` | Separadores visíveis, por ordem. Um só = sem barra de separadores. Valores fora do conjunto são ignorados na leitura. | - | | `source` | `enumeration` | não | `"auto"` | De onde vêm os registos: a tabela Timer, as linhas da feature, ou `auto` (Timer quando a feature é a do temporizador). | - | | `columnMap` | `map` | não | `{}` | Que coluna desta feature transporta cada parte do registo. Só sai no JSON quando tem alguma parte preenchida, e só conta quando a fonte são as linhas da feature. | - | | `filterSourceFeatureId` | `uuid` | não | - | Restringe os registos aos que vêm desta feature de origem (compara com `TimerEntry.sourceFeatureId` na fonte Timer). | feature (uuid) | | `categoryFilter` | `string` | não | - | Restringe os registos a uma categoria: valor, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterUserId` | `uuid` | não | - | Restringe os registos a um utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterProfileId` | `uuid` | não | - | Perfil de temporizador pré-escolhido na entrada manual, e filtro dos registos desse perfil. | perfil de timer (uuid) | | `hoursPerDayTarget` | `number` | não | - | Horas-alvo por dia, usadas nas barras de progresso. | - | | `allowManualEntry` | `boolean` | não | `true` | Deixa lançar registos à mão. | - | | `showCategoryBreakdown` | `boolean` | não | `true` | No modo diário: mostra o detalhe por categoria. | - | | `groupByCategory` | `boolean` | não | `false` | No modo semanal: uma linha por categoria. | - | | `weekStartsOn` | `integer` | não | `1` | No modo semanal: dia em que a semana começa, de 1 a 7. | - | | `firstDayOfWeek` | `integer` | não | `1` | No modo mensal: dia em que a grelha começa, de 1 a 7. | - | | `showWeekTotals` | `boolean` | não | `true` | No modo mensal: mostra os totais por semana. | - | ### `columnMap` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `date` | `string` | não | - | Coluna da data do registo, POR NOME. | coluna (nome) | | `duration` | `string` | não | - | Coluna da duração em segundos, POR NOME. Ganha ao par início/fim quando está preenchida. | coluna (nome) | | `startedAt` | `string` | não | - | Coluna do início, POR NOME. | coluna (nome) | | `endedAt` | `string` | não | - | Coluna do fim, POR NOME. | coluna (nome) | | `label` | `string` | não | - | Coluna da descrição do registo, POR NOME. | coluna (nome) | | `category` | `string` | não | - | Coluna da categoria, POR NOME. | coluna (nome) | | `userId` | `string` | não | - | Coluna do utilizador a quem o registo pertence, POR NOME. | coluna (nome) | | `notes` | `string` | não | - | Coluna das notas, POR NOME. | coluna (nome) | ## Exemplo JSON ```json [ { "modes": [ "daily", "weekly", "monthly", "stats" ], "source": "auto", "columnMap": {}, "allowManualEntry": true, "showCategoryBreakdown": true, "groupByCategory": false, "weekStartsOn": 1, "firstDayOfWeek": 1, "showWeekTotals": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # dashboard **Dashboard** Painel de widgets - KPIs, gráficos, listas e tabelas -, cada um com a sua feature e os seus filtros. - **Kind**: `view` - **Key**: `dashboard` - **Categoria**: `painel` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `layoutMode` | `enumeration` | não | `"rows"` | Como os widgets se arrumam: em faixas horizontais (`rows`) ou numa grelha de colunas e linhas (`grid`). | - | | `rows` | `list` de `map` | não | `[]` | As faixas do modo `rows`; fica vazia no modo `grid` (o `DashboardLayout` nem as lê). | - | | `gridColumns` | `integer` | não | `12` | Quantas colunas tem a grelha; só lido no modo `grid`. | - | | `gridRows` | `integer` | não | `6` | Quantas linhas tem a grelha; só lido no modo `grid`. | - | | `widgets` | `list` de `map` | não | `[]` | Os widgets do painel. Cada um traz a sua feature, os seus filtros e a sua config de dados. | - | | `globalFilterDefinitions` | `map` | não | `{}` | Os filtros globais do painel, por id: o que a barra de cima mostra e a que os widgets se ligam. | - | | `globalFilterValues` | `json` | não | `{}` | Valores que o administrador fixou para os filtros globais, por id: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `globalFilterMappings` | `json` | não | `{}` | Ligação de cada filtro global à variável dos widgets: na chave o id do filtro, no valor o nome da variável (em regra o nome da coluna filtrada). | - | | `title` | `string` | não | `"Dashboard"` | Título do painel, mostrado no cabeçalho. | - | | `showHeader` | `boolean` | não | `true` | Mostra o cabeçalho do painel (título e acções). | - | | `showGlobalPeriodBar` | `boolean` | não | `false` | Mostra a barra de período (granularidade e navegação), que alimenta os filtros `__period.from`/`__period.to`. | - | ### `rows[]` Cada elemento de `rows` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | sim | - | Identificador da faixa, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `slots` | `integer` | não | `8` | Em quantas casas a faixa se divide na horizontal; é o limite do `span` dos widgets que lá vivem. | - | | `height` | `integer` | não | `1` | Altura em unidades de 120 px (1, 2 ou 3), ou o sentinela `fillRemaining` na última faixa. | - | | `title` | `string` | não | - | Título da faixa, mostrado acima dos widgets. Só sai no JSON quando não é nulo. | - | ### `widgets[]` Cada elemento de `widgets` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | sim | - | Identificador do widget, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `category` | `enumeration` | sim | - | Família do widget. É ela que diz como ler o `dataConfig` e o `displayConfig`. | - | | `subtype` | `string` | sim | - | Variante dentro da categoria: `kpi` tem single, comparison, sparkline, progress e gauge; `chart` tem bar, column, line, area, pie, scatter e combo; `list` tem simple, top e leaderboard; `table` tem aggregated, raw e pivot; `actionGroup` tem buttons; `linkedView` usa a string vazia. | - | | `title` | `string` | não | - | Título mostrado no cabeçalho do widget. Só sai no JSON quando não é nulo. | - | | `subtitle` | `string` | não | - | Subtítulo mostrado sob o título. Só sai no JSON quando não é nulo. | - | | `swatchColor` | `string` | não | - | Cor de realce do cartão do widget, escolhida no editor; hoje só guardada. | - | | `hideHeader` | `boolean` | não | `false` | Esconde o cabeçalho do widget (título e acções). | - | | `featureId` | `uuid` | não | - | A feature de onde este widget tira as linhas. É o alvo de todas as colunas do widget; fica nulo nos `actionGroup`, que não leem dados. | feature (uuid) | | `filterBindings` | `list` de `string` | não | `[]` | Variáveis de filtro a que o widget se liga: colunas da feature do widget, POR NOME. | - | | `localFilters` | `map` | não | - | Filtro próprio do widget, aplicado às linhas da feature dele. | - | | `globalFilters` | `map` | não | - | Grupo paralelo em que cada regra liga uma coluna do widget a um filtro global: o valor é sempre o sentinela `${id do filtro global}`, não uma constante. | - | | `rowId` | `string` | não | - | Faixa onde o widget está, pelo `rows[].id`; só lido no modo `rows`. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `slotStart` | `integer` | não | - | Casa da faixa onde o widget começa, de 0 a `slots - span`; modo `rows`. | - | | `span` | `integer` | não | - | Quantas casas da faixa o widget ocupa, de 1 a `slots`; modo `rows`. | - | | `colStart` | `integer` | não | - | Coluna da grelha onde o widget começa, de 0 a `gridColumns - 1`; modo `grid`. | - | | `rowStart` | `integer` | não | - | Linha da grelha onde o widget começa, de 0 a `gridRows - 1`; modo `grid`. | - | | `colSpan` | `integer` | não | - | Quantas colunas da grelha o widget ocupa; modo `grid`. | - | | `rowSpan` | `integer` | não | - | Quantas linhas da grelha o widget ocupa; modo `grid`. | - | | `dataConfig` | `json` | não | `{}` | Config de dados do widget, de forma livre por category/subtype: a medida (`measureColumn`, `aggregation`), as dimensões (`dimensionColumn`, `seriesColumn`) e os alvos - colunas POR NOME da feature do widget. O `linkedView` guarda aqui o `viewId` da vista embebida e o `actionGroup` os `buttons[]`, cujo `target` é um workflow ou um URL. | - | | `displayConfig` | `json` | não | `{}` | Config de aparência do widget, de forma livre por category/subtype. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `sourceTemplateId` | `string` | não | - | Modelo da biblioteca de que este widget foi criado: proveniência, não dependência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `widgets[].localFilters` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `widgets[].localFilters.rules[]` Cada elemento de `widgets[].localFilters.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature do widget, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `widgets[].localFilters.groups[]` Cada elemento de `widgets[].localFilters.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `widgets[].localFilters.groups[].rules[]` Cada elemento de `widgets[].localFilters.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature do widget, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `widgets[].globalFilters` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `widgets[].globalFilters.rules[]` Cada elemento de `widgets[].globalFilters.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature do widget, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `widgets[].globalFilters.groups[]` Cada elemento de `widgets[].globalFilters.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `widgets[].globalFilters.groups[].rules[]` Cada elemento de `widgets[].globalFilters.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature do widget, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `globalFilterDefinitions{}` Cada entrada de `globalFilterDefinitions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | sim | - | Identificador do filtro, escrito pelo administrador; é o que os widgets citam no sentinela `${id}`. | - | | `label` | `string` | sim | - | Nome do filtro na barra de cima. | - | | `description` | `string` | não | `""` | Ajuda mostrada a par do campo do filtro. | - | | `dataType` | `enumeration` | não | `"string"` | Tipo do valor, que escolhe o campo desenhado na barra de filtros. | - | | `defaultValue` | `json` | não | - | Valor inicial do filtro: dado de utilizador (pode ser uma DateReference relativa). Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `showInFrontend` | `boolean` | não | `true` | Mostra o filtro na barra de cima; a falso fica só como valor fixo do administrador. | - | ## Exemplo JSON ```json [ { "layoutMode": "rows", "rows": [], "gridColumns": 12, "gridRows": 6, "widgets": [], "globalFilterDefinitions": {}, "globalFilterValues": {}, "globalFilterMappings": {}, "title": "Dashboard", "showHeader": true, "showGlobalPeriodBar": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # document **Documentos** Explorador de ficheiros sobre uma feature: árvore de agrupamento à esquerda, pré-visualização, e encaminhamento do upload para uma automação. - **Kind**: `view` - **Key**: `document` - **Categoria**: `ficheiros` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `documentColumnId` | `uuid` | não | - | Coluna de ficheiro que a vista explora. Sem ela a vista não tem nada para mostrar. | coluna (uuid) | | `displayMode` | `enumeration` | não | `"list"` | Como os ficheiros se arrumam: lista, grelha ou largura inteira. | - | | `itemsPerRow` | `integer` | não | `3` | Quantos ficheiros por linha no modo de grelha. | - | | `showFileSize` | `boolean` | não | `true` | Mostra o tamanho do ficheiro. | - | | `showUploadDate` | `boolean` | não | `true` | Mostra a data do carregamento. | - | | `showUploadedBy` | `boolean` | não | `false` | Mostra quem carregou o ficheiro. | - | | `enablePreview` | `boolean` | não | `true` | Deixa pré-visualizar o ficheiro sem o descarregar. | - | | `enableDownload` | `boolean` | não | `true` | Deixa descarregar o ficheiro. | - | | `enableDelete` | `boolean` | não | `false` | Deixa apagar o ficheiro. | - | | `sortBy` | `enumeration` | não | `"date"` | Por que atributo do ficheiro se ordena. | - | | `sortAscending` | `boolean` | não | `false` | Ordem crescente; por omissão mostra os mais recentes primeiro. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtro de base no formato legado: nome da coluna → valor escolhido (operador `equals`). Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `allowedExtensions` | `list` de `string` | não | `[]` | Extensões admitidas no carregamento; vazio = todas. Valores, não referências. | - | | `titleColumnId` | `uuid` | não | - | Coluna que dá o título do cartão. | coluna (uuid) | | `subtitleColumnId` | `uuid` | não | - | Coluna que dá o subtítulo do cartão. | coluna (uuid) | | `additionalColumnIds` | `list` de `string` | não | `[]` | Colunas extra mostradas no cabeçalho de cada ficheiro. | - | | `groupingColumnIds` | `list` de `string` | não | `[]` | Até três colunas que formam a árvore da esquerda, por ordem; vazio = descoberta automática. | - | | `groupingColumnId` | `uuid` | não | - | **Descontinuado.** Nome antigo, de uma só coluna, do groupingColumnIds; ainda lido, já não escrito pela app. | coluna (uuid) | | `aiWorkflowId` | `uuid` | não | - | Automação da primeira geração (com uma ação de ingestão por IA) que os botões "Processar com AI" correm; nula esconde-os. | workflow (uuid) | | `workflowV2Id` | `uuid` | não | - | Automação WorkflowV2 para onde o carregamento encaminha os ficheiros (gatilho `file.upload`); nula = só a linha nova. | workflow V2 (uuid) | | `uploadPathColumnId` | `uuid` | não | - | Coluna de texto onde o carregamento carimba o caminho do ficheiro. É a chave que deixa a automação PREENCHER a linha criada pelo upload em vez de criar uma segunda. | coluna (uuid) | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "displayMode": "list", "itemsPerRow": 3, "showFileSize": true, "showUploadDate": true, "showUploadedBy": false, "enablePreview": true, "enableDownload": true, "enableDelete": false, "sortBy": "date", "sortAscending": false, "allowedExtensions": [], "additionalColumnIds": [], "groupingColumnIds": [] } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # form **Formulário** Um registo de cada vez, com os campos dispostos em secções, linhas e abas. - **Kind**: `view` - **Key**: `form` - **Categoria**: `formulário` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `tabs` | `list` de `map` | não | `[]` | Abas do formulário; vazio dá um formulário de uma só. | - | | `sections` | `list` de `map` | não | `[]` | Secções do formulário quando não há abas. | - | | `hiddenFields` | `list` de `string` | não | - | Colunas escondidas do formulário, POR NOME. | - | | `toolbar` | `map` | não | - | Barra de ações do formulário. | - | | `fieldOverrides` | `map` | não | - | Nome da coluna na chave → o que se sobrepõe ao componente dela neste formulário. A referência à coluna está na chave do mapa, não no valor. | chave: coluna (nome) | | `wizardMode` | `boolean` | não | - | Percorre as abas como um assistente, uma a uma; só sai no JSON quando é verdadeiro. | - | | `builderMode` | `enumeration` | não | - | Modo em que o construtor do formulário abre: `auto` dispõe os campos sozinho, `advanced` respeita o layout guardado. | - | | `rightPanel` | `map` | não | - | Painel de contexto à direita, para um componente pesado (`document`, `linked_view`, `description`, `checklist`). | - | | `bottomPanel` | `map` | não | - | Painel de contexto em baixo, com a mesma forma do da direita. | - | ### `tabs[]` Cada elemento de `tabs` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `label` | `string` | sim | - | Título da aba (omissão de leitura: "Tab"). | - | | `sections` | `list` de `map` | não | `[]` | Secções desta aba, com a forma das de topo. | - | ### `tabs[].sections[]` Cada elemento de `tabs[].sections` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `type` | `string` | sim | - | Tipo da secção: `section`, `row` (linha de colunas), `toolbar_section` ou `special_section`. | - | | `label` | `string` | não | - | Título da secção; sai no JSON mesmo quando é nulo. | - | | `fields` | `list` de `string` | não | - | Colunas desenhadas nesta secção, POR NOME. | - | | `children` | `list` | não | - | Secções encaixadas, com a MESMA forma desta. O layout do formulário é recursivo e uma FieldDecl const não se pode referir a si própria: os níveis abaixo do primeiro varrem-se às cegas (só uuids). Como os campos são NOMES de coluna, não há uuid morto a escapar - o que se perde é a contagem exacta das referências por nome em secções encaixadas. | - | | `columns` | `integer` | não | `2` | Número de colunas da linha; só sai no JSON quando o type é `row`. | - | | `visibility` | `map` | não | - | Nome do campo governado na chave → regra que decide se ele aparece. A chave do mapa é uma coluna, POR NOME. | - | | `collapsedByDefault` | `boolean` | não | - | Abre fechada; só sai no JSON quando é verdadeiro. | - | | `rowLeftFraction` | `number` | não | - | Fração da largura dada à coluna esquerda da linha, de 0 a 1. | - | ### `tabs[].sections[].visibility{}` Cada entrada de `tabs[].sections[].visibility` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `dependsOn` | `string` | sim | - | Coluna de que a visibilidade depende, POR NOME. | coluna (nome) | | `operator` | `string` | sim | - | Comparação aplicada ao valor dessa coluna. | - | | `value` | `string` | não | - | Valor comparado: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `action` | `enumeration` | sim | - | O que fazer ao campo quando a condição se verifica. | - | | `rules` | `list` de `map` | não | - | A forma de VÁRIAS condições: o toJson escreve a condição sozinha quando é uma só e este `rules` quando são mais. | - | ### `tabs[].sections[].visibility{}.rules[]` Cada elemento de `tabs[].sections[].visibility{}.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `dependsOn` | `string` | sim | - | Coluna de que a visibilidade depende, POR NOME. | coluna (nome) | | `operator` | `string` | sim | - | Comparação aplicada ao valor dessa coluna. | - | | `value` | `string` | não | - | Valor comparado: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `action` | `enumeration` | sim | - | O que fazer ao campo quando a condição se verifica. | - | | `combineWithPrev` | `enumeration` | não | `"and"` | Como se junta à condição anterior do conjunto. | - | ### `sections[]` Cada elemento de `sections` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `type` | `string` | sim | - | Tipo da secção: `section`, `row` (linha de colunas), `toolbar_section` ou `special_section`. | - | | `label` | `string` | não | - | Título da secção; sai no JSON mesmo quando é nulo. | - | | `fields` | `list` de `string` | não | - | Colunas desenhadas nesta secção, POR NOME. | - | | `children` | `list` | não | - | Secções encaixadas, com a MESMA forma desta. O layout do formulário é recursivo e uma FieldDecl const não se pode referir a si própria: os níveis abaixo do primeiro varrem-se às cegas (só uuids). Como os campos são NOMES de coluna, não há uuid morto a escapar - o que se perde é a contagem exacta das referências por nome em secções encaixadas. | - | | `columns` | `integer` | não | `2` | Número de colunas da linha; só sai no JSON quando o type é `row`. | - | | `visibility` | `map` | não | - | Nome do campo governado na chave → regra que decide se ele aparece. A chave do mapa é uma coluna, POR NOME. | - | | `collapsedByDefault` | `boolean` | não | - | Abre fechada; só sai no JSON quando é verdadeiro. | - | | `rowLeftFraction` | `number` | não | - | Fração da largura dada à coluna esquerda da linha, de 0 a 1. | - | ### `sections[].visibility{}` Cada entrada de `sections[].visibility` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `dependsOn` | `string` | sim | - | Coluna de que a visibilidade depende, POR NOME. | coluna (nome) | | `operator` | `string` | sim | - | Comparação aplicada ao valor dessa coluna. | - | | `value` | `string` | não | - | Valor comparado: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `action` | `enumeration` | sim | - | O que fazer ao campo quando a condição se verifica. | - | | `rules` | `list` de `map` | não | - | A forma de VÁRIAS condições: o toJson escreve a condição sozinha quando é uma só e este `rules` quando são mais. | - | ### `sections[].visibility{}.rules[]` Cada elemento de `sections[].visibility{}.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `dependsOn` | `string` | sim | - | Coluna de que a visibilidade depende, POR NOME. | coluna (nome) | | `operator` | `string` | sim | - | Comparação aplicada ao valor dessa coluna. | - | | `value` | `string` | não | - | Valor comparado: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `action` | `enumeration` | sim | - | O que fazer ao campo quando a condição se verifica. | - | | `combineWithPrev` | `enumeration` | não | `"and"` | Como se junta à condição anterior do conjunto. | - | ### `toolbar` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `items` | `list` de `string` | não | - | Colunas (tipicamente componentes de ação) postas na barra. | - | | `label` | `string` | não | - | Título da barra, quando tem. | - | ### `fieldOverrides{}` Cada entrada de `fieldOverrides` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `widthCode` | `string` | não | - | Largura do campo no formulário, no vocabulário do construtor (`quarter`, `third`, `half`, `twoThirds`, `full`). | - | | `helpText` | `string` | não | - | Texto de ajuda mostrado sob o campo. | - | | `requiredOverride` | `boolean` | não | - | Torna o campo obrigatório (ou não) só neste formulário. | - | | `defaultValueOverride` | `string` | não | - | Valor inicial do campo neste formulário: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `rowLeftFraction` | `number` | não | - | Fração da largura dada a este campo quando está numa linha de dois. | - | ### `rightPanel` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `fieldName` | `string` | sim | - | Coluna desenhada dentro do painel, POR NOME. | coluna (nome) | | `defaultVisible` | `boolean` | não | `true` | Se o painel abre visível. | - | | `defaultSize` | `number` | não | - | Tamanho inicial do painel, em pixels. | - | | `minSize` | `number` | não | - | Tamanho mínimo, em pixels, abaixo do qual o painel fecha; nulo usa o mínimo do próprio layout. | - | | `maxRatio` | `number` | não | - | Tamanho máximo como fração do espaço disponível, de 0 a 1; nulo usa o máximo do próprio layout. | - | ### `bottomPanel` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `fieldName` | `string` | sim | - | Coluna desenhada dentro do painel, POR NOME. | coluna (nome) | | `defaultVisible` | `boolean` | não | `true` | Se o painel abre visível. | - | | `defaultSize` | `number` | não | - | Tamanho inicial do painel, em pixels. | - | | `minSize` | `number` | não | - | Tamanho mínimo, em pixels, abaixo do qual o painel fecha; nulo usa o mínimo do próprio layout. | - | | `maxRatio` | `number` | não | - | Tamanho máximo como fração do espaço disponível, de 0 a 1; nulo usa o máximo do próprio layout. | - | ## Exemplo JSON ```json [ { "tabs": [], "sections": [] } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # gantt **Cronograma** Barras temporais por registo num cronograma com zoom. - **Kind**: `view` - **Key**: `gantt` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `startDateField` | `string` | não | - | Coluna da data de início da barra. | coluna (nome) | | `endDateField` | `string` | não | - | Coluna da data de fim da barra. | coluna (nome) | | `titleField` | `string` | não | - | Coluna da etiqueta da barra. | coluna (nome) | | `progressField` | `string` | não | - | Coluna numérica lida de 0 a 100 para o enchimento da barra. | coluna (nome) | | `dependencyField` | `string` | não | - | Coluna `linked_select` para a PRÓPRIA feature cujos valores são os registos predecessores; desenha as setas de dependência. | coluna (nome) | | `groupBy` | `string` | não | - | Coluna de agrupamento em faixas. | coluna (nome) | | `defaultZoom` | `enumeration` | não | `"week"` | Zoom em que o cronograma abre; o zoom ativo do utilizador é uma sobreposição, não parte desta config. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordena, por ordem. | - | | `sortDirections` | `map` | não | - | Nome da coluna → sentido da ordenação. | chave: coluna (nome) | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `showSearchButton` | `boolean` | não | `true` | Mostra o botão de pesquisa. | - | | `showFilterButton` | `boolean` | não | `true` | Mostra o botão de filtros. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "defaultZoom": "week", "allowAdd": true, "showSearchButton": true, "showFilterButton": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # kanban **Kanban** Cartões em colunas por estado, movidos por arrastar. - **Kind**: `view` - **Key**: `kanban` - **Categoria**: `quadro` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `groupBy` | `string` | não | - | Coluna cujos valores fazem as colunas do quadro. | coluna (nome) | | `swimlaneBy` | `string` | não | - | Segundo eixo: coluna cujos valores fazem as faixas horizontais. Vazio dá o quadro clássico de um só eixo. | coluna (nome) | | `groupType` | `enumeration` | não | `"field"` | Se as colunas saem dos valores de uma coluna (`field`) ou dos dias da semana (`weekdays`). | - | | `dateField` | `string` | não | - | Coluna de data que posiciona o cartão quando o agrupamento é por dias da semana. | coluna (nome) | | `weekRange` | `enumeration` | não | `"both"` | Semanas mostradas no agrupamento por dias da semana; `custom` usa customStartDate/customEndDate. | - | | `customStartDate` | `string` | não | - | Início do intervalo quando weekRange é `custom`, em ISO-8601 (o modelo escreve `toIso8601String()`). | - | | `customEndDate` | `string` | não | - | Fim do intervalo quando weekRange é `custom`, em ISO-8601. | - | | `collapsedGroups` | `list` | não | `[]` | Grupos fechados, pelos VALORES da coluna de agrupamento: dado de utilizador, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `groupOrder` | `list` | não | `[]` | Ordem manual das colunas do quadro, pelos VALORES da coluna de agrupamento. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `swimlaneOrder` | `list` | não | `[]` | Ordem manual das faixas, pelos VALORES da coluna de swimlaneBy; vazio ordena por alfabeto. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `hideEmptyGroups` | `boolean` | não | `false` | Esconde as colunas sem cartões. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtros no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado: nome da coluna → operador. Só lido, a par de filters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `displayFields` | `list` de `string` | não | - | Colunas desenhadas dentro do cartão. | - | | `predefinedFilters` | `list` | não | - | Filtros guardados no formato legado (mapas por chave de coluna com valores escolhidos): dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordenam os cartões dentro de cada coluna do quadro, por ordem. | - | | `sortWithinGroups` | `string` | não | - | **Descontinuado.** Nome antigo, de uma só coluna e sem sentido, do sortedColumns; ainda lido, já não escrito pela app. | coluna (nome) | | `sortDirections` | `map` | não | - | Nome da coluna → sentido da ordenação. | chave: coluna (nome) | | `columnSize` | `enumeration` | não | `"m"` | Largura das colunas do quadro; resolve-se em pixels por `kanbanColumnWidthFor`. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `allowSelection` | `boolean` | não | `true` | Permite selecionar cartões. | - | | `showSearchButton` | `boolean` | não | `true` | Mostra o botão de pesquisa. | - | | `showFilterButton` | `boolean` | não | `true` | Mostra o botão de filtros. | - | | `showGroupButton` | `boolean` | não | `true` | Mostra o botão de agrupamento. | - | | `showExportButton` | `boolean` | não | `true` | Mostra o botão de exportação. | - | | `showCollapseButton` | `boolean` | não | `true` | Mostra o botão de fechar as colunas. | - | | `facetPanelState` | `json` | não | - | Estado do painel de filtros facetados, por utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "groupType": "field", "weekRange": "both", "collapsedGroups": [], "groupOrder": [], "swimlaneOrder": [], "hideEmptyGroups": false, "columnSize": "m", "allowAdd": true, "allowSelection": true, "showSearchButton": true, "showFilterButton": true, "showGroupButton": true, "showExportButton": true, "showCollapseButton": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # kiosk **Kiosk** Balcão para operação rápida por subutilizadores: login de operador, separadores com vistas embebidas, botões de automação e marcação de turno. - **Kind**: `view` - **Key**: `kiosk` - **Categoria**: `balcão` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `tabs` | `list` de `map` | não | `[]` | Os separadores do balcão. Um separador malformado é descartado na leitura, nunca derruba os outros. | - | | `actions` | `list` de `map` | não | `[]` | Botões de automação da barra lateral, por baixo dos separadores. Só sai no JSON quando não está vazia. | - | | `operatorLoginEnabled` | `boolean` | não | `true` | Exige login de operador (cartão + PIN) antes de mostrar conteúdo. Ligado por omissão, também em configs antigas sem a chave: desligá-lo é uma escolha explícita. | - | | `loginGroupIds` | `list` | não | `[]` | Grupos de subutilizadores visíveis no ecrã de login; vazio = todos. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `shiftFeatureId` | `uuid` | não | - | Feature onde as marcações de turno são gravadas. | feature (uuid) | | `shiftTypeColumnId` | `uuid` | não | - | Coluna da feature de turnos que diz o tipo de marcação (entrada, saída, pausa). | coluna de `shiftFeatureId` (uuid) | | `shiftWorkflowId` | `uuid` | não | - | Automação da primeira geração que o botão de turno corre. | workflow (uuid) | | `timerProfileId` | `uuid` | não | - | Perfil de temporizador que a barra de cima arranca e para para o operador da sessão. | perfil de timer (uuid) | | `layoutMode` | `enumeration` | não | `"tabsOnly"` | Onde vive a navegação: só nos separadores de cima, só na barra lateral, ou nos dois (em retrato estreito a barra recolhe). | - | | `workflowDockGraceSeconds` | `integer` | não | - | Segundos que o painel de automações fica visível depois da última execução; nulo vale 5. | - | | `autoLockSeconds` | `integer` | não | - | Segundos de inactividade até a sessão de UI do operador terminar sozinha; nulo vale 300, zero ou negativo nunca bloqueia. | - | | `allowOperatorVoidOwnPunch` | `boolean` | não | `false` | Deixa o operador anular as SUAS marcações de turno no histórico. Desligado por omissão: editar a própria assiduidade é escolha explícita do admin. | - | ### `tabs[]` Cada elemento de `tabs` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | sim | - | Identificador do separador, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `label` | `string` | sim | - | Nome do separador, mostrado na barra. | - | | `icon` | `string` | não | - | Nome semântico do ícone, resolvido por `kioskTabIcon`. Só sai no JSON quando não é nulo. | - | | `feature_id` | `uuid` | não | - | Feature que o separador mostra; nulo = a feature do próprio kiosk. | feature (uuid) | | `view_type` | `enumeration` | não | `"cards"` | Tipo de vista embebida. Qualquer tipo registado menos o kiosk: um kiosk dentro de um kiosk é proibido. | - | | `view_name` | `string` | não | - | Variante nomeada da vista embebida (nulo = a por omissão). O par que a identifica é `feature_id` + `view_type` + este nome. | vista de `feature_id` (nome) | | `dynamic_filters` | `map` | não | `{}` | Filtros passados à vista embebida: id de coluna → valor (mais a chave reservada `__rowIds`). | chave: coluna de `feature_id` (uuid) | ### `actions[]` Cada elemento de `actions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `label` | `string` | sim | - | Texto do botão. | - | | `workflow_id` | `uuid` | sim | - | Automação da primeira geração que o botão corre. | workflow (uuid) | | `icon` | `string` | não | - | Nome semântico do ícone do botão. | - | ## Exemplo JSON ```json [ { "tabs": [], "actions": [], "operatorLoginEnabled": true, "loginGroupIds": [], "layoutMode": "tabsOnly", "allowOperatorVoidOwnPunch": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # list **Lista** Linhas numa lista compacta, com imagem, títulos, data e caixa de verificação escolhidos coluna a coluna. - **Kind**: `view` - **Key**: `list` - **Categoria**: `grelha` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `hiddenColumns` | `list` de `string` | não | - | Colunas escondidas. | - | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordena, por ordem. | - | | `sortDirections` | `map` | não | - | Nome da coluna → sentido da ordenação. | chave: coluna (nome) | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtros no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado: nome da coluna → operador. Só lido, a par de filters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `groupedColumns` | `list` de `string` | não | - | Colunas por que se agrupa. | - | | `groupBy` | `string` | não | - | Primeira coluna de groupedColumns, escrita também à parte para quem só lê um nível de agrupamento. | coluna (nome) | | `showImage` | `boolean` | não | `false` | Mostra a imagem à esquerda. | - | | `imageColumn` | `string` | não | - | Coluna de onde sai a imagem. | coluna (nome) | | `showTitle` | `boolean` | não | `true` | Mostra o título. | - | | `titleColumn` | `string` | não | - | Coluna do título. | coluna (nome) | | `showSubtitle` | `boolean` | não | `true` | Mostra o subtítulo. | - | | `subtitleColumn` | `string` | não | - | Coluna do subtítulo. | coluna (nome) | | `showThirdTitle` | `boolean` | não | `false` | Mostra a terceira linha de texto. | - | | `thirdTitleColumn` | `string` | não | - | Coluna da terceira linha de texto. | coluna (nome) | | `showDate` | `boolean` | não | `false` | Mostra a data. | - | | `dateColumn` | `string` | não | - | Coluna da data. | coluna (nome) | | `showCheckbox` | `boolean` | não | `false` | Mostra a caixa de verificação. | - | | `checkboxColumn` | `string` | não | - | Coluna da caixa de verificação. | coluna (nome) | | `showTrailing` | `boolean` | não | `false` | Mostra o valor ao fim da linha. | - | | `trailingColumn` | `string` | não | - | Coluna do valor ao fim da linha. | coluna (nome) | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `allowSelection` | `boolean` | não | `true` | Permite selecionar linhas. | - | | `showSearchButton` | `boolean` | não | `true` | Mostra o botão de pesquisa. | - | | `showFilterButton` | `boolean` | não | `true` | Mostra o botão de filtros. | - | | `showGroupButton` | `boolean` | não | `true` | Mostra o botão de agrupamento. | - | | `showExportButton` | `boolean` | não | `true` | Mostra o botão de exportação. | - | | `facetPanelState` | `json` | não | - | Estado do painel de filtros facetados, por utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "showImage": false, "showTitle": true, "showSubtitle": true, "showThirdTitle": false, "showDate": false, "showCheckbox": false, "showTrailing": false, "allowAdd": true, "allowSelection": true, "showSearchButton": true, "showFilterButton": true, "showGroupButton": true, "showExportButton": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # map **Mapa** Registos com coordenadas dispostos como marcadores num mapa. - **Kind**: `view` - **Key**: `map` - **Categoria**: `mapa` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `latField` | `string` | não | - | Coluna numérica da latitude, em [-90, 90]. | coluna (nome) | | `lngField` | `string` | não | - | Coluna numérica da longitude, em [-180, 180]. | coluna (nome) | | `titleField` | `string` | não | - | Coluna da etiqueta do marcador. | coluna (nome) | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | | `showSearchButton` | `boolean` | não | `false` | Mostra o botão de pesquisa. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "showSearchButton": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # monthly_timesheet **Folha de horas mensal** Folha de horas mensal (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). - **Kind**: `view` - **Key**: `monthly_timesheet` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `modes` | `list` de `enumeration` | não | `["daily","weekly","monthly","stats"]` | Separadores visíveis, por ordem. Um só = sem barra de separadores. Valores fora do conjunto são ignorados na leitura. | - | | `source` | `enumeration` | não | `"auto"` | De onde vêm os registos: a tabela Timer, as linhas da feature, ou `auto` (Timer quando a feature é a do temporizador). | - | | `columnMap` | `map` | não | `{}` | Que coluna desta feature transporta cada parte do registo. Só sai no JSON quando tem alguma parte preenchida, e só conta quando a fonte são as linhas da feature. | - | | `filterSourceFeatureId` | `uuid` | não | - | Restringe os registos aos que vêm desta feature de origem (compara com `TimerEntry.sourceFeatureId` na fonte Timer). | feature (uuid) | | `categoryFilter` | `string` | não | - | Restringe os registos a uma categoria: valor, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterUserId` | `uuid` | não | - | Restringe os registos a um utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterProfileId` | `uuid` | não | - | Perfil de temporizador pré-escolhido na entrada manual, e filtro dos registos desse perfil. | perfil de timer (uuid) | | `hoursPerDayTarget` | `number` | não | - | Horas-alvo por dia, usadas nas barras de progresso. | - | | `allowManualEntry` | `boolean` | não | `true` | Deixa lançar registos à mão. | - | | `showCategoryBreakdown` | `boolean` | não | `true` | No modo diário: mostra o detalhe por categoria. | - | | `groupByCategory` | `boolean` | não | `false` | No modo semanal: uma linha por categoria. | - | | `weekStartsOn` | `integer` | não | `1` | No modo semanal: dia em que a semana começa, de 1 a 7. | - | | `firstDayOfWeek` | `integer` | não | `1` | No modo mensal: dia em que a grelha começa, de 1 a 7. | - | | `showWeekTotals` | `boolean` | não | `true` | No modo mensal: mostra os totais por semana. | - | ### `columnMap` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `date` | `string` | não | - | Coluna da data do registo, POR NOME. | coluna (nome) | | `duration` | `string` | não | - | Coluna da duração em segundos, POR NOME. Ganha ao par início/fim quando está preenchida. | coluna (nome) | | `startedAt` | `string` | não | - | Coluna do início, POR NOME. | coluna (nome) | | `endedAt` | `string` | não | - | Coluna do fim, POR NOME. | coluna (nome) | | `label` | `string` | não | - | Coluna da descrição do registo, POR NOME. | coluna (nome) | | `category` | `string` | não | - | Coluna da categoria, POR NOME. | coluna (nome) | | `userId` | `string` | não | - | Coluna do utilizador a quem o registo pertence, POR NOME. | coluna (nome) | | `notes` | `string` | não | - | Coluna das notas, POR NOME. | coluna (nome) | ## Exemplo JSON ```json [ { "modes": [ "daily", "weekly", "monthly", "stats" ], "source": "auto", "columnMap": {}, "allowManualEntry": true, "showCategoryBreakdown": true, "groupByCategory": false, "weekStartsOn": 1, "firstDayOfWeek": 1, "showWeekTotals": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # pivot **Tabela dinâmica** Linhas agregadas em prateleiras de linhas, colunas e valores, com totais e percentagens. - **Kind**: `view` - **Key**: `pivot` - **Categoria**: `análise` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `hiddenColumns` | `list` de `string` | não | - | Colunas escondidas. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtros no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado: nome da coluna → operador. Só lido, a par de filters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `dynamicFilters` | `map` | não | - | Filtros aplicados em execução, com o UUID da coluna na chave; entradas combinadas por E, e uma chave órfã esconde tudo (falha fechada). | chave: coluna (uuid) | | `predefinedFilters` | `list` | não | - | Filtros guardados no formato legado (mapas por chave de coluna com valores escolhidos): dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordena, por ordem. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `footerSumColumns` | `list` de `string` | não | - | Colunas somadas no rodapé. | - | | `rowFields` | `list` de `map` | não | - | Colunas que fazem as LINHAS da tabela dinâmica, por ordem. | - | | `columnFields` | `list` de `map` | não | - | Colunas que fazem as COLUNAS da tabela dinâmica, por ordem. | - | | `valueFields` | `list` de `map` | não | - | Colunas agregadas nas células. | - | | `showTotals` | `boolean` | não | `true` | Mostra os subtotais de cada grupo. | - | | `showGrandTotal` | `boolean` | não | `true` | Mostra o total geral. | - | | `showPercentages` | `boolean` | não | `false` | Mostra cada valor também em percentagem do total. | - | | `sortRows` | `enumeration` | não | `"asc"` | Sentido da ordenação das linhas. | - | | `sortColumns` | `enumeration` | não | `"asc"` | Sentido da ordenação das colunas. | - | | `defaultExpandedLevel` | `integer` | não | - | Profundidade aberta por omissão: nulo fecha tudo, 0 deixa só o total geral, N abre até ao nível N e 999 abre tudo. | - | | `title` | `string` | não | - | Título mostrado acima da tabela. | - | | `allowUserShelves` | `boolean` | não | `true` | Deixa o utilizador mexer nas prateleiras em execução. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `rowFields[]` Cada elemento de `rowFields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureColumnId` | `uuid` | sim | - | Coluna desta tabela, por UUID (o pivot é a única vista que refere colunas por identificador). | coluna (uuid) | | `label` | `string` | não | - | Rótulo mostrado na prateleira. | - | | `order` | `integer` | não | `0` | Posição na prateleira. | - | | `dateGranularity` | `enumeration` | não | - | Granularidade, quando a coluna é de data. | - | | `dateGroupType` | `string` | não | - | **Descontinuado.** Nome antigo do dateGranularity, ainda lido como recurso; aceita também `normal`, que vale por "sem granularidade". | - | ### `columnFields[]` Cada elemento de `columnFields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureColumnId` | `uuid` | sim | - | Coluna desta tabela, por UUID (o pivot é a única vista que refere colunas por identificador). | coluna (uuid) | | `label` | `string` | não | - | Rótulo mostrado na prateleira. | - | | `order` | `integer` | não | `0` | Posição na prateleira. | - | | `dateGranularity` | `enumeration` | não | - | Granularidade, quando a coluna é de data. | - | | `dateGroupType` | `string` | não | - | **Descontinuado.** Nome antigo do dateGranularity, ainda lido como recurso; aceita também `normal`, que vale por "sem granularidade". | - | ### `valueFields[]` Cada elemento de `valueFields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureColumnId` | `uuid` | sim | - | Coluna desta tabela, por UUID (o pivot é a única vista que refere colunas por identificador). | coluna (uuid) | | `label` | `string` | não | - | Rótulo mostrado na prateleira. | - | | `aggregation` | `enumeration` | sim | - | Operação aplicada aos valores. | - | | `format` | `enumeration` | não | `"number"` | Formato de apresentação do resultado. | - | ## Exemplo JSON ```json [ { "allowAdd": true, "showTotals": true, "showGrandTotal": true, "showPercentages": false, "sortRows": "asc", "sortColumns": "asc", "allowUserShelves": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # record **Record** Mestre-detalhe: à esquerda um seletor de linhas desta feature, à direita a vista de detalhe que a linha escolhida filtra. - **Kind**: `view` - **Key**: `record` - **Categoria**: `painel` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `selectorColumns` | `list` de `string` | não | `[]` | Colunas mostradas no seletor, por ID; vazio = todas as visíveis. A ordem guardada nunca foi honrada (o runtime usa a ordem das colunas da feature). | - | | `selectorFilterGroup` | `map` | não | - | Filtro de base das linhas do seletor. | - | | `selectorFilters` | `json` | não | - | **Descontinuado.** Filtro do seletor no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há selectorFilterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `selectorFilterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado do seletor: nome da coluna → operador. Só lido, a par de selectorFilters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `selectorSortColumn` | `string` | não | - | Coluna por que o seletor ordena, POR NOME. O utilizador pode trocá-la em runtime (fica nas suas preferências, não aqui). | coluna (nome) | | `selectorSortAscending` | `boolean` | não | `true` | Ordem crescente no seletor. | - | | `showSearch` | `boolean` | não | `true` | Mostra a caixa de pesquisa do seletor. | - | | `selectorMode` | `enumeration` | não | `"list"` | Como o seletor se desenha: lista ou colunas. | - | | `selectorGroupByColumn` | `string` | não | - | Coluna por que o seletor agrupa, POR NOME; nula = lista plana. | coluna (nome) | | `detailFeatureId` | `uuid` | não | - | Feature da vista de detalhe; nula = a feature desta vista. | feature (uuid) | | `detailViewType` | `enumeration` | não | - | Tipo da vista de detalhe; nulo = o painel da direita fica vazio. | - | | `detailViewName` | `string` | não | - | Variante nomeada da vista de detalhe (nula = a por omissão). | vista de `detailFeatureId` (nome) | | `detailFilterColumnId` | `uuid` | não | - | Coluna da feature de detalhe que o valor da linha escolhida filtra. | coluna de `detailFeatureId` (uuid) | | `sourceValueColumnId` | `uuid` | não | - | Coluna desta feature de onde sai o valor passado ao detalhe; nula usa o id da linha. | coluna (uuid) | | `selectorWidthRatio` | `number` | não | `0.3` | Fração da largura que o seletor ocupa. O utilizador pode arrastá-la (fica nas suas preferências). | - | ### `selectorFilterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `selectorFilterGroup.rules[]` Cada elemento de `selectorFilterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `selectorFilterGroup.groups[]` Cada elemento de `selectorFilterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `selectorFilterGroup.groups[].rules[]` Cada elemento de `selectorFilterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "selectorColumns": [], "selectorSortAscending": true, "showSearch": true, "selectorMode": "list", "selectorWidthRatio": 0.3 } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # report **Report** Relatório autónomo: um documento HTML escrito pela IA (ou um template de PDF) desenhado sobre dados ao vivo, sem rede. - **Kind**: `view` - **Key**: `report` - **Categoria**: `relatório` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"html"` | HTML autónomo numa webview isolada, ou PDF desenhado pelo motor de relatórios a partir do template. | - | | `scope` | `enumeration` | não | `"collection"` | O relatório é do conjunto de linhas, ou de UMA linha (que fica disponível como `current`). | - | | `title` | `string` | não | `""` | Título do relatório. | - | | `artifact` | `string` | não | `""` | O documento HTML autónomo (CSS e JS embutidos, sem rede), com os tokens que o runtime substitui ao abrir. | expressões `{{record.coluna}}` | | `emailBody` | `string` | não | - | Variante estática para email (CSS embutido, sem JS). A app escreve-a a partir do rascunho da IA, mas nenhum consumidor a lê. | expressões `{{record.coluna}}` | | `dataContract` | `map` | não | `{}` | Que dados do OutDo são injetados a cada abertura: uma consulta por conjunto de linhas, mais as variáveis. | - | | `template` | `json` | não | - | O JSON do template de PDF (página, cabeçalho, corpo, rodapé e blocos) quando o tipo é `native`. | expressões `{{record.coluna}}` | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `facetPanelState` | `json` | não | - | Estado do painel de filtros facetados, por utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `dataContract` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `queries` | `list` de `map` | não | `[]` | As consultas, uma por chave de dados. | - | | `variables` | `json` | não | `{}` | Variáveis passadas ao documento: nome → valor. Dados de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `dataContract.queries[]` Cada elemento de `dataContract.queries` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `name` | `string` | sim | - | Chave sob a qual as linhas aparecem no documento. | - | | `feature` | `string` | sim | - | Feature de onde saem as linhas: id, nome, ou a referência simbólica que a IA escreve. | feature (uuid ou nome) | | `columns` | `list` de `string` | não | `[]` | Colunas trazidas, POR NOME; vazio = todas. Só sai no JSON quando não está vazia. | - | | `filter` | `list` de `string` | não | `[]` | Filtros de linha na forma `campo:operador:valor` (a mesma sintaxe das ferramentas de leitura da IA). | - | | `limit` | `integer` | não | - | Máximo de linhas trazidas. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "kind": "html", "scope": "collection", "title": "", "artifact": "", "dataContract": {} } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # sidebyside **Lado a lado** Duas features lado a lado para comparar, conciliar e passar linhas de um lado para o outro. - **Kind**: `view` - **Key**: `sidebyside` - **Categoria**: `comparação` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `compareFeatureId` | `uuid` | não | - | A OUTRA feature, a do lado de comparação. É o campo que dá sentido a todos os `compare*`: sem ele a vista só mostra um lado. | feature (uuid) | | `compareFields` | `list` de `string` | não | - | Forma ANTIGA da correspondência: colunas comparadas por semelhança de texto quando não há compareMappings. O nome tem de existir nos DOIS lados (o scorer lê-o em cada linha com a mesma chave), por isso conta-se do lado de comparação. | - | | `invertSides` | `boolean` | não | `false` | Troca os lados: o primário passa para a direita. | - | | `primaryLinkColumn` | `string` | não | - | Coluna desta feature onde se guarda a ligação à linha do outro lado, POR NOME. | coluna (nome) | | `compareLinkColumn` | `string` | não | - | Coluna da feature de comparação onde se guarda a ligação à linha deste lado, POR NOME. | coluna de `compareFeatureId` (nome) | | `primaryIdColumn` | `string` | não | - | Coluna desta feature que leva o identificador de domínio usado na conciliação, POR NOME. | coluna (nome) | | `compareIdColumn` | `string` | não | - | Coluna da feature de comparação que leva o identificador de domínio, POR NOME. | coluna de `compareFeatureId` (nome) | | `compareMappings` | `list` de `map` | não | `[]` | A correspondência a sério: pares de colunas, um de cada lado, com método e peso. | - | | `minSimilarityScore` | `number` | não | - | Pontuação mínima, de 0 a 1, para uma linha do outro lado aparecer como candidata. | - | | `primaryFilterGroup` | `map` | não | - | Filtro de base do lado primário, aplicado logo que a vista abre. | - | | `defaultPrimaryFilters` | `json` | não | - | **Descontinuado.** Filtro de base do lado primário no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há primaryFilterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `defaultPrimaryFilterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado do lado primário: nome da coluna → operador. Só lido, a par de defaultPrimaryFilters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `compareFilterGroup` | `map` | não | - | Filtro de base do lado de comparação. As regras referem colunas da OUTRA feature. | - | | `defaultCompareFilters` | `json` | não | - | **Descontinuado.** Filtro de base do lado de comparação no formato legado: nome da coluna DESSA feature → valor escolhido. Só lido, e só quando não há compareFilterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `defaultCompareFilterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado do lado de comparação: nome da coluna dessa feature → operador. Só lido, a par de defaultCompareFilters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `formFieldMapping` | `map` | não | `{}` | Correspondência usada ao criar a linha do outro lado: na chave o nome da coluna DESTA feature, no valor o nome da coluna da feature de COMPARAÇÃO. | chave: coluna (nome) | | `compareDefaults` | `map` | não | `{}` | Valores fixos escritos na linha criada do lado de comparação: na chave o nome da coluna DESSA feature, no valor a constante. | chave: coluna de `compareFeatureId` (nome) | | `hiddenPrimaryColumns` | `list` de `string` | não | - | Colunas escondidas do lado primário, POR NOME. | - | | `hiddenCompareColumns` | `list` de `string` | não | - | Colunas escondidas do lado de comparação, POR NOME. | - | | `primaryColorConditions` | `list` de `map` | não | `[]` | Regras que pintam as linhas do lado primário. | - | | `compareColorConditions` | `list` de `map` | não | `[]` | Regras que pintam as linhas do lado de comparação. | - | | `sharedFacets` | `list` de `map` | não | `[]` | Facetas emparelhadas: uma escolha no painel de cima filtra os dois lados, mesmo quando a coluna tem nomes diferentes em cada feature. | - | | `markTransferred` | `boolean` | não | `false` | Pinta as linhas de origem que já existem no destino (inerte sem colunas de ligação configuradas). | - | | `preventDuplicates` | `boolean` | não | `false` | Impede passar uma linha que já exista no destino: a seta de passagem desliga-se. | - | | `transferFixedValues` | `list` de `map` | não | `[]` | Constantes gravadas na linha de destino quando se passa uma linha; ganham a qualquer colisão com os campos copiados. | - | | `defaultColumnWidth` | `number` | não | - | Largura inicial das colunas das duas tabelas, em pixels; nulo usa a largura de cada componente. | - | | `allowMultiSelection` | `boolean` | não | `false` | Deixa escolher várias linhas de cada vez. | - | ### `compareMappings[]` Cada elemento de `compareMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `primaryField` | `string` | sim | - | Coluna DESTA feature, POR NOME. | coluna (nome) | | `compareField` | `string` | sim | - | Coluna da feature de COMPARAÇÃO, POR NOME. | coluna de `compareFeatureId` (nome) | | `method` | `enumeration` | não | `"equals"` | Como se compara o valor das duas colunas. | - | | `weight` | `number` | não | `1` | Peso deste par na pontuação final, de 0 a 1 (o scorer limita a esse intervalo). | - | | `tolerance` | `number` | não | - | Diferença tolerada: o valor nos métodos numéricos, os dias no `dateDaysTolerance`. | - | ### `primaryFilterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `primaryFilterGroup.rules[]` Cada elemento de `primaryFilterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `primaryFilterGroup.groups[]` Cada elemento de `primaryFilterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `primaryFilterGroup.groups[].rules[]` Cada elemento de `primaryFilterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `compareFilterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `compareFilterGroup.rules[]` Cada elemento de `compareFilterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature de comparação, POR NOME. | coluna de `compareFeatureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `compareFilterGroup.groups[]` Cada elemento de `compareFilterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `compareFilterGroup.groups[].rules[]` Cada elemento de `compareFilterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da feature de comparação, POR NOME. | coluna de `compareFeatureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `primaryColorConditions[]` Cada elemento de `primaryColorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | sim | - | Coluna DESTA feature avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | sim | - | Operador da comparação: os sem valor (`isEmpty`, `isNotEmpty`) e os do descriptor da coluna (`equals`, `contains`, `between`, …). | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Limite de cima do `between`: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | sim | - | Cor aplicada à linha, em ARGB de 32 bits. | - | | `description` | `string` | não | - | Nota do administrador sobre a regra, mostrada na UI. | - | ### `compareColorConditions[]` Cada elemento de `compareColorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | sim | - | Coluna da feature de comparação avaliada, POR NOME. | coluna de `compareFeatureId` (nome) | | `operator` | `string` | sim | - | Operador da comparação: os sem valor (`isEmpty`, `isNotEmpty`) e os do descriptor da coluna (`equals`, `contains`, `between`, …). | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Limite de cima do `between`: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | sim | - | Cor aplicada à linha, em ARGB de 32 bits. | - | | `description` | `string` | não | - | Nota do administrador sobre a regra, mostrada na UI. | - | ### `sharedFacets[]` Cada elemento de `sharedFacets` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `primaryField` | `string` | sim | - | Coluna DESTA feature, POR NOME. | coluna (nome) | | `compareField` | `string` | sim | - | Coluna da feature de COMPARAÇÃO, POR NOME. | coluna de `compareFeatureId` (nome) | | `label` | `string` | sim | - | Título da faceta no painel. | - | | `iconName` | `string` | não | - | Nome do ícone mostrado a par do título. | - | ### `transferFixedValues[]` Cada elemento de `transferFixedValues` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumnName` | `string` | sim | - | Coluna da feature de COMPARAÇÃO que recebe a constante, POR NOME. | coluna de `compareFeatureId` (nome) | | `value` | `string` | não | - | A constante gravada: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "invertSides": false, "compareMappings": [], "formFieldMapping": {}, "compareDefaults": {}, "primaryColorConditions": [], "compareColorConditions": [], "sharedFacets": [], "markTransferred": false, "preventDuplicates": false, "transferFixedValues": [], "allowMultiSelection": false } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # table **Tabela** Grelha de linhas e colunas, com agrupamento, filtros, somas de rodapé e cores por regra. - **Kind**: `view` - **Key**: `table` - **Categoria**: `grelha` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `hiddenColumns` | `list` de `string` | não | - | Colunas escondidas. | - | | `sortedColumns` | `list` de `string` | não | - | Colunas por que se ordena, por ordem. | - | | `sortDirections` | `map` | não | - | Nome da coluna → sentido da ordenação. | chave: coluna (nome) | | `groupedColumns` | `list` de `string` | não | - | Colunas por que se agrupa. | - | | `inlineEditColumns` | `list` de `string` | não | - | Colunas editáveis directamente na grelha. | - | | `frozenColumns` | `list` de `string` | não | - | Colunas fixas à esquerda. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `filters` | `json` | não | - | **Descontinuado.** Filtros no formato legado: nome da coluna → valor escolhido. Só lido, e só quando não há filterGroup. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterTypes` | `json` | não | - | **Descontinuado.** Operadores do formato legado: nome da coluna → operador. Só lido, a par de filters. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `predefinedFilters` | `list` | não | - | Filtros guardados no formato legado (mapas por chave de coluna com valores escolhidos): dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `footerSumColumns` | `list` de `string` | não | - | Colunas somadas no rodapé. | - | | `allowAdd` | `boolean` | não | `true` | Permite acrescentar linhas. | - | | `allowSelection` | `boolean` | não | `true` | Permite selecionar linhas. | - | | `showActionColumn` | `boolean` | não | `true` | Mostra a coluna de ações da linha. | - | | `showSearchButton` | `boolean` | não | `true` | Mostra o botão de pesquisa. | - | | `showFilterButton` | `boolean` | não | `true` | Mostra o botão de filtros. | - | | `showGroupButton` | `boolean` | não | `true` | Mostra o botão de agrupamento. | - | | `showExportButton` | `boolean` | não | `true` | Mostra o botão de exportação. | - | | `showImportButton` | `boolean` | não | `true` | Mostra o botão de importação. | - | | `facetPanelState` | `json` | não | - | Estado do painel de filtros facetados, por utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `colorConditions` | `list` de `map` | não | - | Regras que pintam a linha segundo o valor de uma coluna. | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `colorConditions[]` Cada elemento de `colorConditions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columnName` | `string` | não | - | Coluna avaliada, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, nos operadores de intervalo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `integer` | não | - | Cor aplicada à linha, em ARGB de 32 bits. | - | ## Exemplo JSON ```json [ { "allowAdd": true, "allowSelection": true, "showActionColumn": true, "showSearchButton": true, "showFilterButton": true, "showGroupButton": true, "showExportButton": true, "showImportButton": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # timesheet **Folha de horas** Registo de horas por dia, semana ou mês. - **Kind**: `view` - **Key**: `timesheet` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `modes` | `list` de `enumeration` | não | `["daily","weekly","monthly","stats"]` | Separadores visíveis, por ordem. Um só = sem barra de separadores. Valores fora do conjunto são ignorados na leitura. | - | | `source` | `enumeration` | não | `"auto"` | De onde vêm os registos: a tabela Timer, as linhas da feature, ou `auto` (Timer quando a feature é a do temporizador). | - | | `columnMap` | `map` | não | `{}` | Que coluna desta feature transporta cada parte do registo. Só sai no JSON quando tem alguma parte preenchida, e só conta quando a fonte são as linhas da feature. | - | | `filterSourceFeatureId` | `uuid` | não | - | Restringe os registos aos que vêm desta feature de origem (compara com `TimerEntry.sourceFeatureId` na fonte Timer). | feature (uuid) | | `categoryFilter` | `string` | não | - | Restringe os registos a uma categoria: valor, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterUserId` | `uuid` | não | - | Restringe os registos a um utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterProfileId` | `uuid` | não | - | Perfil de temporizador pré-escolhido na entrada manual, e filtro dos registos desse perfil. | perfil de timer (uuid) | | `hoursPerDayTarget` | `number` | não | - | Horas-alvo por dia, usadas nas barras de progresso. | - | | `allowManualEntry` | `boolean` | não | `true` | Deixa lançar registos à mão. | - | | `showCategoryBreakdown` | `boolean` | não | `true` | No modo diário: mostra o detalhe por categoria. | - | | `groupByCategory` | `boolean` | não | `false` | No modo semanal: uma linha por categoria. | - | | `weekStartsOn` | `integer` | não | `1` | No modo semanal: dia em que a semana começa, de 1 a 7. | - | | `firstDayOfWeek` | `integer` | não | `1` | No modo mensal: dia em que a grelha começa, de 1 a 7. | - | | `showWeekTotals` | `boolean` | não | `true` | No modo mensal: mostra os totais por semana. | - | ### `columnMap` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `date` | `string` | não | - | Coluna da data do registo, POR NOME. | coluna (nome) | | `duration` | `string` | não | - | Coluna da duração em segundos, POR NOME. Ganha ao par início/fim quando está preenchida. | coluna (nome) | | `startedAt` | `string` | não | - | Coluna do início, POR NOME. | coluna (nome) | | `endedAt` | `string` | não | - | Coluna do fim, POR NOME. | coluna (nome) | | `label` | `string` | não | - | Coluna da descrição do registo, POR NOME. | coluna (nome) | | `category` | `string` | não | - | Coluna da categoria, POR NOME. | coluna (nome) | | `userId` | `string` | não | - | Coluna do utilizador a quem o registo pertence, POR NOME. | coluna (nome) | | `notes` | `string` | não | - | Coluna das notas, POR NOME. | coluna (nome) | ## Exemplo JSON ```json [ { "modes": [ "daily", "weekly", "monthly", "stats" ], "source": "auto", "columnMap": {}, "allowManualEntry": true, "showCategoryBreakdown": true, "groupByCategory": false, "weekStartsOn": 1, "firstDayOfWeek": 1, "showWeekTotals": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # weekly_timesheet **Folha de horas semanal** Folha de horas semanal (compatibilidade: o tipo foi absorvido pelo timesheet unificado, que cobre as cadências por modes). - **Kind**: `view` - **Key**: `weekly_timesheet` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `modes` | `list` de `enumeration` | não | `["daily","weekly","monthly","stats"]` | Separadores visíveis, por ordem. Um só = sem barra de separadores. Valores fora do conjunto são ignorados na leitura. | - | | `source` | `enumeration` | não | `"auto"` | De onde vêm os registos: a tabela Timer, as linhas da feature, ou `auto` (Timer quando a feature é a do temporizador). | - | | `columnMap` | `map` | não | `{}` | Que coluna desta feature transporta cada parte do registo. Só sai no JSON quando tem alguma parte preenchida, e só conta quando a fonte são as linhas da feature. | - | | `filterSourceFeatureId` | `uuid` | não | - | Restringe os registos aos que vêm desta feature de origem (compara com `TimerEntry.sourceFeatureId` na fonte Timer). | feature (uuid) | | `categoryFilter` | `string` | não | - | Restringe os registos a uma categoria: valor, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterUserId` | `uuid` | não | - | Restringe os registos a um utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `filterProfileId` | `uuid` | não | - | Perfil de temporizador pré-escolhido na entrada manual, e filtro dos registos desse perfil. | perfil de timer (uuid) | | `hoursPerDayTarget` | `number` | não | - | Horas-alvo por dia, usadas nas barras de progresso. | - | | `allowManualEntry` | `boolean` | não | `true` | Deixa lançar registos à mão. | - | | `showCategoryBreakdown` | `boolean` | não | `true` | No modo diário: mostra o detalhe por categoria. | - | | `groupByCategory` | `boolean` | não | `false` | No modo semanal: uma linha por categoria. | - | | `weekStartsOn` | `integer` | não | `1` | No modo semanal: dia em que a semana começa, de 1 a 7. | - | | `firstDayOfWeek` | `integer` | não | `1` | No modo mensal: dia em que a grelha começa, de 1 a 7. | - | | `showWeekTotals` | `boolean` | não | `true` | No modo mensal: mostra os totais por semana. | - | ### `columnMap` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `date` | `string` | não | - | Coluna da data do registo, POR NOME. | coluna (nome) | | `duration` | `string` | não | - | Coluna da duração em segundos, POR NOME. Ganha ao par início/fim quando está preenchida. | coluna (nome) | | `startedAt` | `string` | não | - | Coluna do início, POR NOME. | coluna (nome) | | `endedAt` | `string` | não | - | Coluna do fim, POR NOME. | coluna (nome) | | `label` | `string` | não | - | Coluna da descrição do registo, POR NOME. | coluna (nome) | | `category` | `string` | não | - | Coluna da categoria, POR NOME. | coluna (nome) | | `userId` | `string` | não | - | Coluna do utilizador a quem o registo pertence, POR NOME. | coluna (nome) | | `notes` | `string` | não | - | Coluna das notas, POR NOME. | coluna (nome) | ## Exemplo JSON ```json [ { "modes": [ "daily", "weekly", "monthly", "stats" ], "source": "auto", "columnMap": {}, "allowManualEntry": true, "showCategoryBreakdown": true, "groupByCategory": false, "weekStartsOn": 1, "firstDayOfWeek": 1, "showWeekTotals": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # workload **Capacidade** Carga e capacidade dos recursos ao longo do tempo, com sinalização de sobrecarga. - **Kind**: `view` - **Key**: `workload` - **Categoria**: `tempo` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `View.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `userField` | `string` | não | - | Coluna que define as linhas (as pessoas). | coluna (nome) | | `dateField` | `string` | não | - | Coluna de data que posiciona o registo. | coluna (nome) | | `hoursField` | `string` | não | - | Coluna numérica lida como horas. | coluna (nome) | | `hoursPerDayTarget` | `number` | não | `8` | Capacidade de cada pessoa por dia útil; a do intervalo é esta vezes os seus dias úteis. | - | | `defaultGranularity` | `enumeration` | não | `"week"` | Granularidade em que a vista abre; a ativa do utilizador é uma sobreposição. | - | | `filterGroup` | `map` | não | - | Grupo de filtros aplicado às linhas da vista. | - | | `showUnassignedRow` | `boolean` | não | `true` | Mostra a linha agregada "Sem responsável". | - | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna desta tabela, POR NOME. | coluna (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json [ { "hoursPerDayTarget": 8, "defaultGranularity": "week", "showUnassignedRow": true } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # Passos do WorkflowV2 37 keys declaradas. Como montar o `graph_config` que leva estas keys, e como criá-lo pela API ou pelo MCP: [Automações (WorkflowV2)](/reference/workflows-v2). | Key | Nome | Descrição | |---|---|---| | [`agent.review`](./agent-review.md) | Agente (Revisão) | IA revê os dados e o fluxo ramifica conforme a decisão. | | [`agent.route`](./agent-route.md) | Agente (Escolha) | IA analisa os dados e escolhe qual das rotas seguir. | | [`agent.run`](./agent-run.md) | Agente (IA) | IA analisa os dados e devolve variáveis para o fluxo. | | [`agent.tools`](./agent-tools.md) | Agente (Autónomo) | IA investiga com ferramentas e propõe o resultado. | | [`aggregate`](./aggregate.md) | Agregar (Resumir) | Agrupa registos e calcula somas, contagens e resumos. | | [`ai.classify`](./ai-classify.md) | Classificar (IA) | IA classifica o conteúdo numa das categorias definidas. | | [`ai.summarize`](./ai-summarize.md) | Resumir (IA) | IA resume o conteúdo e guarda o resumo numa variável. | | [`ai.translate`](./ai-translate.md) | Traduzir (IA) | IA traduz o conteúdo para o idioma escolhido. | | [`approval`](./approval.md) | Aprovação | Pára o fluxo até alguém aprovar ou rejeitar. | | [`conversation`](./conversation.md) | Revisão em conversa | Pára o fluxo para afinar o resultado em conversa com o agente. | | [`dedupe`](./dedupe.md) | Deduplicar | Compara com as linhas existentes da tabela alvo e marca cada registo como criar, atualizar ou ignorar. | | [`delay`](./delay.md) | Esperar (Delay) | Suspende o fluxo durante um intervalo ou até uma data. | | [`delete`](./delete.md) | Apagar registos | Apaga linhas de uma tabela — ação destrutiva. | | [`email.send`](./email-send.md) | Enviar email | Envia um email, com anexos opcionais. | | [`feature.read`](./feature-read.md) | Ler registos | Lê as linhas de uma tabela do Outdo para o fluxo. | | [`feature.write`](./feature-write.md) | Escrever registo | Escreve ou atualiza registos numa tabela à escolha. | | [`file.parse`](./file-parse.md) | Ler ficheiro | Lê um ficheiro anexado (CSV, Excel ou JSON) e converte-o em registos. | | [`filter`](./filter.md) | Filtrar (Registos) | Mantém ou remove registos conforme uma condição. | | [`formula`](./formula.md) | Fórmula (Calcular) | Calcula novas colunas ou variáveis através de uma expressão. | | [`http.request`](./http-request.md) | Chamar API (HTTP) | Chama uma API por HTTP — guarda a resposta, opcionalmente vira dados do fluxo ou espera por callback. | | [`ifElse`](./ifelse.md) | Condição (Se/senão) | Segue um de dois caminhos conforme uma condição. | | [`import`](./import.md) | Guardar registos preparados | Aplica na tabela de destino o lote de registos preparado pelos passos anteriores (ex.: Ler documento → Mapear → Revisão), criando ou atualizando registos. | | [`inspect`](./inspect.md) | Ver dados (teste) | Mostra o que chega a este ponto do fluxo — registos e variáveis — sem fazer nada. | | [`iterator`](./iterator.md) | Iterar (por linha) | Corre uma automação por cada registo e espera que termine. | | [`join`](./join.md) | Fundir | Junta dois conjuntos pela chave e acrescenta os campos do segundo. | | [`map`](./map.md) | Mapear (Colunas) | Liga as colunas da fonte às colunas da tabela alvo. | | [`match`](./match.md) | Conciliar | Cruza dois conjuntos de registos e propõe correspondências. | | [`mcp.call`](./mcp-call.md) | Executar ferramenta (MCP) | Executa uma tool de uma ligação MCP. | | [`notify`](./notify.md) | Notificar | Publica uma mensagem num canal, ou avisa pessoas de uma linha. | | [`ocr.extract`](./ocr-extract.md) | Ler documento (IA) | IA lê um documento e extrai os campos para registos. | | [`resolve`](./resolve.md) | Resolver (Relação) | Transforma texto na relação certa, procurando na tabela ligada. | | [`review`](./review.md) | Revisão (Humana) | Pára o fluxo para alguém rever os registos antes de continuar. | | [`runWorkflow`](./runworkflow.md) | Sub-automação | Corre outra automação como um passo desta. | | [`select`](./select.md) | Escolher/renomear colunas | Escolhe as colunas que seguem no fluxo e renomeia-as. | | [`sort`](./sort.md) | Ordenar | Ordena os registos por uma ou mais colunas. | | [`switch`](./switch.md) | Escolher caminho | Encaminha o fluxo conforme o valor de uma coluna ou variável. | | [`unwind`](./unwind.md) | Expandir lista | Desdobra uma coluna com listas numa linha por item. | --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # agent.review **Agente (Revisão)** IA revê os dados e o fluxo ramifica conforme a decisão. - **Kind**: `step` - **Key**: `agent.review` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `criteria` | `string` | não | `""` | O critério (rubric) que o agente aplica. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `userPrompt` | `string` | não | `"Revê os registos abaixo segundo o critério."` | O que rever, por cima do critério. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `allowedTools` | `list` de `string` | não | `[]` | Ferramentas de leitura que o agente pode usar para conferir contexto. Vazio = todas as de leitura. | - | | `confidenceThreshold` | `number` | não | `0.8` | Confiança mínima (0..1) para uma aprovação seguir pelo ramo `approved`. Abaixo disto escala a um humano. | - | | `maxIterations` | `integer` | não | - | Teto de iterações do loop do agente. Ausente = o teto do servidor (que faz sempre clamp ao seu máximo). | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "criteria": "", "userPrompt": "Revê os registos abaixo segundo o critério.", "allowedTools": [], "confidenceThreshold": 0.8 } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # agent.route **Agente (Escolha)** IA analisa os dados e escolhe qual das rotas seguir. - **Kind**: `step` - **Key**: `agent.route` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `options` | `list` de `string` | não | `[]` | As rotas possíveis (pelo menos 2): cada nome é um ramo, e a sub-cadeia dele vive em `config[]`. | - | | `systemPrompt` | `string` | não | `"És um classificador de documentos. Escolhe exatamente UMA das rotas permitidas para este documento; se nenhuma encaixar bem, escolhe a última."` | Instrução de sistema enviada ao modelo. Vazio na config = esta instrução. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `userPrompt` | `string` | não | `""` | Pedido concreto, por cima da instrução de sistema. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `fallbackRoute` | `string` | não | `""` | Rota de recurso quando o modelo não escolhe nenhuma das rotas. Tem de ser uma delas. Vazio = o passo falha. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "options": [], "systemPrompt": "És um classificador de documentos. Escolhe exatamente UMA das rotas permitidas para este documento; se nenhuma encaixar bem, escolhe a última.", "userPrompt": "", "fallbackRoute": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # agent.run **Agente (IA)** IA analisa os dados e devolve variáveis para o fluxo. - **Kind**: `step` - **Key**: `agent.run` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `systemPrompt` | `string` | não | `"És um classificador de documentos. Analisa o documento e devolve apenas os campos pedidos no schema, sem inventar valores."` | Instrução de sistema enviada ao modelo. Vazio na config = esta instrução. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `userPrompt` | `string` | não | `""` | Pedido concreto, por cima da instrução de sistema. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `schema` | `json` | não | `{}` | JSON Schema do que o agente devolve; as chaves do primeiro registo emitido entram em `vars`. | - | | `invalidSchema` | `string` | não | `""` | Texto cru do schema quando não é um JSON de objeto. Não-vazio = config por corrigir, e o passo falha antes de chamar o modelo. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "systemPrompt": "És um classificador de documentos. Analisa o documento e devolve apenas os campos pedidos no schema, sem inventar valores.", "userPrompt": "", "schema": {}, "invalidSchema": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # agent.tools **Agente (Autónomo)** IA investiga com ferramentas e propõe o resultado. - **Kind**: `step` - **Key**: `agent.tools` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `systemPrompt` | `string` | não | `""` | Instruções que substituem as do agente por omissão. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `userPrompt` | `string` | não | `""` | O OBJETIVO que o agente persegue. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `allowedTools` | `list` de `string` | não | `[]` | Ferramentas que o agente pode usar. Vazio = todas as de leitura (é o modo normal). | - | | `maxIterations` | `integer` | não | - | Teto de iterações do loop do agente. Ausente = o teto do servidor (que faz sempre clamp ao seu máximo). | - | | `outputSchema` | `json` | não | `{}` | JSON Schema da resposta final. Vazio = resposta em texto livre, sem forma imposta. | - | | `allowProposeRows` | `boolean` | não | `false` | O agente pode PROPOR linhas (substituem os registos do envelope como proposta). Escrever é sempre de outro passo. | - | | `includeRunFiles` | `boolean` | não | `true` | Os ficheiros desta execução seguem para o agente como contexto. Desligado = corre só sobre os dados do envelope. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | | `referenceCorpus` | `list` de `map` | não | `[]` | Ficheiros de base anexados ao CARD (ex.: o texto de uma lei), que o agente consulta em TODAS as execuções. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ### `referenceCorpus[]` Cada elemento de `referenceCorpus` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `uuid` | sim | - | Id do ficheiro no storage da organização de origem. Um ficheiro não é entidade de template: não viaja num pacote. | ficheiro (uuid) | | `name` | `string` | sim | - | Nome do ficheiro, como o autor o vê. | - | | `mimeType` | `string` | sim | - | Tipo MIME: é por ele que o servidor decide se converte o ficheiro em texto ou o manda em base64. | - | | `storagePath` | `string` | não | - | Caminho no armazenamento, de onde o servidor descarrega os bytes. | - | ## Exemplo JSON ```json { "systemPrompt": "", "userPrompt": "", "allowedTools": [], "outputSchema": {}, "allowProposeRows": false, "includeRunFiles": true, "referenceCorpus": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # aggregate **Agregar (Resumir)** Agrupa registos e calcula somas, contagens e resumos. - **Kind**: `step` - **Key**: `aggregate` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `groupBy` | `list` de `string` | não | `[]` | As colunas de agrupamento, pelos nomes que têm no envelope em curso (não de uma tabela que o passo nomeie). Vazio = um único grupo global, o resumo total. | - | | `aggregations` | `list` de `map` | não | `[]` | O que calcular por grupo. | - | ### `aggregations[]` Cada elemento de `aggregations` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `column` | `string` | não | `""` | Coluna de origem, pelo nome que tem no envelope. Vazia só é válido na contagem. | - | | `fn` | `enumeration` | sim | - | A função a aplicar à coluna. | - | | `as` | `string` | sim | - | Nome da coluna de saída, único entre as agregações. | - | ## Exemplo JSON ```json { "groupBy": [], "aggregations": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # ai.classify **Classificar (IA)** IA classifica o conteúdo numa das categorias definidas. - **Kind**: `step` - **Key**: `ai.classify` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `input` | `string` | não | `""` | O conteúdo a classificar (`{{vars.x}}`/`{{record.y}}`/literal). Vazio = classifica os dados do envelope. | expressões `{{record.coluna}}` | | `categories` | `list` de `string` | não | `[]` | As categorias possíveis (pelo menos 2): o schema prende a escolha do modelo a esta lista. | - | | `outputVar` | `string` | não | `"category"` | Variável onde a categoria escolhida aterra; a confiança vai para a mesma com o sufixo `_confidence`. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "input": "", "categories": [], "outputVar": "category" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # ai.summarize **Resumir (IA)** IA resume o conteúdo e guarda o resumo numa variável. - **Kind**: `step` - **Key**: `ai.summarize` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `input` | `string` | não | `""` | O conteúdo a resumir (`{{vars.x}}`/`{{record.y}}`/literal). Vazio = resume os dados do envelope. | expressões `{{record.coluna}}` | | `length` | `enumeration` | não | `"medium"` | Comprimento alvo do resumo, que guia o modelo. | - | | `outputVar` | `string` | não | `"summary"` | Variável onde o resumo aterra. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "input": "", "length": "medium", "outputVar": "summary" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # ai.translate **Traduzir (IA)** IA traduz o conteúdo para o idioma escolhido. - **Kind**: `step` - **Key**: `ai.translate` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `input` | `string` | não | `""` | O conteúdo a traduzir (`{{vars.x}}`/`{{record.y}}`/literal). Vazio = traduz os dados do envelope. | expressões `{{record.coluna}}` | | `targetLanguage` | `string` | não | `""` | Idioma de destino (`en`, `pt-PT`, `Francês`). Tem de ser fixo: uma variável do fluxo NÃO é substituída aqui. | - | | `outputVar` | `string` | não | `"translation"` | Variável onde a tradução aterra. | - | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "input": "", "targetLanguage": "", "outputVar": "translation" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # approval **Aprovação** Pára o fluxo até alguém aprovar ou rejeitar. - **Kind**: `step` - **Key**: `approval` - **Categoria**: `gate` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `title` | `string` | não | `""` | Título que o aprovador vê. Aceita tokens `{{record.x}}`/`{{vars.y}}`, resolvidos ao mostrar. | expressões `{{record.coluna}}` | | `message` | `string` | não | `""` | Mensagem que o aprovador vê. Aceita tokens `{{record.x}}`/`{{vars.y}}`, resolvidos ao mostrar. | expressões `{{record.coluna}}` | | `approvers` | `map` | não | - | Quem pode aprovar: uma coluna de pessoas da linha do gatilho, pessoas fixas, ou papéis. Ausente = aprova quem tiver acesso. | - | ### `approvers` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `userColumn` | `string` | não | - | O nome da coluna de pessoas de onde saem os aprovadores. | coluna (nome) | | `users` | `list` de `uuid` | não | - | Ids de pessoas fixas, da organização de origem. | - | | `roles` | `list` de `string` | não | - | Papéis cujos membros aprovam (`owner`, `admin`, `dev`, `user`, `view`). Viajam como estão: um papel é o mesmo nome em qualquer organização. | - | ## Exemplo JSON ```json { "title": "", "message": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # conversation **Revisão em conversa** Pára o fluxo para afinar o resultado em conversa com o agente. - **Kind**: `step` - **Key**: `conversation` - **Categoria**: `gate` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `seedPrompt` | `string` | não | `""` | Instruções ao agente para a conversa de refinamento. Aceita tokens `{{record.x}}`/`{{vars.y}}`. Vazio = sem instruções. | expressões `{{record.coluna}}` | ## Exemplo JSON ```json { "seedPrompt": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # dedupe **Deduplicar** Compara com as linhas existentes da tabela alvo e marca cada registo como criar, atualizar ou ignorar. - **Kind**: `step` - **Key**: `dedupe` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `keyFields` | `list` de `string` | não | `[]` | As colunas que formam a chave composta, pelos nomes que têm no envelope em curso. A tabela alvo vem do passo de mapeamento a montante, não desta config: por isso não se diz de que feature são as colunas. | - | | `conflictPolicy` | `enumeration` | não | `"skip_existing"` | O que fazer quando a chave já existe: ignorar a linha, ou atualizá-la quando os dados mudaram. | - | ## Exemplo JSON ```json { "keyFields": [], "conflictPolicy": "skip_existing" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # delay **Esperar (Delay)** Suspende o fluxo durante um intervalo ou até uma data. - **Kind**: `step` - **Key**: `delay` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mode` | `enumeration` | não | `"duration"` | Esperar uma duração relativa (`duration`) ou até uma data (`until`). | - | | `durationMinutes` | `integer` | não | `0` | Minutos a esperar, no modo `duration`. A autoria exige > 0; em execução um valor <= 0 não suspende. | - | | `untilDate` | `string` | não | `""` | Instante-alvo no modo `until`: ISO 8601 (ou data à portuguesa) ou um token `{{vars.x}}` resolvido em execução. | expressões `{{record.coluna}}` | ## Exemplo JSON ```json { "mode": "duration", "durationMinutes": 0, "untilDate": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # delete **Apagar registos** Apaga linhas de uma tabela — ação destrutiva. - **Kind**: `step` - **Key**: `delete` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetFeatureId` | `uuid` | não | `""` | A tabela de onde se apagam as linhas. | feature (uuid) | | `rowIdField` | `string` | não | `"_rowId"` | Campo do envelope que traz o id da linha a apagar. O passo cai para `id` quando este falta. | - | ## Exemplo JSON ```json { "targetFeatureId": "$f_exemplo", "rowIdField": "_rowId" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # email.send **Enviar email** Envia um email, com anexos opcionais. - **Kind**: `step` - **Key**: `email.send` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `to` | `string` | não | `""` | Destinatário(s). A var homónima do envelope ganha a este valor; um token que não resolva FALHA o passo em vez de enviar o literal. | expressões `{{record.coluna}}` | | `subject` | `string` | não | `""` | Assunto do email. | expressões `{{record.coluna}}` | | `body` | `string` | não | `""` | Corpo do email (HTML, salvo `plainText`). | expressões `{{record.coluna}}` | | `from` | `string` | não | `""` | Remetente. Vazio = o do transporte da organização. | expressões `{{record.coluna}}` | | `cc` | `string` | não | `""` | Cópia. Vazio = sem cópia. | expressões `{{record.coluna}}` | | `bcc` | `string` | não | `""` | Cópia oculta. Vazio = sem cópia oculta. | expressões `{{record.coluna}}` | | `plainText` | `boolean` | não | `false` | Enviar o corpo como texto simples em vez de HTML. | - | | `attachFiles` | `boolean` | não | `true` | Anexar os ficheiros que vêm no envelope. Ligado por omissão. | - | | `connectionName` | `string` | não | - | Nome da ligação `smtp` por onde enviar. Vazio = o transporte global do servidor. | ligação (nome) | ## Exemplo JSON ```json { "to": "", "subject": "", "body": "", "from": "", "cc": "", "bcc": "", "plainText": false, "attachFiles": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # feature.read **Ler registos** Lê as linhas de uma tabela do Outdo para o fluxo. - **Kind**: `step` - **Key**: `feature.read` - **Categoria**: `source` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureId` | `uuid` | não | `""` | Tabela de onde se leem as linhas. Vazio = passo por configurar. | feature (uuid) | | `filters` | `list` de `map` | não | `[]` | Filtros simples por coluna (caminho legado). Quando há `filterGroup`, é ele que manda. | - | | `filterGroup` | `map` | não | - | Filtros tipados sobre as linhas a ler. Presente, é a fonte de verdade (o executor converte-os para `filters`). | - | | `limit` | `integer` | não | `500` | Teto de linhas lidas (1 a 2000): uma leitura sem teto era uma tabela inteira no envelope. | - | | `orderBy` | `map` | não | - | Ordenação da leitura. Coluna vazia = sem ordenação (o parse nem a grava). | - | | `mergeMode` | `enumeration` | não | `"replace"` | O que fazer aos registos já no envelope: `replace` substitui-os, `append` concatena (é o modo da conciliação). | - | ### `filters[]` Cada elemento de `filters` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `column` | `string` | sim | - | Coluna da tabela lida, POR NOME. | coluna de `featureId` (nome) | | `op` | `enumeration` | não | `"eq"` | Operador da comparação. `isEmpty` e `notEmpty` ignoram o valor. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Aceita `{{vars.x}}`, resolvido em execução. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | expressões `{{record.coluna}}` | ### `filterGroup` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filterGroup.rules[]` Cada elemento de `filterGroup.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela lida, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filterGroup.groups[]` Cada elemento de `filterGroup.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filterGroup.groups[].rules[]` Cada elemento de `filterGroup.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela lida, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `orderBy` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `column` | `string` | sim | - | Coluna que ordena a leitura, POR NOME. | coluna de `featureId` (nome) | | `desc` | `boolean` | não | `false` | Ordem descendente. | - | ## Exemplo JSON ```json { "featureId": "$f_exemplo", "filters": [], "limit": 500, "mergeMode": "replace" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # feature.write **Escrever registo** Escreve ou atualiza registos numa tabela à escolha. - **Kind**: `step` - **Key**: `feature.write` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetFeatureId` | `uuid` | não | `""` | A tabela onde se escreve. Vazia = o card não está pronto. | feature (uuid) | | `bindings` | `list` de `map` | não | `[]` | Uma entrada por coluna-alvo a preencher. | - | | `keyFields` | `list` de `string` | não | `[]` | Chave de upsert: colunas da tabela de destino que identificam o registo. Vazia = insert cego. IGNORADA no modo "atualizar o registo do gatilho". | - | | `mode` | `enumeration` | não | `"upsert"` | Como escrever: `upsert` (casa pelas chaves, senão insere), `insert` (sempre insere), `applyDecisions` (aplica as decisões da revisão) ou `updateTrigger` (só a linha do gatilho). | - | ### `bindings[]` Cada elemento de `bindings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | sim | - | Coluna da tabela de destino, POR NOME. | coluna de `targetFeatureId` (nome) | | `source` | `enumeration` | não | - | Valor fixo tipado (`literal`) ou binding do envelope (`variable`). Ausente = deduzido de conter `{{`. | - | | `value` | `string` | não | - | O que escrever: literal tipado (texto, número, booleano, lista, data) ou template `{{record.x}}`/`{{vars.y}}`. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | expressões `{{record.coluna}}` | | `type` | `string` | não | `"text"` | Tipo de ESCRITA do valor: decide a coerção antes de gravar (`convertValue`; `document` traz o envelope de extração). | - | | `decimals` | `integer` | não | - | Casas decimais da coluna alvo, aplicadas depois da coerção; vazio não arredonda nada. | - | ## Exemplo JSON ```json { "targetFeatureId": "$f_exemplo", "bindings": [], "keyFields": [], "mode": "upsert" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # file.parse **Ler ficheiro** Lê um ficheiro anexado (CSV, Excel ou JSON) e converte-o em registos. - **Kind**: `step` - **Key**: `file.parse` - **Categoria**: `source` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `parser` | `enumeration` | não | `"csv"` | Que leitor usar. Um valor fora do trio é recusado em autoria e falha em execução - nunca se lê um livro binário como CSV. | - | | `delimiter` | `string` | não | `","` | Só CSV: separador dos campos, UM carácter (`,` `;` tab). Mais do que um nunca casava e o ficheiro virava uma coluna só. | - | | `hasHeader` | `boolean` | não | `true` | CSV e Excel: a primeira linha dá os nomes dos campos; senão chamam-se col1, col2, … | - | | `sheet` | `string` | não | `""` | Só Excel: nome da folha a ler. Vazio = a primeira. | - | | `path` | `string` | não | `""` | Só JSON: caminho pontuado até à LISTA de registos (ex.: `data.items`). Vazio = a raiz já é a lista. | - | | `encoding` | `enumeration` | não | `"utf8"` | Só CSV: como descodificar os bytes. Em `utf8` é estrito - um ficheiro latin-1 falha em vez de virar mojibake em silêncio. | - | | `inferredColumns` | `list` de `string` | não | `[]` | Nomes das colunas que o form detetou numa amostra do ficheiro. Vazio = desconhecidas. Não afeta a execução. | - | ## Exemplo JSON ```json { "parser": "csv", "delimiter": ",", "hasHeader": true, "sheet": "", "path": "", "encoding": "utf8", "inferredColumns": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # filter **Filtrar (Registos)** Mantém ou remove registos conforme uma condição. - **Kind**: `step` - **Key**: `filter` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `filter` | `map` | não | - | A condição, sobre as colunas que o passo anterior entrega (o envelope em curso). | - | | `mode` | `enumeration` | não | `"keep"` | Os que casam ficam (`keep`) ou saem (`drop`). | - | ### `filter` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filter.rules[]` Cada elemento de `filter.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna do envelope em curso, POR NOME: o passo não nomeia feature nenhuma, logo não é referência a coluna de tabela. | - | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filter.groups[]` Cada elemento de `filter.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filter.groups[].rules[]` Cada elemento de `filter.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna do envelope em curso, POR NOME: o passo não nomeia feature nenhuma, logo não é referência a coluna de tabela. | - | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "mode": "keep" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # formula **Fórmula (Calcular)** Calcula novas colunas ou variáveis através de uma expressão. - **Kind**: `step` - **Key**: `formula` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `computations` | `list` de `map` | não | `[]` | As expressões a calcular, pela ordem em que correm. | - | ### `computations[]` Cada elemento de `computations` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `target` | `string` | sim | - | Nome de saída: a coluna que se acrescenta a cada registo, ou a variável do run. | - | | `expression` | `expression` | sim | - | A expressão a avaliar (aritmética, funções, condições), com tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `perRecord` | `boolean` | não | `true` | Avalia por registo e escreve a coluna em cada um; a falso, avalia uma vez e escreve a variável. | - | ## Exemplo JSON ```json { "computations": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # http.request **Chamar API (HTTP)** Chama uma API por HTTP — guarda a resposta, opcionalmente vira dados do fluxo ou espera por callback. - **Kind**: `step` - **Key**: `http.request` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `url` | `string` | não | `""` | O alvo do pedido (ou o caminho, com uma ligação). Aceita tokens `{{vars.x}}`/`{{record.y}}` e a `{{callbackUrl}}`. | expressões `{{record.coluna}}` | | `method` | `string` | não | `"GET"` | Verbo HTTP. Qualquer token válido serve (verbos próprios incluídos); só a ausência total cai em `GET`. | - | | `headers` | `map` | não | `{}` | Cabeçalhos do pedido, nome → valor. | - | | `invalidHeaders` | `string` | não | `""` | O texto cru dos cabeçalhos quando não é um JSON de objeto. Presente = a config está inválida e o passo falha antes do pedido. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `body` | `string` | não | - | Corpo a enviar, com tokens. Ausente = sem corpo (um corpo vazio com `recordsAsBody` envia os registos do fluxo). | expressões `{{record.coluna}}` | | `recordsAsBody` | `boolean` | não | `true` | Corpo vazio envia os registos do fluxo como JSON array. Ligado por omissão. | - | | `responseVar` | `string` | não | `"http"` | Nome da variável onde a resposta (`{status, ok, body}`) fica sempre disponível a jusante. | - | | `continueOnError` | `boolean` | não | `false` | Um status fora de 2xx deixa de falhar o passo: a resposta entra com `ok: false` e o fluxo segue. | - | | `useResponseAsRecords` | `boolean` | não | `false` | A resposta SUBSTITUI os registos do fluxo. Desligado = o fluxo segue com os registos que já tinha. | - | | `recordsPath` | `string` | não | `""` | Caminho pontuado dentro da resposta até à lista a usar como registos (ex.: `data.items`). Vazio = a raiz. | - | | `inferredColumns` | `list` de `string` | não | `[]` | As colunas que o botão "Testar & inferir" detetou na resposta: metadados de autoria, publicados quando a resposta vira registos. | - | | `awaitAck` | `boolean` | não | `false` | Modo callback: faz o pedido, embebe a `{{callbackUrl}}` e suspende até o serviço chamar de volta. | - | | `callbackVar` | `string` | não | `"callback"` | Nome da variável onde o corpo do callback aterra ao retomar. Só sai no JSON em modo callback. | - | | `timeoutMinutes` | `integer` | não | - | Prazo máximo de espera do callback, em minutos. Ausente = espera indefinida. | - | | `connectionName` | `string` | não | - | Nome da ligação `http` a usar (baseUrl, cabeçalhos e autenticação do cofre). Vazio = pedido cru. | ligação (nome) | | `endpointRef` | `string` | não | `""` | Nome de um endpoint da ligação, que governa verbo, caminho, cabeçalhos e corpo. Vazio = sem endpoint nomeado. | - | | `connectionVariables` | `json` | não | `{}` | Valores por-step para as variáveis declaradas na ligação. Podem transportar segredos: nem o varredor lhes toca. **Segredo.** O exportador substitui este valor por vazio e nomeia o caminho em `redacted[]`: nunca sai num pacote de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `shaping` | `map` | não | - | Resumir na fonte: filtra, agrupa e agrega a resposta ANTES de ela virar registos. Ausente = sem resumo. | - | ### `shaping` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `filter` | `map` | não | - | Filtro prévio, aplicado às linhas da resposta antes de agrupar. | - | | `groupBy` | `list` de `string` | não | `[]` | Campos por que se agrupa. Vazio = um único grupo global (o total). | - | | `metrics` | `list` de `map` | não | `[]` | O que calcular por grupo. Sem métricas não há resumo. | - | ### `shaping.filter` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `shaping.filter.rules[]` Cada elemento de `shaping.filter.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Campo da resposta, POR NOME: o passo não nomeia feature nenhuma, logo não é referência a coluna de tabela. | - | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `shaping.filter.groups[]` Cada elemento de `shaping.filter.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `shaping.filter.groups[].rules[]` Cada elemento de `shaping.filter.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Campo da resposta, POR NOME: o passo não nomeia feature nenhuma, logo não é referência a coluna de tabela. | - | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `shaping.metrics[]` Cada elemento de `shaping.metrics` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `op` | `enumeration` | não | - | A operação a aplicar. Só a contagem dispensa o campo. | - | | `field` | `string` | não | `""` | Campo de origem, pelo nome que tem no envelope da resposta. Vazio só é válido na contagem. | - | | `as` | `string` | não | `""` | Nome da coluna de saída. Vazio = derivado do campo (ou da operação, na contagem). | - | ## Exemplo JSON ```json { "url": "", "method": "GET", "headers": {}, "invalidHeaders": "", "recordsAsBody": true, "responseVar": "http", "continueOnError": false, "useResponseAsRecords": false, "recordsPath": "", "inferredColumns": [], "awaitAck": false, "callbackVar": "callback", "endpointRef": "", "connectionVariables": {} } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # ifElse **Condição (Se/senão)** Segue um de dois caminhos conforme uma condição. - **Kind**: `step` - **Key**: `ifElse` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `condition` | `map` | sim | - | A condição que decide o caminho. | - | | `then` | `list` | não | `[]` | O ramo seguido quando a condição é verdadeira: transporta STEPS, não config. | - | | `else` | `list` | não | `[]` | O ramo seguido quando a condição é falsa: transporta STEPS, não config. | - | ### `condition` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `subject` | `enumeration` | sim | - | O que se testa: uma variável, o nº de registos, ou a forma dos dados. | - | | `var` | `string` | não | - | Nome da variável a testar (só com o sujeito `var`). Aceita um caminho ou o token `{{record.x}}` inteiro. | expressões `{{record.coluna}}` | | `op` | `enumeration` | sim | - | Como se compara. `exists`/`notExists` não usam valor; os de ordem exigem números ou datas dos dois lados. | - | | `value` | `string` | não | - | O valor a comparar. Aceita tokens `{{record.x}}`/`{{vars.y}}`; um literal numérico também serve. | expressões `{{record.coluna}}` | ## Exemplo JSON ```json { "condition": { "subject": "var", "op": "eq" }, "then": [], "else": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # import **Guardar registos preparados** Aplica na tabela de destino o lote de registos preparado pelos passos anteriores (ex.: Ler documento → Mapear → Revisão), criando ou atualizando registos. - **Kind**: `step` - **Key**: `import` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mode` | `enumeration` | não | `"applyDecisions"` | O modo que o preset carimba ao materializar em `feature.write`: aplicar as decisões revistas. É sempre este. | - | | `keyFields` | `list` de `string` | não | `[]` | Colunas que identificam o registo, para uma retoma não gravar o lote outra vez. Vazio = insert cego (o card avisa). | - | ## Exemplo JSON ```json { "mode": "applyDecisions", "keyFields": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # inspect **Ver dados (teste)** Mostra o que chega a este ponto do fluxo — registos e variáveis — sem fazer nada. Útil para testar. - **Kind**: `step` - **Key**: `inspect` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `note` | `string` | não | `""` | Nota livre do autor para distinguir este card dos outros no registo do run. Só descritiva: não passa pelo binding. | - | ## Exemplo JSON ```json { "note": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # iterator **Iterar (por linha)** Corre uma automação por cada registo e espera que termine. - **Kind**: `step` - **Key**: `iterator` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `workflowId` | `uuid` | não | `""` | A automação a correr: o id do GRUPO de versões (o servidor resolve a versão ativa desta organização), não o da versão. | workflow V2 (uuid) | | `passPayload` | `boolean` | não | `true` | Passar o envelope atual como semente do filho. Ignorado quando `forEachRecord` está ligado (aí a semente é por registo). | - | | `forEachRecord` | `boolean` | não | `false` | Uma execução-filha POR registo do envelope (as `vars` do pai propagam-se, os ficheiros não). | - | | `waitForChildren` | `boolean` | não | `false` | Suspender o pai até TODOS os filhos terminarem, e só então continuar com o resumo deles. | - | | `resultVar` | `string` | não | `"children"` | Variável onde aterra o resumo dos filhos `{total, success, failed}`. Só tem efeito nos modos que esperam. | - | ## Exemplo JSON ```json { "workflowId": "nome-da-workflowV2", "passPayload": true, "forEachRecord": false, "waitForChildren": false, "resultVar": "children" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # join **Fundir** Junta dois conjuntos pela chave e acrescenta os campos do segundo. - **Kind**: `step` - **Key**: `join` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `setBSource` | `uuid` | não | `""` | Carimbo `_source` do conjunto B: o id da tabela lida em `append`. Vazio = detetar o último `_source` distinto dos registos. | feature (uuid) | | `rules` | `list` de `map` | não | `[]` | As regras que emparelham A com B - as MESMAS do passo de conciliação. | - | | `minConfidence` | `number` | não | `0.5` | Confiança mínima (0..1) para um par ganhar. | - | | `aggregate` | `boolean` | não | `false` | Permite 1 de A ↔ N de B quando a soma bate a regra numérica; a política de vários decide o que se funde. | - | | `columns` | `list` de `string` | não | `[]` | As colunas de B a trazer para A, pelos nomes que têm no envelope. Vazia = todas, exceto as internas (`_source`, `_rowId`, `_match`). | - | | `prefix` | `string` | não | `""` | Prefixo aplicado às colunas trazidas de B (ex.: `b_`), para não colidirem com as de A. Vazio = sem prefixo. | - | | `onMultiple` | `enumeration` | não | `"first"` | Quando um registo de A casa com vários de B: fundir o primeiro, ou trazer cada campo como lista. | - | ### `rules[]` Cada elemento de `rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `keyA` | `string` | sim | - | Chave no registo de A, pelo nome que tem no envelope. | - | | `keyB` | `string` | sim | - | Chave no registo de B, pelo nome que tem no envelope. | - | | `kind` | `enumeration` | não | `"exact"` | Como se comparam as duas chaves: igual, numérica com tolerância, data com janela de dias, ou aproximada. | - | | `tolerance` | `number` | não | `0.01` | Só na comparação numérica: diferença absoluta máxima aceite (\|a-b\| ≤ tolerância). | - | | `days` | `integer` | não | `0` | Só na comparação de datas: diferença máxima em dias de calendário. | - | | `minSimilarity` | `number` | não | `0.8` | Só na comparação aproximada: semelhança mínima (0..1) para a regra contar. | - | ## Exemplo JSON ```json { "setBSource": "$f_exemplo", "rules": [], "minConfidence": 0.5, "aggregate": false, "columns": [], "prefix": "", "onMultiple": "first" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # map **Mapear (Colunas)** Liga as colunas da fonte às colunas da tabela alvo. - **Kind**: `step` - **Key**: `map` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mappings` | `list` de `map` | não | `[]` | As ligações coluna da fonte → coluna da tabela alvo. | - | | `sourceColumns` | `list` de `string` | não | `[]` | As colunas fonte conhecidas, pelos nomes que têm no envelope: metadados de autoria para o card reabrir com os dropdowns cheios. Não afeta a execução. | - | | `fixedValues` | `map` | não | `{}` | Valores fixos a gravar: a chave é o nome da coluna alvo, o valor é o que se escreve em todas as linhas. | chave: coluna de `targetFeatureId` (nome) | | `targetFeatureId` | `uuid` | não | - | Tabela alvo das ligações: é ela que dá sentido aos nomes de coluna deste passo. | feature (uuid) | ### `mappings[]` Cada elemento de `mappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `sourcePath` | `string` | sim | - | De onde vem o valor: caminho pontuado no registo recebido ou um token `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `targetColumn` | `string` | sim | - | Coluna da tabela alvo, POR NOME. | coluna de `targetFeatureId` (nome) | | `type` | `string` | não | `"text"` | Tipo de ESCRITA do valor (o `workflowColumnWriteType` da coluna alvo): decide a coerção antes de gravar. | - | | `decimals` | `integer` | não | - | Casas decimais da coluna alvo, aplicadas depois da coerção; vazio não arredonda nada. | - | ## Exemplo JSON ```json { "mappings": [], "sourceColumns": [], "fixedValues": {} } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # match **Conciliar** Cruza dois conjuntos de registos e propõe correspondências. - **Kind**: `step` - **Key**: `match` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `setBSource` | `uuid` | não | `""` | Carimbo `_source` do conjunto B: o id da tabela lida em `append`. Vazio = detetar o último `_source` distinto dos registos. | feature (uuid) | | `rules` | `list` de `map` | não | `[]` | As regras que comparam A com B. A confiança de um candidato é a soma das contribuições das regras. | - | | `aggregate` | `boolean` | não | `false` | Permite 1 registo de A ↔ N de B quando a regra numérica bate na SOMA dos B (pagamentos agregados). | - | | `minConfidence` | `number` | não | `0.5` | Confiança mínima (0..1) para um candidato ganhar. | - | | `keepUnmatchedB` | `boolean` | não | `true` | Os registos de B que ninguém consumiu ficam no resultado, anotados como não casados; a falso, saem. | - | ### `rules[]` Cada elemento de `rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `keyA` | `string` | sim | - | Chave no registo de A, pelo nome que tem no envelope. | - | | `keyB` | `string` | sim | - | Chave no registo de B, pelo nome que tem no envelope. | - | | `kind` | `enumeration` | não | `"exact"` | Como se comparam as duas chaves: igual, numérica com tolerância, data com janela de dias, ou aproximada. | - | | `tolerance` | `number` | não | `0.01` | Só na comparação numérica: diferença absoluta máxima aceite (\|a-b\| ≤ tolerância). | - | | `days` | `integer` | não | `0` | Só na comparação de datas: diferença máxima em dias de calendário. | - | | `minSimilarity` | `number` | não | `0.8` | Só na comparação aproximada: semelhança mínima (0..1) para a regra contar. | - | ## Exemplo JSON ```json { "setBSource": "$f_exemplo", "rules": [], "aggregate": false, "minConfidence": 0.5, "keepUnmatchedB": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # mcp.call **Executar ferramenta (MCP)** Executa uma tool de uma ligação MCP. - **Kind**: `step` - **Key**: `mcp.call` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `connectionName` | `string` | não | - | Nome da ligação `mcp` que serve a ferramenta (URL e segredo resolvidos no servidor). | ligação (nome) | | `tool` | `string` | não | `""` | Nome da ferramenta a executar. Normalmente fixo, mas aceita tokens. | expressões `{{record.coluna}}` | | `args` | `json` | não | `{}` | Argumentos da ferramenta, de forma livre. Os valores aceitam tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `invalidArgs` | `string` | não | `""` | O texto cru dos argumentos quando não é um JSON de objeto. Presente = a config está inválida e a tool não é chamada. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `includeVars` | `boolean` | não | `false` | Fundir as variáveis do envelope nos argumentos. A config ganha em caso de colisão. | - | | `resultVar` | `string` | não | `"mcp"` | Nome da variável onde o resultado da ferramenta fica disponível a jusante. | - | ## Exemplo JSON ```json { "tool": "", "args": {}, "invalidArgs": "", "includeVars": false, "resultVar": "mcp" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # notify **Notificar** Publica uma mensagem num canal, ou avisa pessoas de uma linha. - **Kind**: `step` - **Key**: `notify` - **Categoria**: `action` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `scopeType` | `enumeration` | não | `"channel"` | Que tipo de alvo recebe o aviso: `channel` (um canal de mensagens) ou `user` (pessoas). | - | | `scopeId` | `uuid` | não | `""` | O canal de mensagens onde a mensagem é publicada (o `scopeId` de `Message`, que com `scopeType: channel` é um canal). Vazio com `scopeType: user`. | canal (uuid) | | `from` | `map` | não | - | Quem é avisado com `scopeType: user`: uma coluna de pessoas da linha do gatilho, ou pessoas fixas. | - | | `content` | `string` | não | `""` | O corpo da mensagem. Aceita tokens `{{record.x}}`/`{{vars.y}}`, resolvidos ao publicar. | expressões `{{record.coluna}}` | | `type` | `enumeration` | não | `"chat"` | Dica de render da mensagem: `chat` (como um humano) ou `system` (aviso do sistema). | - | ### `from` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `userColumn` | `string` | não | - | O nome da coluna de pessoas de onde saem os destinatários. | coluna (nome) | | `users` | `list` de `uuid` | não | - | Ids de pessoas fixas, da organização de origem. | - | ## Exemplo JSON ```json { "scopeType": "channel", "scopeId": "nome-da-channel", "content": "", "type": "chat" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # ocr.extract **Ler documento (IA)** IA lê um documento e extrai os campos para registos. - **Kind**: `step` - **Key**: `ocr.extract` - **Categoria**: `source` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `schema` | `json` | não | `{}` | Schema da extração (os campos a tirar do documento). Vazio = extração livre: a IA devolve os campos que encontrar. | - | | `invalidSchema` | `string` | não | `""` | Texto cru do schema quando não é um JSON de objeto. Não-vazio = config por corrigir, e o passo falha antes de gastar uma extração paga. | - | | `systemPrompt` | `string` | não | `"És um extrator de dados de documentos. Devolve apenas JSON válido com os campos pedidos no schema."` | Instrução de sistema enviada ao modelo. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `userPrompt` | `string` | não | `"Extrai os campos do documento segundo o schema fornecido."` | Pedido concreto ao modelo, por cima da instrução de sistema. Aceita tokens `{{record.x}}`/`{{vars.y}}`. | expressões `{{record.coluna}}` | | `modelSource` | `map` | não | - | De onde vem o modelo de IA: o catálogo OutDo (omissão) ou uma ligação `ai_provider` da organização. | - | | `splitDocuments` | `boolean` | não | `false` | O ficheiro pode trazer vários documentos (um PDF com 20 faturas): cada um sai como um registo separado. | - | ### `modelSource` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `kind` | `enumeration` | não | `"catalog"` | Catálogo OutDo (resolvido pelas definições de IA da organização) ou ligação própria (BYOK). | - | | `mode` | `enumeration` | não | - | Slot do catálogo a forçar. Ausente = o slot por omissão do passo. Só conta no modo de catálogo. | - | | `connectionName` | `string` | não | - | Nome da ligação `ai_provider` que serve o modelo. Só conta no modo de ligação. | ligação (nome) | ## Exemplo JSON ```json { "schema": {}, "invalidSchema": "", "systemPrompt": "És um extrator de dados de documentos. Devolve apenas JSON válido com os campos pedidos no schema.", "userPrompt": "Extrai os campos do documento segundo o schema fornecido.", "splitDocuments": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # resolve **Resolver (Relação)** Transforma texto na relação certa, procurando na tabela ligada. - **Kind**: `step` - **Key**: `resolve` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `resolutions` | `list` de `map` | não | `[]` | As trocas texto → valor da relação, uma por coluna a resolver. | - | ### `resolutions[]` Cada elemento de `resolutions` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | `""` | Coluna dos registos em curso cujo texto se resolve. O passo não tem tabela anfitriã: a feature desta coluna fica por determinar. | coluna (nome) | | `linkedFeatureId` | `uuid` | não | `""` | Tabela ligada onde se procura o par rótulo→valor. | feature (uuid) | | `linkedLabelColumn` | `string` | não | `""` | Coluna da tabela ligada com o TEXTO a casar, POR NOME (no componente `linked_select` o campo homónimo é um uuid). | coluna de `linkedFeatureId` (nome) | | `linkedValueColumn` | `string` | não | `""` | Coluna da tabela ligada com o VALOR a escrever (o que a relação guarda), POR NOME. | coluna de `linkedFeatureId` (nome) | | `missPolicy` | `enumeration` | não | `"keep"` | Quando o texto não casa nada: deixar cru, pôr vazio, ou marcar o registo para revisão. | - | ## Exemplo JSON ```json { "resolutions": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # review **Revisão (Humana)** Pára o fluxo para alguém rever os registos antes de continuar. - **Kind**: `step` - **Key**: `review` - **Categoria**: `gate` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `reviewType` | `enumeration` | não | `"generic"` | O renderer que o cliente usa para rever. Ausente = `generic` (campos por chave), que é a omissão segura. | - | | `autoApprove` | `map` | não | - | Auto-aprovação por confiança. Ausente = nada é auto-aprovado (tudo espera por um humano). | - | | `documentMapping` | `map` | não | - | Só no formato `document`: casa o editor de fatura com as chaves do schema do utilizador. Ausente = auto-deteção total. | - | ### `autoApprove` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `path` | `string` | sim | - | Caminho pontuado dentro do registo onde está a confiança (ex.: `_match..confidence`). | - | | `threshold` | `number` | sim | - | Confiança mínima para passar sem revisão humana; tem de estar em (0,1]. Valor em falta ou inválido = tudo pendente. | - | ### `documentMapping` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `linesArrayPath` | `string` | não | `""` | Chave da lista de linhas no registo extraído (ex.: `linhas`). Vazia = auto-deteção. | - | | `header` | `map` | não | `{}` | Campo canónico do cabeçalho (`supplier.name`, `totals.total`) → chave do registo extraído (`fornecedor`, `total`). | - | | `line` | `map` | não | `{}` | Chave canónica da linha (`description`, `totalPrice`) → chave dentro do item da lista do utilizador. | - | | `headerAutoMatch` | `map` | não | `{}` | Ligações automáticas do CABEÇALHO, por campo canónico. Ausente = o cliente deriva-as dos passos `resolve` a jusante. | - | | `lineAutoMatch` | `map` | não | `{}` | Ligações automáticas das LINHAS, por chave canónica da linha (na prática só `description`). | - | ### `documentMapping.headerAutoMatch{}` Cada entrada de `documentMapping.headerAutoMatch` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureId` | `uuid` | não | `""` | A tabela onde se procura o texto extraído (a "tabela de pesquisa"). Vazia = a ligação não é oferecida. | feature (uuid) | | `searchColumn` | `string` | não | `""` | Coluna da tabela de pesquisa com o TEXTO a casar - o rótulo por que se procura, pelo NOME. | coluna de `featureId` (nome) | | `valueColumn` | `string` | não | `""` | Coluna da tabela de pesquisa com o VALOR que o campo passa a guardar, pelo NOME. Vazia = fica o próprio rótulo. | coluna de `featureId` (nome) | | `creationMappings` | `list` de `map` | não | `[]` | Colunas a pré-preencher quando o revisor CRIA o registo em falta a partir deste campo. Vazia = a criação leva só o texto. | - | ### `documentMapping.headerAutoMatch{}.creationMappings[]` Cada elemento de `documentMapping.headerAutoMatch{}.creationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | `""` | Coluna da tabela de pesquisa a pré-preencher (uuid ou nome - o runtime aceita os dois). | coluna de `featureId` (uuid ou nome) | | `sourceField` | `string` | não | `""` | Campo do registo de origem de onde vem o valor: caminho pontuado no cabeçalho, chave simples na linha. | - | ### `documentMapping.lineAutoMatch{}` Cada entrada de `documentMapping.lineAutoMatch` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `featureId` | `uuid` | não | `""` | A tabela onde se procura o texto extraído (a "tabela de pesquisa"). Vazia = a ligação não é oferecida. | feature (uuid) | | `searchColumn` | `string` | não | `""` | Coluna da tabela de pesquisa com o TEXTO a casar - o rótulo por que se procura, pelo NOME. | coluna de `featureId` (nome) | | `valueColumn` | `string` | não | `""` | Coluna da tabela de pesquisa com o VALOR que o campo passa a guardar, pelo NOME. Vazia = fica o próprio rótulo. | coluna de `featureId` (nome) | | `creationMappings` | `list` de `map` | não | `[]` | Colunas a pré-preencher quando o revisor CRIA o registo em falta a partir deste campo. Vazia = a criação leva só o texto. | - | ### `documentMapping.lineAutoMatch{}.creationMappings[]` Cada elemento de `documentMapping.lineAutoMatch{}.creationMappings` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `targetColumn` | `string` | não | `""` | Coluna da tabela de pesquisa a pré-preencher (uuid ou nome - o runtime aceita os dois). | coluna de `featureId` (uuid ou nome) | | `sourceField` | `string` | não | `""` | Campo do registo de origem de onde vem o valor: caminho pontuado no cabeçalho, chave simples na linha. | - | ## Exemplo JSON ```json { "reviewType": "generic" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # runWorkflow **Sub-automação** Corre outra automação como um passo desta. - **Kind**: `step` - **Key**: `runWorkflow` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `workflowId` | `uuid` | não | `""` | A automação a correr: o id do GRUPO de versões (o servidor resolve a versão ativa desta organização), não o da versão. | workflow V2 (uuid) | | `passPayload` | `boolean` | não | `true` | Passar o envelope atual como semente do filho. Ignorado quando `forEachRecord` está ligado (aí a semente é por registo). | - | | `forEachRecord` | `boolean` | não | `false` | Uma execução-filha POR registo do envelope (as `vars` do pai propagam-se, os ficheiros não). | - | | `waitForChildren` | `boolean` | não | `false` | Suspender o pai até TODOS os filhos terminarem, e só então continuar com o resumo deles. | - | | `resultVar` | `string` | não | `"children"` | Variável onde aterra o resumo dos filhos `{total, success, failed}`. Só tem efeito nos modos que esperam. | - | ## Exemplo JSON ```json { "workflowId": "nome-da-workflowV2", "passPayload": true, "forEachRecord": false, "waitForChildren": false, "resultVar": "children" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # select **Escolher/renomear colunas** Escolhe as colunas que seguem no fluxo e renomeia-as. - **Kind**: `step` - **Key**: `select` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `columns` | `list` de `map` | não | `[]` | As colunas que seguem, pela ordem escolhida: nomes do envelope em curso, não de uma tabela que o passo nomeie. | - | ### `columns[]` Cada elemento de `columns` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `source` | `string` | sim | - | Coluna recebida, pelo nome que tem no envelope. | - | | `as` | `string` | não | `""` | Novo nome à saída. Vazio = mantém o nome da fonte. | - | ## Exemplo JSON ```json { "columns": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # sort **Ordenar** Ordena os registos por uma ou mais colunas. - **Kind**: `step` - **Key**: `sort` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `keys` | `list` de `map` | não | `[]` | As chaves de ordenação, por prioridade: cada uma sobre uma coluna do envelope em curso, que não é de uma tabela que o passo nomeie. | - | ### `keys[]` Cada elemento de `keys` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `column` | `string` | sim | - | Coluna a comparar, pelo nome que tem no envelope. | - | | `descending` | `boolean` | não | `false` | Ordem descendente. | - | ## Exemplo JSON ```json { "keys": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # switch **Escolher caminho** Encaminha o fluxo conforme o valor de uma coluna ou variável. - **Kind**: `step` - **Key**: `switch` - **Categoria**: `control` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `value` | `string` | não | `""` | O valor a avaliar (`{{record.x}}`/`{{vars.y}}` ou literal), comparado por igualdade com cada caso. | expressões `{{record.coluna}}` | | `cases` | `list` de `string` | não | `[]` | Os casos (pelo menos 1): cada nome é ao mesmo tempo o valor a comparar e um ramo, com a sub-cadeia em `config[]`. O ramo `default` é implícito e não entra aqui. | - | ## Exemplo JSON ```json { "value": "", "cases": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # unwind **Expandir lista** Desdobra uma coluna com listas numa linha por item. - **Kind**: `step` - **Key**: `unwind` - **Categoria**: `transform` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `column` | `string` | não | `""` | A coluna-lista a explodir, pelo nome que tem no envelope em curso (não de uma tabela que o passo nomeie). | - | | `keepNonList` | `boolean` | não | `true` | As linhas em que a coluna não é uma lista (ou é vazia) passam inalteradas; a falso, são descartadas. | - | ## Exemplo JSON ```json { "column": "", "keepNonList": true } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # Gatilhos do WorkflowV2 7 keys declaradas. Como a key de um gatilho entra em `trigger_config.type` e a sua config em `trigger_config.config`, e como criar a automação pela API ou pelo MCP: [Automações (WorkflowV2)](/reference/workflows-v2). | Key | Nome | Descrição | |---|---|---| | [`cron`](./cron.md) | Agendado | Dispara automaticamente no horário agendado. | | [`email.inbound`](./email-inbound.md) | Email (Recebido) | Dispara quando chega um email a uma caixa da organização, com os seus anexos. | | [`file.upload`](./file-upload.md) | Ficheiro (Upload) | Dispara quando é carregado um ficheiro. | | [`input`](./input.md) | Formulário | Pede dados num formulário antes de arrancar; as respostas entram como variáveis do run. | | [`manual`](./manual.md) | Manual | Dispara à mão, no geral ou a partir de uma linha, tabela ou vista. | | [`record.event`](./record-event.md) | Registo (Mudança) | Dispara quando uma linha é criada, alterada ou apagada na tabela observada. | | [`webhook`](./webhook.md) | Webhook | Dispara com um pedido HTTP vindo de fora. | --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # cron **Agendado** Dispara automaticamente no horário agendado. - **Kind**: `trigger` - **Key**: `cron` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mode` | `enumeration` | não | `"interval"` | Modo do agendamento: intervalo, calendário (diário a anual), disparo único ou expressão cron. | - | | `timezone` | `string` | não | `"Europe/Lisbon"` | Fuso IANA em que a hora marcada é hora-de-parede. Só `Europe/Lisbon` e `UTC` são exatos; os outros caem no primeiro. | - | | `everyValue` | `integer` | não | `1` | Quantas unidades entre disparos, no modo de intervalo (mínimo 1). | - | | `everyUnit` | `enumeration` | não | `"days"` | Unidade do intervalo entre disparos. | - | | `atTime` | `string` | não | `"09:00"` | Hora-de-parede do disparo nos modos de calendário, em `HH:mm`. | - | | `daysOfWeek` | `list` de `integer` | não | `[1]` | Dias da semana do modo semanal, em ISO (1=segunda … 7=domingo). | - | | `dayOfMonth` | `integer` | não | `1` | Dia do mês nos modos mensal e anual (1-31), ou o sentinela `last` para o último dia. Dias além do fim do mês encostam ao último. | - | | `businessDayAdjust` | `enumeration` | não | `"none"` | Ajuste quando o dia marcado cai a um fim-de-semana (só sábado e domingo; feriados não contam). O ajuste nunca sai do mês. | - | | `month` | `integer` | não | `1` | Mês do disparo no modo anual (1-12). | - | | `runAt` | `string` | não | - | Instante do disparo único, em ISO-8601 UTC. Só no modo de uma vez. | - | | `cronExpression` | `string` | não | `""` | Expressão cron de 5 campos (minuto hora dia-do-mês mês dia-da-semana), no modo avançado. | - | ## Exemplo JSON ```json { "mode": "interval", "timezone": "Europe/Lisbon", "everyValue": 1, "everyUnit": "days", "atTime": "09:00", "daysOfWeek": [ 1 ], "dayOfMonth": 1, "businessDayAdjust": "none", "month": 1, "cronExpression": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # email.inbound **Email (Recebido)** Dispara quando chega um email a uma caixa da organização, com os seus anexos. - **Kind**: `trigger` - **Key**: `email.inbound` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `mailboxId` | `uuid` | não | `""` | Caixa de correio da organização que alimenta o gatilho. Vazio = gatilho por configurar, não recebe nada. | caixa de correio (uuid) | | `fromContains` | `string` | não | `""` | Só dispara se o remetente contiver este texto. Vazio = qualquer remetente. | - | | `subjectContains` | `string` | não | `""` | Só dispara se o assunto contiver este texto. Vazio = qualquer assunto. | - | | `token` | `string` | não | - | **Descontinuado.** Legado: chave de routing do endereço próprio do workflow. SEGREDO, nunca sai num template. **Segredo.** O exportador substitui este valor por vazio e nomeia o caminho em `redacted[]`: nunca sai num pacote de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "mailboxId": "nome-da-mailbox", "fromContains": "", "subjectContains": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # file.upload **Ficheiro (Upload)** Dispara quando é carregado um ficheiro. - **Kind**: `trigger` - **Key**: `file.upload` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `acceptedExtensions` | `list` de `string` | não | `["pdf","png","jpg","jpeg","webp","csv","xlsx","json"]` | Extensões (sem ponto) aceites na escolha de ficheiros. Vazia, o parse devolve o conjunto por omissão. | - | | `maxFiles` | `integer` | não | `20` | Teto de ficheiros por execução: um disparo leva TODOS os escolhidos num só run. | - | ## Exemplo JSON ```json { "acceptedExtensions": [ "pdf", "png", "jpg", "jpeg", "webp", "csv", "xlsx", "json" ], "maxFiles": 20 } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # input **Formulário** Pede dados num formulário antes de arrancar; as respostas entram como variáveis do run. - **Kind**: `trigger` - **Key**: `input` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `fields` | `list` de `map` | não | `[]` | Os campos que o formulário pede antes de arrancar; cada um semeia uma variável do run com o seu nome. | - | ### `fields[]` Cada elemento de `fields` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `name` | `string` | sim | - | Nome do campo e da variável que ele semeia (`{{vars.}}`). Não é uma coluna de tabela. | - | | `label` | `string` | não | `""` | Rótulo mostrado no formulário. Sai sempre resolvido: vazio, o `toJson()` escreve o nome. | - | | `type` | `enumeration` | não | `"text"` | Tipo do campo, que decide o componente que o pinta e o tipo da coluna virtual. | - | | `required` | `boolean` | não | `false` | Campo de preenchimento obrigatório: sem ele o disparo não avança. Só sai no JSON quando é verdadeiro. | - | | `config` | `json` | não | - | Config do componente que pinta o campo (as opções de uma escolha, o formato de um número): viaja como está. | - | ## Exemplo JSON ```json { "fields": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # manual **Manual** Dispara à mão, no geral ou a partir de uma linha, tabela ou vista. - **Kind**: `trigger` - **Key**: `manual` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `scope` | `enumeration` | não | `"generic"` | De onde parte o disparo: sem contexto, de uma linha, de uma tabela ou de uma vista. | - | | `sourceFeatureId` | `uuid` | não | - | Tabela de ORIGEM das linhas (obrigatória nos âmbitos de linha e de tabela). Não é o alvo: o alvo é escolhido a jusante. | feature (uuid) | | `viewId` | `uuid` | não | - | Vista de origem, no âmbito de vista: o disparo leva as linhas que ela mostra. | vista de `sourceFeatureId` (uuid) | ## Exemplo JSON ```json { "scope": "generic" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # record.event **Registo (Mudança)** Dispara quando uma linha é criada, alterada ou apagada na tabela observada. - **Kind**: `trigger` - **Key**: `record.event` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `modes` | `list` de `enumeration` | não | `["created"]` | Que mudanças disparam: criação, alteração e/ou remoção de uma linha. Os modos escolhidos decidem que outras chaves contam. | - | | `mode` | `enumeration` | não | `"created"` | O primeiro dos `modes`, repetido para quem só sabe ler um modo. Uma config antiga que só traga esta chave vale por um modo. | - | | `featureId` | `uuid` | não | `""` | Tabela observada. Vazio = gatilho por configurar (o gate impede a ativação). | feature (uuid) | | `filter` | `map` | não | - | Filtro sobre o estado DEPOIS do evento (antes, no modo de remoção). Vazio = qualquer linha dispara. | - | | `previousFilter` | `map` | não | - | Filtro sobre o estado ANTES do evento, só no modo de alteração: é o que modela a transição X→Y. | - | | `watchedColumns` | `list` de `string` | não | `[]` | Colunas vigiadas, só no modo de alteração: com elas, o gatilho só dispara quando pelo menos uma mudar. | - | ### `filter` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `filter.rules[]` Cada elemento de `filter.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela observada, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `filter.groups[]` Cada elemento de `filter.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `filter.groups[].rules[]` Cada elemento de `filter.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela observada, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `previousFilter` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do grupo: `and` exige todas, `or` basta uma. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` de `map` | não | - | Subgrupos aninhados, com a mesma forma. | - | ### `previousFilter.rules[]` Cada elemento de `previousFilter.rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela observada, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `previousFilter.groups[]` Cada elemento de `previousFilter.groups` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `combinator` | `enumeration` | não | `"and"` | Como se combinam as regras do subgrupo. | - | | `rules` | `list` de `map` | não | - | As regras do grupo. | - | | `groups` | `list` | não | - | Subgrupos de terceiro nível: varrem-se às cegas (uma FieldDecl const não se pode referir a si própria). | - | ### `previousFilter.groups[].rules[]` Cada elemento de `previousFilter.groups[].rules` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `id` | `string` | não | - | Identificador da regra, gerado pela app. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `columnName` | `string` | não | - | Coluna da tabela observada, POR NOME. | coluna de `featureId` (nome) | | `operator` | `string` | não | - | Operador da comparação. | - | | `value` | `string` | não | - | Valor da comparação: dado de utilizador. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `secondValue` | `string` | não | - | Segundo valor, usado pelos operadores de intervalo. Só aparece no JSON quando não é nulo. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "modes": [ "created" ], "mode": "created", "featureId": "$f_exemplo", "watchedColumns": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # webhook **Webhook** Dispara com um pedido HTTP vindo de fora. - **Kind**: `trigger` - **Key**: `webhook` - **Categoria**: `trigger` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `token` | `string` | não | `""` | Chave de routing da URL pública e credencial do endpoint: SEGREDO, nunca sai num template. **Segredo.** O exportador substitui este valor por vazio e nomeia o caminho em `redacted[]`: nunca sai num pacote de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `description` | `string` | não | `""` | Nota livre do autor sobre para que serve este webhook. | - | | `secret` | `string` | não | `""` | Segredo de assinatura HMAC-SHA256 dos pedidos: SEGREDO, nunca sai num template. **Segredo.** O exportador substitui este valor por vazio e nomeia o caminho em `redacted[]`: nunca sai num pacote de template. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ## Exemplo JSON ```json { "token": "", "description": "", "secret": "" } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # Entidades de estrutura 7 keys declaradas. | Key | Nome | Descrição | |---|---|---| | [`feature`](./feature.md) | Tabela (config) | A coluna `config` de uma Feature. | | [`featurecolumn`](./featurecolumn.md) | Coluna (campos de topo) | As COLUNAS DE TOPO de uma Featurecolumn que decidem como a coluna se comporta - não um jsonb. | | [`module.rail_order_config`](./module-rail_order_config.md) | Ordem dos rails do módulo | A coluna `rail_order_config` de um Module - uma coluna jsonb PRÓPRIA, não uma sub-chave de um `config`. | | [`organization`](./organization.md) | Organização (config) | A coluna `config` de uma Organization. | | [`rail`](./rail.md) | Rail (config) | A coluna `config` de um Rail: uma LISTA de um elemento, com a categoria do rail e os separadores de vista que ele mostra. | | [`workspace`](./workspace.md) | Workspace (config) | A coluna `config` de um Workspace. | | [`workspace.module_order_config`](./workspace-module_order_config.md) | Ordem dos módulos do workspace | A coluna `module_order_config` de um Workspace - uma coluna jsonb PRÓPRIA, não uma sub-chave do `config`. | --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # feature **Tabela (config)** A coluna `config` de uma Feature. - **Kind**: `structure` - **Key**: `feature` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `shared` | `boolean` | não | - | Tabela partilhada entre workspaces. | - | | `changesEnabled` | `boolean` | não | - | **Descontinuado.** Legado: já não liga nem desliga nada. | - | | `messagesEnabled` | `boolean` | não | - | Liga as mensagens por linha. | - | | `notifyChanges` | `enumeration` | não | `"people"` | Quem é avisado quando uma linha muda ou é eliminada: ninguém, as pessoas nas colunas de pessoa da linha, os subscritores da tabela ou ambos. | - | | `notifyMessages` | `enumeration` | não | `"none"` | Quem é avisado dos comentários e da conversa de uma linha, com os mesmos quatro alvos do `notifyChanges`. | - | | `notifySubscriberRoles` | `list` de `string` | não | `[]` | Papéis cujos membros entram na lista de subscritores da tabela, resolvidos no envio contra o workspace da tabela e a organização. | - | | `notificationLabelColumn` | `uuid` | não | - | Coluna usada como rótulo do registo no sino de notificações. | coluna (uuid) | | `_managed_by_workflow` | `uuid` | não | - | Automação WorkflowV2 que materializa (é dona) desta tabela - o id do GRUPO de versões, não o da versão. | workflow V2 (uuid) | ## Exemplo JSON ```json { "notifyChanges": "people", "notifyMessages": "none", "notifySubscriberRoles": [] } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # featurecolumn **Coluna (campos de topo)** As COLUNAS DE TOPO de uma Featurecolumn que decidem como a coluna se comporta - não um jsonb. A `config` da coluna varre-se por direito próprio, como `(component, default_component)`. - **Kind**: `structure` - **Key**: `featurecolumn` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `type` | `enumeration` | não | `"text"` | Como o valor CRU da coluna é interpretado; `string` é alias legado de `text`. | - | | `default_component` | `enumeration` | não | `"textfield"` | Componente com que a coluna se edita e se mostra; é ele que diz como ler a `config` da coluna. Inclui o alias `workflow_button` (= `execution`), que a API aceita. | - | | `initial_value` | `string` | não | `""` | Valor com que a coluna nasce numa linha nova. `opaque`: é conteúdo escrito por quem configura, não referência. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `read_only` | `boolean` | não | `false` | A coluna mostra-se mas não se edita. | - | | `required` | `boolean` | não | `false` | O formulário não grava sem esta coluna preenchida. | - | | `hidden` | `boolean` | não | `false` | A coluna não aparece por omissão nas vistas. | - | | `inline_editable` | `boolean` | não | `false` | A coluna edita-se directamente na grelha. | - | | `externally_visible` | `boolean` | não | `false` | A coluna é projetada para o portal do cliente. Não concede acesso a nada por si. | - | | `order` | `integer` | não | - | Posição da coluna na tabela; vazio = vai para o fim. | - | ## Exemplo JSON ```json { "type": "text", "default_component": "textfield", "initial_value": "", "read_only": false, "required": false, "hidden": false, "inline_editable": false, "externally_visible": false } ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # module.rail_order_config **Ordem dos rails do módulo** A coluna `rail_order_config` de um Module - uma coluna jsonb PRÓPRIA, não uma sub-chave de um `config`. - **Kind**: `structure` - **Key**: `module.rail_order_config` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `order` | `list` de `uuid` | não | - | Ids dos rails na ordem em que aparecem na barra lateral; os que faltarem vão para o fim por ordem alfabética. | - | | `updated_at` | `string` | não | - | Carimbo ISO 8601 de quando esta ordem foi gravada. Rasto apenas: nenhum leitor o usa. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # organization **Organização (config)** A coluna `config` de uma Organization. Quase tudo o que lá está é estado da própria organização (plano, faturação, segredos) e nunca sai num template - daí tanto `opaque`. - **Kind**: `structure` - **Key**: `organization` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `variables` | `json` | não | - | Variáveis da organização: mapa livre `nome → valor`. | - | | `secretVariables` | `list` de `string` | não | - | Nomes das variáveis marcadas como secretas. Os VALORES vivem no `variables`: esta lista é só a marca. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `color` | `enumeration` | não | - | Cor nomeada da organização, escolhida no diálogo de gestão. | - | | `defaultWorkspaceId` | `uuid` | não | - | Workspace a que a organização abre por omissão. | workspace (uuid) | | `entitlements` | `map` | não | - | O plano subscrito e os seus limites, espelhados na organização. `opaque`: é estado de subscrição, escrito pelo servidor, nunca exportado. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | | `billing` | `map` | não | - | Estado de cobrança em falha (dunning), escrito pelo servidor. `opaque`: estado de faturação, nunca se exporta. Opaco: transporta dados do utilizador e nenhum resolvedor entra aqui. | - | ### `entitlements` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `plan` | `string` | não | - | Nome do tier (`free`, `basic`, `pro`, `scale`, `enterprise`). | - | | `plan_label` | `string` | não | - | Nome do tier como se mostra ao utilizador. | - | | `is_free` | `boolean` | não | - | Verdadeiro nos tiers sem pagamento. | - | | `updated_at` | `string` | não | - | Quando o espelho do tier foi escrito. | - | | `features` | `map` | não | - | O bloco `features` do plano, copiado em cheio do catálogo de planos. | - | ### `entitlements.features` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `support` | `string` | não | - | Nível de suporte do tier (`community`, `email`, `priority`, `dedicated`). | - | | `limits` | `map` | não | - | Tetos do plano; `null` = ilimitado. | - | | `capabilities` | `map` | não | - | O que o plano deixa fazer; o cliente lê por `capability(nome)` e o servidor impõe à parte. | - | ### `entitlements.features.limits` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `workspaces` | `integer` | não | - | Máximo de workspaces da organização. | - | | `records_per_workspace` | `integer` | não | - | Máximo de linhas por workspace. | - | | `storage_gb` | `integer` | não | - | Armazenamento incluído, em GB. | - | | `kiosk_terminals` | `integer` | não | - | Máximo de terminais de quiosque; o catálogo de planos ainda não o preenche. | - | ### `entitlements.features.capabilities` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `build_from_scratch` | `boolean` | não | - | Capacidade `build_from_scratch` do plano. | - | | `manual_workflows` | `boolean` | não | - | Capacidade `manual_workflows` do plano. | - | | `automations` | `boolean` | não | - | Capacidade `automations` do plano. | - | | `ai_chat` | `boolean` | não | - | Capacidade `ai_chat` do plano. | - | | `ai_full` | `boolean` | não | - | Capacidade `ai_full` do plano. | - | | `advanced_views` | `boolean` | não | - | Capacidade `advanced_views` do plano. | - | | `api` | `boolean` | não | - | Capacidade `api` do plano. | - | | `portals` | `boolean` | não | - | Capacidade `portals` do plano. | - | | `white_label` | `boolean` | não | - | Capacidade `white_label` do plano. | - | | `fine_permissions` | `boolean` | não | - | Capacidade `fine_permissions` do plano. | - | | `reusable_templates` | `boolean` | não | - | Capacidade `reusable_templates` do plano. | - | | `sso` | `boolean` | não | - | Capacidade `sso` do plano. | - | | `byok` | `boolean` | não | - | Capacidade `byok` do plano. | - | | `sla` | `boolean` | não | - | Capacidade `sla` do plano. | - | ### `billing` | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `past_due` | `boolean` | não | - | Verdadeiro enquanto houver pagamento falhado em retentativa; é o que faz aparecer o aviso de cobrança no cliente. O acesso mantém-se. | - | | `since` | `string` | não | - | Instante em que a falha foi registada. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # rail **Rail (config)** A coluna `config` de um Rail: uma LISTA de um elemento, com a categoria do rail e os separadores de vista que ele mostra. - **Kind**: `structure` - **Key**: `rail` - **Categoria**: `estrutura` - **Envelope**: lista de um só elemento (a config vive em `config[0]`) :::warning Envelope de um só elemento `Rail.config` é uma **lista com um único elemento**: a configuração vive em `config[0]`, não em `config`. Uma config escrita como mapa cru é lida de qualquer maneira, mas entra nos relatórios como desvio de envelope. ::: ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `category` | `string` | não | - | Agrupador do rail na barra lateral; ausente ou vazio = sem categoria. | - | | `views` | `list` de `map` | não | `[]` | Os separadores do rail, na ordem em que aparecem. | - | ### `views[]` Cada elemento de `views` é um objeto: | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `label` | `string` | sim | - | Nome do separador do rail, mostrado ao utilizador. | - | | `viewType` | `enumeration` | sim | - | Tipo de vista que o separador mostra. É também o campo irmão que diz como ler o `config` embebido. Sem omissão: o `table` do `fromJson` é fallback de LEITURA, não valor por omissão do construtor (regra D.4). | - | | `featureId` | `uuid` | não | - | Tabela que o separador mostra. | feature (uuid) | | `viewName` | `string` | não | - | Nome da vista guardada (a linha `View` de `(featureId, viewType, viewName)`); `default` é a vista sem nome - e é fallback de LEITURA do `fromJson`, não omissão do construtor (regra D.4). | vista de `featureId` (nome) | | `config` | `json` | não | - | Config de vista INTEIRA, embebida no rail: o tipo vem do irmão `viewType`. Só é usada quando `useRailConfig` é verdadeiro - senão vale a linha `View` global. | config de vista cujo tipo vem de `viewType` ([índice](../vistas/index.md)) | | `useRailConfig` | `boolean` | não | `false` | Verdadeiro = o separador usa o `config` guardado no rail; falso = usa a linha `View` global. | - | | `title` | `string` | não | - | **Descontinuado.** Nome alternativo de `label`, ainda aceite na leitura; a app já não o escreve. | - | | `view_type` | `enumeration` | não | - | **Descontinuado.** Nome alternativo de `viewType`, ainda aceite na leitura; a app já não o escreve. | - | | `type` | `enumeration` | não | - | **Descontinuado.** Nome alternativo de `viewType`, ainda aceite na leitura; a app já não o escreve. | - | | `feature_id` | `uuid` | não | - | **Descontinuado.** Nome alternativo de `featureId`, ainda aceite na leitura; a app já não o escreve. | feature (uuid) | | `feature` | `uuid` | não | - | **Descontinuado.** Nome alternativo de `featureId`, ainda aceite na leitura; a app já não o escreve. | feature (uuid) | | `view_name` | `string` | não | - | **Descontinuado.** Nome alternativo de `viewName`, ainda aceite na leitura; a app já não o escreve. | vista de `featureId` (nome) | | `name` | `string` | não | - | **Descontinuado.** Nome alternativo de `viewName`, ainda aceite na leitura; a app já não o escreve. | vista de `featureId` (nome) | | `viewConfig` | `json` | não | - | **Descontinuado.** Nome alternativo de `config`, ainda aceite na leitura; a app já não o escreve. | config de vista cujo tipo vem de `viewType` ([índice](../vistas/index.md)) | | `view_config` | `json` | não | - | **Descontinuado.** Nome alternativo de `config`, ainda aceite na leitura; a app já não o escreve. | config de vista cujo tipo vem de `viewType` ([índice](../vistas/index.md)) | ## Exemplo JSON ```json [ { "views": [] } ] ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # workspace **Workspace (config)** A coluna `config` de um Workspace. - **Kind**: `structure` - **Key**: `workspace` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `variables` | `json` | não | - | Variáveis do workspace: mapa livre `nome → valor`, escrito pelo formulário do workspace. | - | | `color` | `enumeration` | não | - | Cor nomeada do workspace, mostrada no cartão do workspace. O formulário do workspace não a escreve (só `variables`), logo o que está na base veio de outro escritor. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # workspace.module_order_config **Ordem dos módulos do workspace** A coluna `module_order_config` de um Workspace - uma coluna jsonb PRÓPRIA, não uma sub-chave do `config`. - **Kind**: `structure` - **Key**: `workspace.module_order_config` - **Categoria**: `estrutura` - **Envelope**: mapa (um objeto JSON em `config`) ## Campos | Chave | Tipo | Obrigatório | Omissão | Descrição | Referência | |---|---|---|---|---|---| | `order` | `list` de `uuid` | não | - | Ids dos módulos na ordem em que aparecem; os que faltarem vão para o fim por ordem alfabética. | - | | `updated_at` | `string` | não | - | Carimbo ISO 8601 de quando esta ordem foi gravada. Rasto apenas: nenhum leitor o usa. | - | ## Exemplo JSON ```json {} ``` --- Gerado de `definitions.json` versão `17f3e0bc59d9`. Esta página nasce no build: não se edita à mão. --- # Ferramentas MCP 32 ferramentas publicadas em `https://ai.out-do.app/mcp`. Cada ferramenta diz as credenciais que a alcançam, porque a superfície não é a mesma nas duas: uma chave de API chega às escritas de estrutura e um JWT de utilizador ao relatório. A autenticação está em [MCP](/reference/mcp/). ## `aggregate_rows` **Credenciais:** chave de API ou JWT de utilizador. Aggregate a feature's rows: count, or sum/avg of a numeric column (count takes no column). Filters: 'column:op:value', repeatable. Text ops: eq,neq,gt,gte,lt,lte (text compare), like,ilike (* wildcards), contains,ncontains,startswith,endswith (case-insensitive), in (value '\|'-separated), is (null\|true\|false). Numeric: eqn,neqn,gtn,gten,ltn,lten (stored value must be a JSON number). Prefix any op with 'not.' to negate. match='any' combines filters with OR (default AND). Reserved columns: id, created_at, updated_at; any other column is a data key. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `column` | `string` | não | Opcional. | | `feature_id` | `string` | sim | - | | `filters` | `string[]` | não | Opcional. | | `match` | `string` | não | Por omissão: `"all"`. | | `op` | `string` | sim | - | ## `apply_template` **Credenciais:** chave de API. Apply a template's package to a workspace. Starts a background job and returns its id immediately: poll get_template_job for progress and the final report. Structure lands in one transaction; rows land in batches. Applying the same template to the same workspace twice creates nothing the second time. Starting a second job for the same pair while one is still running is refused — poll the one that runs. `resolutions` answers the package's dependencies, one entry per ref: \{"f_clientes": \{"action": "map", "id": "<existing feature id>", "columns": \{"<column ref>": "<column id>"\}\}\}, \{"action": "import"\}, or \{"action": "skip"\} — which clears every reference to that dependency and reports each cleared field with reason `dependencia_saltada`; nothing is left pointing at an id from the source organization. A mapped id has to be a table of the destination workspace, or one shared across its organization — or, for a `channel` dependency, a named channel of that organization — and the `columns` of a mapped dependency have to cover the columns the package uses — one left out is refused, naming it. `rows_modes` says what to do with each table's rows, one entry per feature ref: `all` (the default), `missingByKey` — only the rows whose key is not in the destination yet, possible ONLY when the package carries a verified key for that table (`keyColumn` with `keyUnique: true`), and refused naming the ref when it does not — or `none`. `include_rows: false` is the global switch and wins over every mode. Pass `job_id` to resume a job that stopped half way (omit it and the server resumes the last unfinished one by itself). Call list_templates to get `template_id`. A refusal you can fix comes back naming what was refused and the ref to correct in `resolutions` or `rows_modes` — read the ref instead of retrying the same body. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `idempotency_key` | `string` | não | Opcional. | | `include_rows` | `boolean` | não | Por omissão: `true`. | | `job_id` | `string` | não | Opcional. | | `resolutions` | `object` | não | Opcional. | | `rows_modes` | `object` | não | Opcional. | | `template_id` | `string` | sim | - | | `workspace_id` | `string` | sim | - | ## `create_column` **Credenciais:** chave de API. Create a column on a feature. `type` is how the raw value is stored (text, number, date, datetime, bool); `default_component` is how it is edited and shown (textfield, select, linked_select, user, formula, ...) and its `config` shape depends on it. Row data is keyed by the column NAME, so pick it once and keep it. Call get_definitions for the allowed values and config keys. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `config` | `object` | não | Opcional. | | `default_component` | `string` | não | Opcional. | | `feature_id` | `string` | sim | - | | `hidden` | `boolean` | não | Por omissão: `false`. | | `idempotency_key` | `string` | não | Opcional. | | `inline_editable` | `boolean` | não | Por omissão: `false`. | | `label` | `string` | não | Opcional. | | `name` | `string` | sim | - | | `order` | `integer` | não | Opcional. | | `read_only` | `boolean` | não | Por omissão: `false`. | | `required` | `boolean` | não | Por omissão: `false`. | | `type` | `string` | sim | - | ## `create_feature` **Credenciais:** chave de API. Create a feature (a data table) inside a workspace. `name` is the technical handle, `label` is what people read. Columns come next, with create_column. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `config` | `object` | não | Opcional. | | `idempotency_key` | `string` | não | Opcional. | | `label` | `string` | não | Opcional. | | `name` | `string` | sim | - | | `workspace_id` | `string` | sim | - | ## `create_module` **Credenciais:** chave de API. Create a navigation module inside a workspace. `name` is the technical handle (lowercase, no spaces), `label` is what people read, `icon` is optional. Writes IMMEDIATELY; needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `icon` | `string` | não | Opcional. | | `idempotency_key` | `string` | não | Opcional. | | `label` | `string` | sim | - | | `name` | `string` | sim | - | | `workspace_id` | `string` | sim | - | ## `create_rail` **Credenciais:** chave de API. Create a navigation rail inside a module. `config` is the single-item list [\{"views": [\{"viewType": "table", "featureId": "<uuid>", "viewName": "<name>"\}]\}] naming the views the rail shows; create the views first and pass their feature id and name. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `config` | `object[]` | sim | - | | `idempotency_key` | `string` | não | Opcional. | | `label` | `string` | sim | - | | `module_id` | `string` | sim | - | | `path` | `string` | não | Por omissão: `""`. | ## `create_rows` **Credenciais:** chave de API ou JWT de utilizador. Create one or more rows in a feature. `rows` is a list of data objects (\{column_name: value\}, only existing columns). Atomic (all-or-nothing), up to 200. Validated against the feature's columns. Writes IMMEDIATELY under the caller's permissions (a user's RLS, or an API key's scopes) — confirm with the human you are acting for first. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | | `idempotency_key` | `string` | não | Opcional. | | `rows` | `object[]` | sim | - | ## `create_view` **Credenciais:** chave de API. Create a saved view over a feature. `type` is one of the view registry's kinds (table, kanban, calendar, form, ...) and `config` depends on it (a kanban needs `groupBy`, for instance). `name` defaults to a slug of the `label`. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `config` | `object` | não | Opcional. | | `feature_id` | `string` | sim | - | | `idempotency_key` | `string` | não | Opcional. | | `label` | `string` | sim | - | | `name` | `string` | não | Opcional. | | `type` | `string` | sim | - | ## `create_workflow_v2` **Credenciais:** chave de API. Create an automation. It is born as a DRAFT, which never fires: pass is_draft=false to create AND apply it, which leaves it applied but INACTIVE (a human activates it in the app). Validate first with validate_workflow_v2: a definition with errors is rejected. Needs the `structure` scope. Pass a stable idempotency_key to make a retry safe (same key → same result). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `description` | `string` | não | Opcional. | | `graph_config` | `object` | sim | - | | `idempotency_key` | `string` | não | Opcional. | | `is_draft` | `boolean` | não | Por omissão: `true`. | | `label` | `string` | não | Opcional. | | `name` | `string` | sim | - | | `trigger_config` | `object` | sim | - | | `workspace_id` | `string` | sim | - | ## `delete_row` **Credenciais:** chave de API ou JWT de utilizador. Delete one row by id. Irreversible. Writes IMMEDIATELY under the caller's permissions (a user's RLS, or an API key's scopes) — confirm with the human you are acting for first. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | | `row_id` | `string` | sim | - | ## `generate_report` **Credenciais:** JWT de utilizador. Generate a self-contained HTML report artifact for a workspace using OutDo's internal report agent (samples the schema + a few rows, then authors a dynamic document). Returns \{id, title, artifact, dataContract\}; the artifact reads live data from window.OUTDO_DATA injected by the OutDo client at render time. Nothing is saved — the caller decides what to do with the artifact. Slow (runs an LLM agent): seconds to minutes. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `message` | `string` | sim | - | | `provider` | `string` | não | Opcional. | | `workspace_id` | `string` | sim | - | ## `get_definitions` **Credenciais:** chave de API ou JWT de utilizador. The config reference catalog: allowed column types and components, view types and their config shapes, feature/workspace/rail/module config keys, and row-data conventions. Use it to understand what each entity's config accepts when interpreting the schema. _Sem argumentos._ ## `get_feature` **Credenciais:** chave de API ou JWT de utilizador. Get one feature's detail by id. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | ## `get_schema` **Credenciais:** chave de API ou JWT de utilizador. The whole structure the user can see in ONE call: workspaces → features → columns + views, nested. ALWAYS use this to discover structure instead of chaining list_workspaces/list_features/list_columns. Pass workspace_id to restrict to one workspace; if the response has truncated=true, repeat with a workspace_id. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `workspace_id` | `string` | não | Opcional. | ## `get_template` **Credenciais:** chave de API. One template with its package (`manifest`): the items it installs, the dependencies it needs resolved and the plan it applies. Read it before apply_template when you need to know what the template will create. Returns 404 when the template does not exist or is not visible to the caller. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `template_id` | `string` | sim | - | ## `get_template_job` **Credenciais:** chave de API. Read the state of a template apply job. `status` is `queued` (not started yet), `structure` (creating tables, columns and views), `rows` (loading data in batches), `done`, `failed` or `cancelled`. `report` counts what was created, skipped and inserted, plus `published` — how many automations came out published instead of draft — and is only complete once the status is `done`; `error` says what stopped a `failed` one. Poll it after apply_template instead of assuming the job finished. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `job_id` | `string` | sim | - | ## `get_workflow_v2` **Credenciais:** chave de API. Read one automation by its `workflow_id`: the active version, or the latest applied one when it is paused. Returns `trigger_config` and `graph_config`. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `workflow_id` | `string` | sim | - | ## `list_columns` **Credenciais:** chave de API ou JWT de utilizador. List a feature's columns (name, label, type) in display order. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | ## `list_features` **Credenciais:** chave de API ou JWT de utilizador. List the features (tables) of a workspace. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `workspace_id` | `string` | sim | - | ## `list_modules` **Credenciais:** chave de API. List the navigation modules of a workspace (id, name, label, icon). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `workspace_id` | `string` | sim | - | ## `list_organizations` **Credenciais:** chave de API ou JWT de utilizador. List the organizations the connected user belongs to. _Sem argumentos._ ## `list_rails` **Credenciais:** chave de API. List the navigation rails of a module. A rail's `config` lists the views it shows, as a single-item list: [\{"views": [\{viewType, featureId, viewName\}]\}]. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `module_id` | `string` | sim | - | ## `list_templates` **Credenciais:** chave de API. The template catalog: platform templates (`system`), shared ones (`public`) and the caller's own organization's. Filter by `scope` (organization\|workspace\|module\|feature) and `visibility` (system\|org\|public). Returns a page `{items, next_cursor}` without the package itself — read one template to get it. Use this to find the `template_id` that apply_template needs. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `cursor` | `string` | não | Opcional. | | `limit` | `integer` | não | Por omissão: `25`. | | `scope` | `string` | não | Opcional. | | `visibility` | `string` | não | Opcional. | ## `list_views` **Credenciais:** chave de API. List the saved views of a feature (id, name, label, type). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | ## `list_workflows_v2` **Credenciais:** chave de API. List the automations of a workspace. Each item is ONE VERSION; `workflow_id` groups the versions of a logical workflow and `is_active` marks the one that fires. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `workspace_id` | `string` | sim | - | ## `list_workspaces` **Credenciais:** chave de API ou JWT de utilizador. List the workspaces the connected user can see, optionally only those of one organization. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `organization_id` | `string` | não | Opcional. | ## `query_rows` **Credenciais:** chave de API ou JWT de utilizador. Read rows of a feature. Filters: 'column:op:value', repeatable. Text ops: eq,neq,gt,gte,lt,lte (text compare), like,ilike (* wildcards), contains,ncontains,startswith,endswith (case-insensitive), in (value '\|'-separated), is (null\|true\|false). Numeric: eqn,neqn,gtn,gten,ltn,lten (stored value must be a JSON number). Prefix any op with 'not.' to negate. match='any' combines filters with OR (default AND). Reserved columns: id, created_at, updated_at; any other column is a data key. Results are capped at 200 rows — use filters/aggregate instead of paging through everything. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `feature_id` | `string` | sim | - | | `fields` | `string[]` | não | Opcional. | | `filters` | `string[]` | não | Opcional. | | `limit` | `integer` | não | Por omissão: `20`. | | `match` | `string` | não | Por omissão: `"all"`. | | `sort` | `string` | não | Opcional. | ## `sign_file` **Credenciais:** chave de API ou JWT de utilizador. Get a temporary signed download URL for a stored file by its path (from a row's file/metadata field). Returns \{url, expires_in\}; fetch the URL to read the file. The path must be one the connected user can see (RLS). | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `expires_in` | `integer` | não | Opcional. | | `path` | `string` | sim | - | ## `suggest_template_mappings` **Credenciais:** chave de API. Before applying a template, find out which existing tables of a workspace its dependencies probably mean. Returns, per dependency, ranked candidates with a confidence from 0 to 1 and the column candidates inside each, plus `proposed` (`map`, `import` or `decide`). Read-only. Pass the chosen ids to apply_template as `resolutions` instead of guessing. Needs the `structure` scope. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `template_id` | `string` | sim | - | | `workspace_id` | `string` | sim | - | ## `update_row` **Credenciais:** chave de API ou JWT de utilizador. Update one row by id. By default MERGES the given keys into the row (merge=true); pass merge=false to replace the whole data object. A null value deletes that key (merge mode). Writes IMMEDIATELY under the caller's permissions (a user's RLS, or an API key's scopes) — confirm with the human you are acting for first. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `data` | `object` | sim | - | | `feature_id` | `string` | sim | - | | `merge` | `boolean` | não | Por omissão: `true`. | | `row_id` | `string` | sim | - | ## `update_view` **Credenciais:** chave de API. Partially update a saved view. `patch` carries only the fields to change (`label`, `name`, `config`); `config` is replaced whole, not merged. Needs the `structure` scope. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `patch` | `object` | sim | - | | `view_id` | `string` | sim | - | ## `validate_workflow_v2` **Credenciais:** chave de API. Check an automation definition WITHOUT writing it. `trigger_config` is \{"type": "<trigger key>", "config": \{...\}\} and `graph_config` is \{"steps": [\{"id": "...", "key": "<step key>", "config": \{...\}\}]\}. Returns \{ok, issues\}; `ok` means no errors (warnings never block). Each issue carries a stable `code` and a `target` saying where it is fixed. ALWAYS call this before create_workflow_v2. | Argumento | Tipo | Obrigatório | Descrição | |---|---|---|---| | `graph_config` | `object` | sim | - | | `trigger_config` | `object` | sim | - | | `workflow_id` | `string` | não | Opcional. | | `workspace_id` | `string` | não | Opcional. | --- Gerado de `mcp_tools.json`. Esta página nasce no build: não se edita à mão.