# Um serviço conectado com WU

Publique um contrato, autorize um cliente e percorra solicitações RPC com versões, validação, cancelamento e limpeza.

<span id="del-cliente-a-una-respuesta"></span>

<span class="section-anchor" id="section-1"></span>

## Do cliente a uma resposta

Se esta é sua primeira integração RPC, comece por [Uma soma entre aplicações](/pt/docs/guides/rpc-between-apps/). Essa receita inclui todos os arquivos para seu workspace. Este capítulo amplia o padrão com descoberta de contratos, cancelamento e o serviço executável do laboratório.

Em [Serviços e RPC](/pt/labs/backend/), duas aplicações WU colaboram com permissões diferentes. O provedor publica qual serviço oferece e atende um canal; o cliente consome esse contrato e solicita uma resposta. O percurso permite testar dados válidos, erros, incompatibilidade de versões, cancelamento e remoção do provedor.

```text
Cliente WU
  → consume('docs:backend:service', '^1.0.0')
  → request('docs:backend:request', solicitud)
  → handler del proveedor WU
  → respuesta { status, headers, body, execution }
```

As solicitações passam pelo RPC do WU dentro do runtime. `status`, `headers` e `body` são membros do contrato de resposta; não significam que o portal abriu uma conexão HTTP ou uma porta de servidor.

<span id="solicitar-y-conceder-la-autoridad-necesaria"></span>

<span class="section-anchor" id="section-2"></span>

## Solicitar e conceder a autoridade necessária

Cada manifesto declara as capacidades que sua app solicita. O provedor precisa de `rpc.provide:docs:backend:*`; o cliente, de `rpc.call:docs:backend:*`. O shell concede esses escopos ao inicializar ambas as aplicações:

```js
await wu.init({
  sandbox: 'module',
  apps: [
    {
      name: 'backend-service',
      url: '/microfrontends/backend-service',
      grants: ['rpc.provide:docs:backend:*'],
    },
    {
      name: 'backend-client',
      url: '/microfrontends/backend-client',
      grants: ['rpc.call:docs:backend:*'],
    },
  ],
});
```

As solicitações do manifesto e as concessões do shell devem corresponder. A permissão efetiva vem da interseção delas. O código da app usa `context.wu`, a fachada com escopo recebida em `mount`; não precisa capturar o singleton privilegiado do host. A [referência de permissões](/pt/docs/framework/security/) detalha os escopos e sua revogação.

<span id="publicar-el-canal-y-el-contrato"></span>

<span class="section-anchor" id="section-3"></span>

## Publicar o canal e o contrato

Dentro da montagem do provedor, `appWu` é essa fachada com escopo e `handleRequest` implementa o serviço:

```js
const release = appWu.handle(
  'docs:backend:request',
  handleRequest,
  { version: '1.0.0', allow: ['backend-client'] },
);

const contract = appWu.provide(
  'docs:backend:service',
  { channel: 'docs:backend:request', method: 'POST' },
  {
    version: '1.0.0',
    shape: { channel: 'string', method: 'string' },
  },
);
```

`handle` registra quem responde ao canal. `provide` publica os dados de que o consumidor precisa para descobri-lo. A lista de permissões do handler limita os solicitantes a `backend-client`; ter uma concessão não elimina essa verificação adicional. `shape` verifica membros do contrato e seus tipos, enquanto a validação do corpo pertence ao serviço.

No WU Framework 4.0.0, `wu.handle(channel, handler, options)` e `wu.eventBus.handle(channel, handler, options)` preservam versão e allowlist. Dentro de um microapp use `context.wu.handle`: além dessas opções, aplica a identidade e os grants do app. Consulte a [página de versões](/pt/sources/) para identificar o runtime do laboratório.

O nome publicado com `provide` pertence ao primeiro provedor. Outro app, ou o host ao tentar substituí-lo, recebe `WU_CAPABILITY_OWNED` até o proprietário executar `revoke` ou ser desmontado com `unmount`. A versão do contrato não permite ignorar essa propriedade.

<span id="consumir-y-llamar-desde-el-cliente"></span>

<span class="section-anchor" id="section-4"></span>

## Consumir e chamar pelo cliente

O cliente obtém um proxy do contrato e solicita um intervalo compatível. Acessar `api.channel` resolve o provedor disponível e verifica esse intervalo:

```js
const api = appWu.consume('docs:backend:service', '^1.0.0');
const channel = api.channel;
const controller = new AbortController();

const pending = appWu.request(channel, {
  method: api.method,
  path: '/validate',
  body: JSON.stringify({ name: 'catalog', entry: 'entry.js' }),
}, {
  version: '^1.0.0',
  timeout: 3500,
  signal: controller.signal,
});

const response = await pending;
console.log(response.status, response.body);
```

