# Interface, dados e achados

> Comandos, menus de mensagem, abas nativas e componentes; armazenamento, configurações, credenciais e achados com evidência.

- Idioma: pt-BR
- URL canônica: https://netcattest.com/catsuite/docs/extensoes/interface-e-dados
- Seção: Extensões
- Atualizado: 2026-10-05
- Outro idioma (en): https://netcattest.com/catsuite/en/docs/extensions/ui-and-data

## Comandos

```js
cat.commands.register('lab.analisar', {'pt-BR': 'Analisar', en: 'Analyze'}, async args => {
  await cat.storage.set('ultimaAnalise', args);
  return {ok: true};
});

const execucao = await cat.commands.execute('lab.analisar', {origem: 'aba'});
```

IDs seguem `[a-z][a-z0-9_.-]{1,79}` e não se repetem. `cat.commands.execute` inicia outro comando da mesma extensão e devolve o identificador da execução. Exige `commands`.

## Menus de mensagem

```js
cat.ui.menu.register({
  id: 'lab.menu',
  title: {'pt-BR': 'Analisar com o laboratório', en: 'Analyze with the lab'},
  command: 'lab.analisar',
  contexts: ['request', 'response']
});
```

Ações de menu recebem a request e a response brutas, a `url` e o `source`. Exige `ui.menu`, `commands` e, para conteúdo HTTP, `traffic.read`.

## Abas nativas

```js
cat.ui.tab.register({
  id: 'lab.painel',
  title: {'pt-BR': 'Laboratório', en: 'Laboratory'},
  components: [
    {type: 'text', text: {'pt-BR': 'Pronto para analisar.', en: 'Ready to analyze.'}},
    {type: 'field', id: 'nota', label: {'pt-BR': 'Nota', en: 'Note'}},
    {type: 'button', label: {'pt-BR': 'Salvar nota', en: 'Save note'}, command: 'lab.salvar'}
  ]
});

cat.commands.register('lab.salvar', {'pt-BR': 'Salvar nota', en: 'Save note'}, async args => {
  await cat.storage.set('nota', args.nota || '');
  cat.ui.update('lab.painel', [{type: 'text', text: {'pt-BR': 'Nota salva.', en: 'Note saved.'}}]);
});
```

Os valores dos campos são enviados como argumentos do comando do botão. Exige `ui.tab`.

## Componentes

Os componentes são renderizados de forma nativa, sem HTML ou JavaScript visual.

| Tipo | Campos | Desde |
|---|---|---|
| `text` | `text` | v1 |
| `button` | `label`, `command`, `args` | v1 |
| `field` e `filter` | `id`, `label`, `value` | v1 |
| `list` | `items` | v1 |
| `table` | `columns`, `rows` | v1 |
| `http` | `message` | v1 |
| `progress` | `value` | v1 |
| `json` | `label`, `value` | SDK 1.2 |
| `diff` | `label`, `before`, `after` | SDK 1.2 |
| `timeline` | `label`, `items` com `title`, `detail` e `time` | SDK 1.2 |
| `chart` | `label`, `values` com `label` e `value` | SDK 1.2 |
| `graph` | `label`, `nodes` e `edges` com `from` e `to` | SDK 1.2 |

Textos humanos precisam de `pt-BR` e `en`. Campos técnicos e identificadores permanecem como estão.

## Armazenamento

```js
await cat.storage.set('contador', 1);
const contador = await cat.storage.get('contador');
await cat.storage.delete('contador');
```

Os dados JSON ficam separados por extensão, com quota de 10 MiB e até 128 KiB por valor. O aplicativo usa um banco versionado com transações, e os dados sobrevivem às atualizações. Exige `storage`.

## Configurações

```js
const laboratorio = cat.settings.get('laboratory');
```

`cat.settings.get` lê os valores de `settings`, validados pelo `settingsSchema` do [manifesto](https://netcattest.com/catsuite/docs/extensoes/manifesto).

## Credenciais

Cadastre credenciais na tela da extensão e informe apenas o identificador no código ou no formulário. Elas ficam protegidas pelo Android Keystore, são adicionadas pelo host como `Bearer` e nunca entram nas exportações.

## Achados

```js
cat.events.on('http.response', async message => {
  const cache = message.headers.find(h => h.name.toLowerCase() === 'cache-control');
  if (!cache || !cache.value.includes('public')) return;
  await cat.findings.add({
    fingerprint: 'cache-publico:' + cat.http.parseUrl(message.url).pathname,
    title: {'pt-BR': 'Resposta com cache público', en: 'Response with public cache'},
    description: {'pt-BR': 'A resposta declara Cache-Control público.', en: 'The response declares public Cache-Control.'},
    severity: 'low',
    confidence: 'observed',
    url: message.url,
    evidence: {request: message.request, response: message}
  });
});
```

| Campo | Valores |
|---|---|
| `severity` | `info`, `low`, `medium`, `high`, `critical` |
| `confidence` | `observed`, `confirmed`, `hypothesis` |
| `status` | `open`, `resolved`, `false_positive` |

O `fingerprint` consolida achados repetidos e preserva o estado escolhido pelo usuário. Exige `findings` e, neste exemplo, `traffic.read`.

## Exportar com .catdata

Um `.catdata` contém dados e achados selecionados. Evidências são opcionais; headers sensíveis, corpos e parâmetros de URL são ocultados na exportação, e credenciais nunca são exportadas. A importação valida o formato e exige que a extensão correspondente já esteja instalada.
