c2f-javascript-ajax
Skill5 starsChanged 2 months agoMITView on GitHub
LEIA OBRIGATORIAMENTE antes de escrever chamadas AJAX, requisições fetch, uploads multipart ou manipuladores backend de AJAX no Gestor. Previne erros 403 Forbidden por CSRF, envelopes JSON quebrados e travamento de UI.
- Sends data out
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 18
No núcleo do framework (gestor.php), o modo AJAX só é ativado quando a requisição POST/GET envia explicitamente ajax: 'sim':
- Very specific: line 138
No controlador PHP do módulo, toda rota AJAX DEVE ser interceptada no início do ciclo com interface_ajax_iniciar() e finalizada com …
- Very specific: line 307
Use list_network_requests para localizar fetch/XHR da ação, incluindo /_ajax/, /_api/ e rotas do módulo.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Governança e Arquitetura de Integração AJAX no Gestor Conn2Flow
⚡ Gatilho Obrigatório
- TRIGGER: Escrever, editar ou migrar código JavaScript frontend (Vanilla Fetch, jQuery) ou endpoints PHP de backend que realizam comunicação assíncrona (AJAX) em módulos do Gestor.
- SKIP APENAS SE: Scripts utilitários puramente visuais locais (ex: animações CSS simples sem chamadas de rede).
- CONSEQUÊNCIA DE IGNORAR: Erros 403 Forbidden (Token CSRF inválido ou ausente) por não ativar o modo AJAX do núcleo, envelopes JSON quebrados, travamento de dimmers/spinners e falhas silenciosas de sessão (401).
🔍 1. Diagnóstico: Como o Gestor Detecta Chamadas AJAX & Prevenção de 403
No núcleo do framework (gestor.php), o modo AJAX só é ativado quando a requisição POST/GET envia explicitamente ajax: 'sim':
- Com
ajax: 'sim': O Gestor popula$_GESTOR['ajax'] = 'sim', lê$_GESTOR['ajax-opcao'](a partir do campoajaxOpcao) e desativa a exigência de token CSRF síncrono de formulário HTML. - Sem
ajax: 'sim': O Gestor assume que se trata de uma submissão de formulário HTML tradicional, exige$_GESTOR['token']e rejeita a requisição imediatamente com 403 Forbidden ({"status":"error","message":"Token CSRF inválido ou ausente."}).
Cobertura automática de CSRF e 401 pelo global.js
gestor/assets/global/global.js injeta X-CSRF-Token em requisições mutáveis (POST, PUT, PATCH, DELETE) de mesma origem em TODOS os canais — não escreva o cabeçalho à mão:
| Canal | Mecanismo |
$.ajax | jQuery.ajaxPrefilter |
fetch | envelope de window.fetch |
| Formulários | listener de submit em captura + envelope de HTMLFormElement.prototype.submit + handler delegado do jQuery |
XMLHttpRequest cru (req-163) | envelope de XMLHttpRequest.prototype.open / setRequestHeader / send (guarda __c2fCsrf) |
- Uploads com barra de progresso:
fetchnão expõeupload.onprogress; usenew XMLHttpRequest()normalmente — o token entra sozinho. Antes da req-163 esse caminho voltava 403 com o usuário logado. - Token definido manualmente (
xhr.setRequestHeader('X-CSRF-Token', ...), em qualquer caixa) não é duplicado nem sobrescrito.GETe cross-origin nunca recebem o token. - Resposta 401 com
X-Gestor-Auth-Redirectredireciona para o login em$.ajax,fetcheXMLHttpRequest. Ainda assim trate o 401 no seu handler para destravar dimmers/spinners.
🏆 2. Padrão Canônico Frontend em JavaScript Vanilla (Gold Standard)
Em módulos modernos com JavaScript puro (Vanilla JS), utilize sempre o padrão canônico com URLSearchParams ou FormData:
A) Requisições de Dados Estruturados (application/x-www-form-urlencoded):
/**
* Padrão Canônico de Requisição AJAX no Gestor (Vanilla JS)
* @param {Object} state - Estado do módulo (deve conter opcao e moduleBaseUrl)
* @param {string} ajaxOpcao - Ação a ser executada no backend (ex: 'salvar-dados', 'listar')
* @param {Object} [extraData] - Parâmetros adicionais (objetos/arrays são serializados em JSON)
* @returns {Promise<Object>} Resposta JSON do backend
*/
function gestorAjax(state, ajaxOpcao, extraData) {
var params = new URLSearchParams({
opcao: state.opcao || 'dashboard',
ajax: 'sim',
ajaxOpcao: ajaxOpcao
});
if (extraData) {
Object.keys(extraData).forEach(function (key) {
var val = extraData[key];
params.set(key, typeof val === 'object' && val !== null ? JSON.stringify(val) : val);
});
}
return fetch(state.moduleBaseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params
})
.then(function (response) {
if (response.status === 401) {
window.location.href = (window.gestor && window.gestor.raiz ? window.gestor.raiz : '/') + 'signin/';
throw new Error('Sessão expirada. Redirecionando...');
}
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.json();
})
.then(function (json) {
if (!json || json.status !== 'Ok') {
throw new Error((json && json.message) || 'Erro na resposta do servidor.');
}
return json;
});
}B) Uploads de Arquivo Multipart (FormData):
/**
* Padrão Canônico para Uploads de Arquivo Multipart (Vanilla JS)
*/
function gestorUpload(state, ajaxOpcao, extraData, file) {
var form = new FormData();
form.append('opcao', state.opcao || 'dashboard');
form.append('ajax', 'sim');
form.append('ajaxOpcao', ajaxOpcao);
if (extraData) {
Object.keys(extraData).forEach(function (key) {
var val = extraData[key];
form.append(key, typeof val === 'object' && val !== null ? JSON.stringify(val) : val);
});
}
if (file) {
form.append('file', file);
}
return fetch(state.moduleBaseUrl, {
method: 'POST',
body: form
})
.then(function (response) {
if (response.status === 401) {
window.location.href = (window.gestor && window.gestor.raiz ? window.gestor.raiz : '/') + 'signin/';
throw new Error('Sessão expirada. Redirecionando...');
}
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.json();
})
.then(function (json) {
if (!json || json.status !== 'Ok') {
throw new Error((json && json.message) || 'Erro no upload.');
}
return json;
});
}🏛️ 3. Padrão Canônico Backend em PHP (modulo.php)
No controlador PHP do módulo, toda rota AJAX DEVE ser interceptada no início do ciclo com interface_ajax_iniciar() e finalizada com interface_ajax_finalizar():
function modulo_start() {
global $_GESTOR;
gestor_incluir_bibliotecas();
// 1. Interceptador de Chamadas AJAX
if (!empty($_GESTOR['ajax'])) {
interface_ajax_iniciar();
switch ($_GESTOR['ajax-opcao']) {
case 'minha-acao':
modulo_ajax_minha_acao();
break;
default:
$_GESTOR['ajax-json'] = array(
'status' => 'Erro',
'message' => 'Ação AJAX desconhecida: ' . ($_GESTOR['ajax-opcao'] ?? '')
);
break;
}
interface_ajax_finalizar();
return;
}
// 2. Roteamento de Páginas Síncronas Normais
switch ($_GESTOR['opcao']) {
case 'dashboard':
default:
modulo_dashboard();
break;
}
}
function modulo_ajax_minha_acao() {
global $_GESTOR;
// Recupera dados enviados
$param1 = $_REQUEST['param1'] ?? '';
// Lógica de negócio / banco
// ...
// Retorno de Sucesso padronizado
$_GESTOR['ajax-json'] = array(
'status' => 'Ok',
'data' => array(
'id' => 123,
'resultado' => 'Processado com sucesso'
)
);
}📦 4. Padrão Legado com jQuery (ajaxDefault)
Para módulos e interfaces legadas que utilizam jQuery e Semantic UI:
var ajaxDefault = {
type: 'POST',
url: gestor.raiz + gestor.moduloCaminho + '/',
ajaxOpcao: 'ajaxOpcao',
data: {
opcao: gestor.moduloOpcao,
ajax: 'sim'
},
dataType: 'json',
beforeSend: function () {
loadDimmer(true);
msg_erro_resetar();
},
success: function (dados) {
if (dados.status === 'Ok') {
this.successCallback(dados);
} else {
this.successNotOkCallback(dados);
console.log('ERROR - ' + this.ajaxOpcao + ' - ' + dados.status);
}
loadDimmer(false);
},
error: function (txt) {
if (txt.status === 401) {
window.open(gestor.raiz + (txt.responseJSON.redirect ? txt.responseJSON.redirect : "signin/"), "_self");
} else {
console.log('ERROR AJAX - ' + this.ajaxOpcao + ' - Dados:', txt);
loadDimmer(false);
}
},
successCallback: function (response) { },
successNotOkCallback: function (response) { }
};
// Uso:
var ajax = Object.assign({}, ajaxDefault);
ajax.ajaxOpcao = 'minha-acao';
ajax.data = Object.assign({}, ajaxDefault.data, {
ajaxOpcao: ajax.ajaxOpcao,
param1: 'valor1'
});
ajax.successCallback = function (response) {
// response.data ...
};
$.ajax(ajax);5. Armadilha de Injeção de Scripts no <head> (gestor_pagina_javascript_incluir)
A função PHP gestor_pagina_javascript_incluir() injeta os scripts dos módulos no elemento <head> da página HTML. Isso significa que o script é executado antes do <body> ser parseado.
5.1 Proibição de Consultas Diretas ao DOM na Raiz do Script
// ❌ ERRADO — DOM ainda não foi parseado, retorna null
var form = document.getElementById('form-checkout');
form.addEventListener('submit', handler); // TypeError: null
// ✅ CORRETO — aguardar DOMContentLoaded
document.addEventListener('DOMContentLoaded', function() {
var form = document.getElementById('form-checkout');
form.addEventListener('submit', handler);
});5.2 Preferência por Delegação de Eventos
Para elementos que podem ser inseridos dinamicamente (widgets, componentes AJAX), use delegação de eventos no document:
// ✅ CORRETO — delegação funciona mesmo para elementos futuros
document.addEventListener('click', function(e) {
if (e.target.matches('.btn-adicionar-carrinho')) {
adicionarAoCarrinho(e.target.dataset.produtoId);
}
});
// ✅ CORRETO — submit com delegação
document.addEventListener('submit', function(e) {
if (e.target.matches('#form-checkout')) {
e.preventDefault();
processarCheckout(e.target);
}
});[!WARNING] Sem
DOMContentLoadedou delegação, o formulário será submetido nativamente (POST síncrono) em vez de ser interceptado via AJAX, causando recarregamento completo da página e perda de estado.
⛔ Regras Invioláveis de AJAX:
- SEMPRE envie
ajax: 'sim': Sem este campo, o backend dispara erro403 Forbiddenpor CSRF. - SEMPRE envie
opcaoeajaxOpcao: Identificam o contexto da página e a ação a ser roteada noswitch ($_GESTOR['ajax-opcao']). - Backend DEVE usar
interface_ajax_iniciar()einterface_ajax_finalizar(): Garante headers JSON corretos, limpeza de buffers e envelope padronizado. - Trate o erro 401 (Unauthorized): Redirecione imediatamente para
signin/em caso de sessão expirada. - Version Bump Obrigatório: Ao alterar qualquer script JavaScript em
resources/, incremente a versão (versao: "X.Y.Z") no<id>.jsonou no manifest do módulo antes de executarc2f resources:syncpara invalidar o cache do navegador.
Depuração de tráfego assíncrono com Chrome DevTools MCP
Em uma sessão local isolada preparada conforme c2f-agent-visual-inspection, reproduza a ação real da interface antes de avaliar console e rede. Consulte o schema negociado pelo servidor instalado; não suponha que os parâmetros sejam idênticos entre versões.
- Colete
list_console_messagesantes/depois da ação. Useget_console_messagepelo ID para detalhar erros e stack traces disponíveis; registre arquivo, linha e frames relevantes, incluindo source maps quando resolvidos. Um console sem erros não comprova que o AJAX funcionou. - Use
list_network_requestspara localizarfetch/XHR da ação, incluindo/_ajax/,/_api/e rotas do módulo. Correlacione ID, método, URL e sequência; examine cada falha comget_network_request, verificando status HTTP, headers, payload e corpo da resposta. - No Gestor, confira
ajax=sim,opcaoeajaxOpcaoonde o contrato da rota os exige. Em métodos mutáveis de mesma origem, verifique presença deX-CSRF-Tokeninjetado peloglobal.jse sessão válida. O campoajax=simnão elimina a proteção CSRF; não desative a proteção para corrigir um 403. Não exponha valores de token, Authorization, Cookie ou Set-Cookie nos registros. - Diferencie 401 (sessão/
X-Gestor-Auth-Redirect), 403 (autorização/CSRF), 500 (backend) e HTTP 200 com HTML de login, warnings PHP ou JSON inválido. Confira Content-Type e envelope JSON esperado pela rota, além de liberar loading/dimmer após sucesso e falha. - Para multipart, confira campos e boundary gerado pelo navegador; não fixe manualmente Content-Type em
FormData. Registre latência observada e pedidos duplicados após cliques repetidos. Verifique resultado no DOM com novo snapshot/screenshot.
Prefira observar a requisição original. Reenviar mutações como fetch() pode duplicar gravações/pagamentos e exige escopo de teste autorizado. Evidências devem conter IDs e dados sanitizados, nunca dumps integrais de headers sensíveis. Referência: ferramentas oficiais.
In this repository102 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- cli/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/sdd.mdcCursor rule
- c2f-database-testingSkill
- c2f-gd-image-safetySkill
- c2f-json-resources-syncSkill
- c2f-mdd-indexing-and-handoffsSkill
- c2f-mysql-utf8-emoji-encodingSkill
- c2f-tailwind-css-architectureSkill
- c2f-tailwind-module-migrationSkill
- c2f-widget-developmentSkill
- c2f-agent-visual-inspectionSkill
- c2f-ai-featuresSkill
- c2f-architect-masterSkill
- c2f-database-operationsSkill
- c2f-database-testingSkill
- c2f-dev-scriptsSkill
- c2f-docker-environmentSkill
- c2f-documentation-governanceSkill
- c2f-documentationSkill
- c2f-environment-configurationSkill
- c2f-executor-agentSkill
- c2f-gd-image-safetySkill
- c2f-gestor-functionsSkill
- c2f-global-variablesSkill
- c2f-hooks-systemSkill
- c2f-html-css-pages-and-componentsSkill
- c2f-interface-v2-architectureSkill
- c2f-json-resources-syncSkill
- c2f-mdd-indexing-and-handoffsSkill
- c2f-modelo-templatesSkill
- c2f-module-crud-scaffoldingSkill
- c2f-module-visual-assetsSkill
- c2f-multilingual-systemSkill
- c2f-mysql-utf8-emoji-encodingSkill
- c2f-payment-gatewaysSkill
- c2f-plugin-architectureSkill
- c2f-preview-modals-systemSkill
- c2f-project-pipeline-and-tasksSkill
- c2f-projects-systemSkill
- c2f-resources-systemSkill
- c2f-reviewer-agentSkill
- c2f-shell-and-windows-trapsSkill
- c2f-system-tasksSkill
- c2f-tailwind-css-architectureSkill
- c2f-tailwind-module-migrationSkill
- c2f-variables-systemSkill
- c2f-widget-developmentSkill
- continue-mdd-batchSkill
- mdd-memory-gardeningSkill
- mdd-workflowSkill
- project-validationSkill
- raise-spec-changeSkill
- review-current-batchSkill
- start-mdd-sliceSkill
- c2f-agent-visual-inspectionSkill
- c2f-ai-featuresSkill
- c2f-architect-masterSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