Há duas verificações de compatibilidade: a do contrato consumido e a do handler RPC. O cenário de versão incompatível solicita `^2.0.0` ao contrato `1.0.0`; falha ao resolvê-lo, antes de iniciar trabalho no serviço. Um provedor removido também não pode atender uma nova solicitação. Consulte [eventos, RPC e contratos](/pt/docs/framework/communication/) para suas assinaturas e erros.

<span id="diferenciar-una-respuesta-de-un-rechazo"></span>

<span class="section-anchor" id="section-5"></span>

## Diferenciar uma resposta de uma rejeição

O serviço espera `POST`, uma rota conhecida e um corpo string de até 4096 bytes UTF-8.

| Solicitação | Resposta do serviço |
| --- | --- |
| `/validate` com JSON válido e `name`/`entry` presentes | 200 com `ok: true` |
| `/validate` com um manifesto que não atende a essas regras | 422 com erros de validação |
| `/uppercase` | 200 com o texto ASCII convertido em maiúsculas |
| `/failure` | 500 para a falha controlada do serviço |
| `/slow` sem cancelar | 504 quando o limite de trabalho de 2500 ms expira |
| Rota desconhecida | 404 sem iniciar o trabalho |
| Método diferente de POST | 405 |
| Estrutura de solicitação inválida | 400 |
| Corpo que excede o limite | 413 |

Essas respostas resolvem a promise RPC com um objeto: o cliente deve verificar `response.status`. A incompatibilidade de contrato, a ausência do provedor ou o cancelamento são tratados como rejeições, com `try`/`catch`.

A receita de manifesto valida apenas `name` e `entry`. Seu resultado declara `scope: "name+entry"` e `completeValidation: false`; não verifica o manifesto inteiro, permissões, rotas publicadas ou a existência da entrada. Consulte [configuração e manifestos](/pt/docs/framework/configuration/) e [WU doctor](/pt/docs/cli/doctor/) para continuar o diagnóstico de um projeto.

<span id="cancelar-y-desmontar-sin-conservar-trabajo-activo"></span>

<span class="section-anchor" id="section-6"></span>

## Cancelar e desmontar sem manter trabalho ativo

Enquanto a solicitação estiver pendente, o cliente pode executar:

```js
controller.abort();
```

O handler recebe o contexto RPC, que inclui `signal`. Neste exemplo, o provedor conecta esse sinal à interrupção do seu executor. Um handler que ignora `signal` pode continuar trabalhando mesmo depois de o cliente parar de esperar.

O prazo RPC de 3500 ms e o limite de trabalho de 2500 ms têm efeitos diferentes: o primeiro limita a espera do WU; o segundo permite ao serviço encerrar o trabalho e responder 504. A interface inclui uma receita lenta para observar o cancelamento antes dos dois prazos.

Ao desmontar o provedor, a implementação interrompe suas solicitações ativas e remove o que publicou:

```js
backend.dispose();
release();
contract.revoke();
```

O WU também revoga a autoridade associada à app. Ao montar novamente, um novo handler e um novo contrato são registrados. Cada solicitação libera seu listener de abort, temporizador e executor ao terminar, falhar ou ser cancelada. O [guia de ciclo de vida](/pt/docs/framework/lifecycle/) explica como vincular essa responsabilidade pelos recursos a `mount` e `unmount`.

<span id="leer-y-comprobar-el-ejemplo"></span>

<span class="section-anchor" id="section-7"></span>

## Ler e verificar o exemplo

O [código do provedor](/microfrontends/backend-service/service.js.txt) mostra o tratamento das solicitações e sua limpeza. Para executar as verificações pelo repositório do portal:

```sh
npm ci
npm run build
npm run dev:shell
# En otra terminal:
npm run test:backend
```

O teste percorre respostas, versão incompatível, revogação, remontagem, timeout, cancelamento e desmontagem durante uma solicitação. Também verifica se a execução não mantém Workers ao terminar e se o percurso não produz erros de página.

<span id="implementación-del-ejemplo"></span>

<span class="section-anchor" id="section-8"></span>

## Implementação do exemplo

O provedor usa um programa WASI compilado e incluído no projeto, executado em um Worker. Isso permite processar dados reais e interromper o trabalho pelo navegador. O host e os arquivos virtuais pertencem à implementação do serviço; o contrato público estudado aqui é WU. O framework não incorpora um motor WASI geral.

Você pode substituir essa implementação por um serviço autorizado da sua aplicação, mantendo um contrato compatível e testando suas respostas, erros e limpeza. Um serviço remoto deve validar novamente identidade, permissões e dados. Para renderizar páginas no Node ou conectar um cliente MCP externo, seus processos e transportes continuam necessários: consulte [SSR](/pt/docs/framework/server-recipes/) e [IA/MCP](/pt/docs/framework/ai-recipes/).