Conn2Flow
Docs navigation

Reference / Libraries

modulo-distribuido.php library

Central/distributed architecture: a module runs on the central Conn2Flow and writes its data to the client installation's database over an HMAC channel, with login and permission decided by the central.

Path in the Gestor bibliotecas/modulo-distribuido.php

It lets a module have two halves:

  • central ("scope": "central-module" in <module>.json): runs on the central installation (the vendor's), where the code, users and permissions live;

  • distributed ("scope": "distributed-module"): runs on the client's site and keeps the data in the client's database.

The central module code keeps using banco_select(), banco_insert()… as usual; inside the distributed channel, banco_query() packs the SQL and runs it on the client installation. The client sees the module as an embedded screen (iframe) of the central, unlocked only after the central confirms login and permission.

Configuration

In the .env (global variables): MODULO_DISTRIBUIDO_SECRET (shared HMAC secret), MODULO_DISTRIBUIDO_CENTRAL_URL (on the distributed side: the central URL) and MODULO_DISTRIBUIDO_ENDPOINT (on the central side: the distributed API URL). Per module, $_CONFIG['modulo-distribuido']['secrets'][<slug>] and ['endpoints'][<slug>] override the general values (modulo_distribuido_config_get('modulo-distribuido.secrets.<slug>')).

modulo_distribuido_scope($manifest), modulo_distribuido_scope_central(), modulo_distribuido_scope_distribuido() and modulo_distribuido_resolver_manifesto() read the scope from the manifest (constants C2F_SCOPE_CENTRAL and C2F_SCOPE_DISTRIBUIDO).

The data channel

// In the central module, wrapping only the client's data operations:
// the central module manifest declares "distributed": {"target-slug": "my-module"}
$config = modulo_distribuido_canal_central($_GESTOR['modulo#'.$_GESTOR['modulo-id']]);
$orders = modulo_distribuido_com_canal(function () {
    return banco_select(['tabela' => 'pedidos', 'campos' => ['id', 'total']]);
}, $config);
// or by hand: banco_distribuido_iniciar($config); … banco_distribuido_finalizar();
  1. banco_distribuido_ativo() makes banco_query() divert to banco_distribuido_query().

  2. modulo_distribuido_montar_payload() packs the SQL (operacao, modulo, linguagem, timestamp, nonce), and modulo_distribuido_enviar() sends it through modulo_distribuido_http_post() to <endpoint>/modulo-distribuido/<slug>/db, with X-C2F-Signature = HMAC-SHA256 of the body (modulo_distribuido_assinar()).

  3. On the distributed side, the API checks the signature (modulo_distribuido_verificar_assinatura(), constant time) and modulo_distribuido_executar_local() runs the SQL through PDO: a SELECT returns columns and rows; a write returns affected_rows and insert_id.

  4. modulo_distribuido_resposta_para_resultado() turns the response into a BancoResultadoRemoto, which mimics mysqli_result for the banco.php functions.

Authentication, variables and the rest of the request stay in the central's local database: only what is inside the channel goes to the client. modulo_distribuido_canal_central($manifest, $overrides) builds the central-side configuration from the manifest's distributed.target-slug (and, optionally, endpoint-config/secret-config, key paths in $_CONFIG); modulo_distribuido_canal_distribuido() does the same on the distributed side, to talk to the central; modulo_distribuido_detectar_operacao() and modulo_distribuido_operacao_leitura() classify the SQL; modulo_distribuido_parse_rota() reads {slug}/{action} from the URL.

Login, permission and screen

The distributed side does not decide access: it asks the central.

  • Sign-in is the central's perfil-usuario: without a token, the distributed host sends the browser to the central's /signin/ with a signed context; after the complete sign-in (second factor included) the login.distribuido hook returns a single-use code, exchanged server to server for the tokens (exchange action). modulo_distribuido_token_sessao() and modulo_distribuido_persistir_token() keep and renew the tokens in the session. There is no username and password sign-in on this channel.

  • modulo_distribuido_guardiao() (distributed side) asks the central, where modulo_distribuido_middleware_central() validates the token and the user's permission on the module and answers nao-autenticado, sem-permissao or authorized. Any failure resolves to the most restrictive state.

  • modulo_distribuido_estado_renderizacao() translates that into login, sem-permissao or iframe; modulo_distribuido_montar_url_iframe() builds the URL of the central screen.

  • modulo_distribuido_app() does it all in one call: token, guardian and the state screen, replacing #modulo-distribuido-app# on the page with the modulo-distribuido-app component (modulo_distribuido_render_estado(), modulo_distribuido_render_componente(), modulo_distribuido_textos()).

The variants modulo_distribuido_estado_por_token_ativo(), modulo_distribuido_estado_por_permissao_central() and modulo_distribuido_middleware_permissao() are the pure (testable) pieces of this flow.

Functions

Generated from gestor/bibliotecas/modulo-distribuido.php · 36 functions

36 of 36

modulo_distribuido_scope

view source · line 140 ↗
modulo_distribuido_scope(array|string $modulo, string|null $slug = null): string|null

Lê o valor da chave "scope" do manifesto <slug>.json de um módulo.

Parameters

$moduloarray|string
Manifesto decodificado, caminho do .json ou do diretório do módulo.
$slugstring|null
Slug do módulo (necessário quando $modulo é um diretório).

Returns

string|null
Valor de scope ('central-module' / 'distributed-module') ou null.

modulo_distribuido_resolver_manifesto

view source · line 170 ↗
modulo_distribuido_resolver_manifesto(array|string $modulo, string|null $slug = null): array|null

Resolve o manifesto (array) de um módulo a partir de array, caminho de .json ou diretório.

Parameters

$moduloarray|string
Manifesto decodificado, caminho do .json ou do diretório do módulo.
$slugstring|null
Slug do módulo (usado para achar <slug>.json quando $modulo é diretório).

Returns

array|null
Manifesto decodificado ou null.

modulo_distribuido_assinar

view source · line 209 ↗
modulo_distribuido_assinar(string $corpo, string $secret, string $algo = 'sha256'): string

Gera a assinatura HMAC de um corpo de requisição.

Parameters

$corpostring
Corpo cru (string JSON) a ser assinado.
$secretstring
Segredo compartilhado entre central e distribuído.
$algostring
Algoritmo de hash (padrão sha256).

Returns

string
Assinatura em hexadecimal.

modulo_distribuido_verificar_assinatura

view source · line 223 ↗
modulo_distribuido_verificar_assinatura(string $corpo, string $assinatura, string $secret, string $algo = 'sha256'): bool

Verifica, de forma resistente a ataques de timing, a assinatura HMAC de um corpo.

Parameters

$corpostring
Corpo cru recebido.
$assinaturastring
Assinatura recebida (header X-C2F-Signature).
$secretstring
Segredo compartilhado.
$algostring
Algoritmo de hash (padrão sha256).

Returns

bool
true se a assinatura confere.

modulo_distribuido_montar_payload

view source · line 267 ↗
modulo_distribuido_montar_payload(string $sql, array $opcoes = []): array

Monta o payload (array) que empacota a instrução SQL para trânsito via API.

Parameters

$sqlstring
Instrução SQL já montada.
$opcoesarray
Opções: 'modulo' (slug), 'linguagem'.

Returns

array
Payload com sql, operacao, modulo, timestamp e nonce.

modulo_distribuido_enviar

view source · line 298 ↗
modulo_distribuido_enviar(array $payload, array $config): array

Envia um payload de banco distribuído para a instalação remota e decodifica a resposta.

Parameters

$payloadarray
Payload montado por modulo_distribuido_montar_payload().
$configarray
Configuração do canal distribuído.

Returns

array
Resposta decodificada. Em erro retorna ['status' => 'error', 'message' => ...].

modulo_distribuido_http_post

view source · line 374 ↗
modulo_distribuido_http_post($url, $corpo, array $headers, $timeout = 15): string|false

POST HTTP simples via cURL. Isolado para permitir mock nos testes.

Parameters

$url
$corpo
$headersarray
$timeout

Returns

string|false
Corpo da resposta ou false em falha de transporte.

modulo_distribuido_executar_local

view source · line 457 ↗
modulo_distribuido_executar_local(array $payload, PDO $pdo): array

Executa localmente, no banco do cliente, a instrução SQL recebida da central.

Parameters

$payloadarray
Payload recebido (deve conter 'sql').
$pdoPDO
Conexão PDO com o banco local do cliente.

Returns

array
Resposta pronta para json_encode: {status, tipo, fields, rows, ...}.

modulo_distribuido_parse_rota

view source · line 570 ↗
modulo_distribuido_parse_rota(array $caminho): array|null

Faz o parse da rota da API distribuída: api/v1/modulo-distribuido/{slug}/{acao}.

Parameters

$caminhoarray
Segmentos do caminho da URL.

Returns

array|null
['slug' => ..., 'acao' => ..., 'resto' => [...]] ou null se não casar.

modulo_distribuido_estado_renderizacao

view source · line 640 ↗
modulo_distribuido_estado_renderizacao(bool $token_ativo, bool $tem_permissao): string

Decide o estado de renderização considerando autenticação E permissão por módulo.

Parameters

$token_ativobool
Usuário autenticado (token válido).
$tem_permissaobool
Usuário autorizado ao módulo alvo.

Returns

string
'login' | 'sem-permissao' | 'iframe'.

modulo_distribuido_estado_por_permissao_central

view source · line 658 ↗
modulo_distribuido_estado_por_permissao_central(string $estado_central): string

Traduz o 'estado' devolvido pelo middleware central (endpoint 'permissao') no estado de renderização do ambiente distribuído.

Parameters

$estado_centralstring
'nao-autenticado' | 'sem-permissao' | 'permitido'.

Returns

string
'login' | 'sem-permissao' | 'iframe'.

modulo_distribuido_middleware_permissao

view source · line 682 ↗
modulo_distribuido_middleware_permissao(array $config, string $token, string|null $slug = null): array

Middleware de permissão (lado distribuído): consulta o central e devolve o estado.

Parameters

$configarray
Config do canal (endpoint, slug, secret, transporte).
$tokenstring
Access token do usuário (obtido no signin).
$slugstring|null
Slug do módulo alvo (default: $config['slug']).

Returns

array
['estado' => 'login'|'sem-permissao'|'iframe', 'resposta' => array].

modulo_distribuido_guardiao

view source · line 732 ↗
modulo_distribuido_guardiao(array $config, array $opcoes = []): array

Guardião de módulo distribuído — fachada obrigatória de controle de acesso.

Parameters

$configarray
Config do canal (endpoint, slug, secret, transporte, central-url).
$opcoesarray
'token', 'central-url', 'opcao', 'params-iframe', 'slug'.

Returns

array
{

modulo_distribuido_middleware_central

view source · line 778 ↗
modulo_distribuido_middleware_central(string $token, string $slug, array $opcoes = []): array

Middleware central — avalia autenticação e permissão como AUTORIDADE do sistema.

Parameters

$tokenstring
Access token do usuário.
$slugstring
Slug do módulo alvo.
$opcoesarray
'resolver_usuario' (callable(token):?int), 'verificar_permissao' (callable(id,slug):bool).

Returns

array
['estado' => 'nao-autenticado'|'sem-permissao'|'permitido', 'id_usuarios' => int|null, 'modulo' => string].

modulo_distribuido_montar_url_iframe

view source · line 818 ↗
modulo_distribuido_montar_url_iframe(string $endpoint_central, string $slug, array $opcoes = []): string

Monta a URL administrativa do módulo no central para renderização em Iframe.

Parameters

$endpoint_centralstring
URL base do central (ex.: https://conn2flow.com/).
$slugstring
Slug do módulo (central) a ser embutido.
$opcoesarray
'modulo' (override do slug na URL), 'opcao', 'token', 'params' (extra).

Returns

string
URL absoluta para o src do Iframe.

banco_distribuido_query

view source · line 885 ↗
banco_distribuido_query(string $sql): BancoResultadoRemoto|bool

Executa uma query no modo distribuído: empacota, envia e converte a resposta.

Parameters

$sqlstring
Instrução SQL montada pelas funções de banco.php.

Returns

BancoResultadoRemoto|bool

modulo_distribuido_config_get

view source · line 922 ↗
modulo_distribuido_config_get(string $path, mixed $default = null): mixed

Lê um valor de $_CONFIG por caminho em dot-notation (ex.: 'modulo-distribuido.secret').

Parameters

$pathstring
Caminho em dot-notation.
$defaultmixed
Valor padrão quando o caminho não existe.

Returns

mixed

modulo_distribuido_canal_central

view source · line 951 ↗
modulo_distribuido_canal_central(array $modulo_config, array $overrides = []): array

Resolve a config do canal para um MÓDULO CENTRAL (que delega banco ao distribuído).

Parameters

$modulo_configarray
Manifesto do módulo central.
$overridesarray
endpoint, secret, slug, token, timeout, transporte.

Returns

array

modulo_distribuido_canal_distribuido

view source · line 991 ↗
modulo_distribuido_canal_distribuido(array $modulo_config, array $overrides = []): array

Resolve a config do canal para um MÓDULO DISTRIBUÍDO (que consulta o central).

Parameters

$modulo_configarray
Manifesto do módulo distribuído.
$overridesarray
central-url, secret, slug, transporte.

Returns

array
Inclui 'endpoint' (central-url/_api) e 'central-url'.

modulo_distribuido_com_canal

view source · line 1026 ↗
modulo_distribuido_com_canal(callable $operacao, array $config): mixed

Executa uma operação de dados dentro do canal distribuído, garantindo o fechamento.

Parameters

$operacaocallable
Função com as chamadas de banco (delegadas ao distribuído).
$configarray
Config do canal (de modulo_distribuido_canal_central()).

Returns

mixed
Retorno de $operacao.

modulo_distribuido_token_sessao

view source · line 1042 ↗
modulo_distribuido_token_sessao(string $chave, $slug = null): string

Lê, da sessão, o token de acesso ao central guardado por um módulo distribuído.

Parameters

$chavestring
Chave da variável de sessão.
$slug

Returns

string
Token ou string vazia.

modulo_distribuido_persistir_token

view source · line 1079 ↗
modulo_distribuido_persistir_token(string $chave, array $tokens, callable|null $persistir = null): void

Persiste os tokens obtidos no login/ativação distribuído.

Parameters

$chavestring
Chave base da variável de sessão do token.
$tokensarray
Tokens retornados pelo central (access_token, refresh_token, ...).
$persistircallable|null
Persistência customizada: function($chave, array $tokens): void.

Returns

void

modulo_distribuido_textos

view source · line 1107 ↗
modulo_distribuido_textos(string|null $lang = null, array $overrides = [], $resolver = null): array

Dicionário de textos (i18n) do componente global de estados distribuídos.

Parameters

$langstring|null
Idioma (default: $_GESTOR['linguagem-codigo']).
$overridesarray
Sobrescritas de texto por chave (#c2f-md-*# sem as cercas).
$resolver

Returns

array
Mapa chave => texto.

modulo_distribuido_render_componente

view source · line 1128 ↗
modulo_distribuido_render_componente(string $html, string $estado, string|null $iframe_url = null, array $textos = []): string

Processa o HTML do componente de estados segundo o estado de acesso (função pura).

Parameters

$htmlstring
HTML do componente (de gestor_componente()).
$estadostring
'login' | 'sem-permissao' | 'iframe'.
$iframe_urlstring|null
URL do Iframe (quando 'iframe').
$textosarray
Mapa de textos (de modulo_distribuido_textos()).

Returns

string
HTML final pronto para injeção.

modulo_distribuido_render_estado

view source · line 1172 ↗
modulo_distribuido_render_estado(string $estado, string|null $iframe_url = null): string

Aplica a renderização por estado diretamente sobre a página do módulo ($_GESTOR['pagina']).

Parameters

$estadostring
'login' | 'sem-permissao' | 'iframe'.
$iframe_urlstring|null
URL do Iframe (quando 'iframe').

Returns

string
O próprio estado.

modulo_distribuido_app

view source · line 1207 ↗
modulo_distribuido_app(array $config, array $opcoes = []): array

Orquestração completa do "app" de um módulo distribuído (fachada de alto nível).

Parameters

$configarray
Config do canal (de modulo_distribuido_canal_distribuido()).
$opcoesarray
'token', 'token-chave', 'opcao', 'params-iframe', 'central-url',

Returns

array
Resultado do guardião + 'html' (componente renderizado).

Installation registry at the central

The central recognizes each distributed installation by its app_id. The reader is modulo_distribuido_instalacao($app, $slug), which returns url, secret, modules and tables, or false.

  • By default the registry is the MODULO_DISTRIBUIDO_INSTALLATIONS variable of the .env (JSON keyed by app_id).

  • A project may keep the registry outside the .env and declare the reader in $_CONFIG['modulo-distribuido']['installations-provider']: callable(string $app): array|false|null. array is the installation; false says it exists and is disabled (the .env is not consulted); null says the provider does not know it, and the .env answers. A provider failure refuses the installation.

Cost per query

Each query of the original module that reaches a table of the installation becomes a signed HTTP call. The connection is reused within the request (modulo_distribuido_http_post() keeps the cURL handle), and the sweep of expired nonces in the client's database is sampled, so each query costs one write there, not two.

The Future is Hybrid: Human + AI.

Conn2Flow is the tool. If you need the Architect to design your company's strategy using this technology...

Hire Specialized Consulting