# Apps remotas e portas de capacidades

Conecte uma app de outra origem por iframe e MessagePort com permissões e revogação.

Esta página descreve o WU Framework `4.0.0`. Consulte o [guia de migração para Framework 4.0 e CLI 1.2](/pt/docs/guides/releases/) antes de atualizar um projeto existente.

<span id="configurar-el-host"></span>

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

## Configurar o host

```js
import { wu } from 'wu-framework/core';
import 'wu-framework/ports';
await wu.init({ apps: [{
  name: 'widget', url: 'https://widgets.example/app/', sandbox: 'remote',
  manifest: { entry: 'index.html', wu: { permissions: ['events.emit:widget:*'] } },
  grants: ['events.emit:widget:*'],
  iframe: { title: 'Remote widget', timeout: 15000, callTimeout: 10000 },
}] });
await wu.mount('widget', '#widget-slot');
await wu.update('widget', { theme: 'light' });
```

Crie `#widget-slot` no shell e sirva a app na origem configurada. WU cria o iframe e transfere a porta para a origem exata da URL. O navegador aplica o isolamento entre origens; as mensagens executam pela facade de `widget`, com as permissões solicitadas e concedidas.

<span id="conectar-el-documento-remoto"></span>

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

## Conectar o documento remoto

```js
import { connect } from 'wu-framework/remote';

const remote = await connect({ hostOrigin: 'https://shell.example' });
const off = remote.onProps(props => {
  document.documentElement.dataset.theme = props.theme;
});
await remote.emit('widget:ready', { ready: true });
await remote.resize(document.body.scrollHeight);

window.addEventListener('pagehide', () => {
  off();
  remote.close();
}, { once: true });
```

O documento remoto usa seu próprio renderer e deve aceitar apenas a origem real do shell em `hostOrigin`. Chamadas ao host são assíncronas: aguarde `store.get`, `store.set`, `emit` e RPC. `onProps` recebe atualizações; `props` mantém os últimos valores. `resize` solicita uma altura e `whenClosed` observa o fechamento. Os dados devem suportar structured clone.

O iframe usa `allow-scripts allow-same-origin allow-forms` por padrão; configure com `iframe.sandbox` e `iframe.allow`. `wu.remoteOf(name)` retorna sua janela. `hide` preserva o iframe; `unmount` o remove e revoga a porta. Falhas de conexão são `WU_REMOTE_TIMEOUT` e `WU_REMOTE_LOAD_FAILED`; um handler remoto que excede o prazo produz `WU_PORT_CALL_TIMEOUT`.

<span id="cabeceras-de-ambos-orígenes"></span>

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

## Cabeçalhos das duas origens

```json
{ "security": { "frameOrigins": ["https://widgets.example"] } }
```

Na WU CLI `1.0.0`, `security.frameOrigins` adiciona essas origens a `frame-src`, não a `script-src` nem a `connect-src`. A resposta remota deve permitir o shell em `frame-ancestors` e não bloqueá-lo com `X-Frame-Options`. Configure também o renderer e a entrada `wu-framework/remote` no build remoto.

<span id="crear-un-puerto-manualmente"></span>

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

## Criar uma porta manualmente

```js
const capability = await wu.ports.mint('widget', { props: { theme: 'dark' } });
worker.postMessage({ wu: 1, type: 'port', app: 'widget' }, [capability.port]);
await capability.ready;
capability.push({ theme: 'light' });
capability.close('finished');
const active = wu.ports.list();
const revoked = wu.ports.revoke('widget');
```

O host cria `worker` e registra previamente `widget` com grants; o receptor precisa conectar o protocolo remoto. A porta pode ser transferida e fechada. `close` revoga essa porta; `revoke` fecha as portas da app. Chamadas pendentes rejeitam com `WU_PORT_CLOSED`. A comunicação por mensagens não compartilha diretamente o objeto store entre documentos.

<span id="validación-de-origen-en-40"></span>

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

## Validação de origem no 4.0

`connect(options)` e `waitForPort(options)` exigem `hostOrigin`; omiti-lo produz `WU_REMOTE_HOST_ORIGIN_REQUIRED`. `"*"` aceita conscientemente qualquer origem. Em iframe ou popup, o emissor também deve ser `parent` ou `opener`; `source` permite indicar outra janela. O overload `connect(port)` aceita uma porta já recebida.

A origem da app é a origem de sua `url`. Um `entry` em outra origem falha com `WU_REMOTE_ORIGIN_MISMATCH`. Um remoto na origem do shell falha com `WU_REMOTE_SAME_ORIGIN`, salvo com `iframe.allowSameOrigin: true`; essa exceção perde o isolamento entre origens. `wu.detach()` rejeita remotos com `WU_WINDOW_REMOTE_UNSUPPORTED`.

O host continua oferecendo a porta após `load` até receber resposta, permitindo que o remoto aguarde trabalho antes de conectar. Pela porta, `consume()` permite apenas métodos da `shape` declarada; sem `shape`, exclui métodos de `Object.prototype`. O unmount e `destroy()` revogam as portas do core.