Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
DOCTRINE CRITIQUE: WTP_UDOCK_V1 jamais sur pages publiques (vitrine weval-consulting.com)
User signaled dock visible on homepage (index.html) - violation doctrine
Fix:
- 38 pages publiques nettoyees (regex multi-pattern + GOLD backup chacune)
* Homepage: index.html
* Landings: landing-industrie, landing-ocp, landing-banque, landing-retail
* SEO FR: consulting-*, crm-pharma, cyber, digitalisation, erp-pme, finance,
formation, marketing, offshore, recrutement, transformation, achats, bpm, cloud
* Corporate: contact, solutions, pricing, cgu, case-studies, use-cases,
pitch, register, booking, apps, living-proof, faq-techniques/knowledge-base,
ecosysteme-ia-maroc, candidates-pool, wepredict, ia-france-consulting
- Script Python sudo avec chattr mgmt + regex 3 patterns
- 38 GOLD backups /opt/wevads/vault/gold_*_REMOVEDOCK_*.html
- Syntax OK partout
Endpoint /api/wtp-udock-coverage.php:
- Added $PUBLIC_EXEMPT array (38 pages)
- Skip public pages from count (same pattern que SEO_EXEMPT)
- Coverage now reports pages INTERNES uniquement: 276/276 = 100 pct
Doctrine documentee: WTP_UDOCK uniquement pour outils internes
(admin, WEVIA Master, Orch, WTP platform, dashboards, monitors).
Pages user-facing externes (SEO, vitrine, landings) = JAMAIS de dock.
Zero regression · Zero ecrasement · GOLD backup integral
96 lines
4.8 KiB
PHP
96 lines
4.8 KiB
PHP
<?php
|
|
/* ═══════════════════════════════════════════════════════════════════
|
|
WTP UDOCK COVERAGE ENDPOINT · Opus 21-avr tour35
|
|
Scans /var/www/html/*.html and returns JSON coverage stats
|
|
Usage: GET /api/wtp-udock-coverage.php [?detail=1]
|
|
═══════════════════════════════════════════════════════════════════ */
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: public, max-age=60');
|
|
header('X-WTP-UDOCK-V', '1');
|
|
|
|
$DIR = '/var/www/html';
|
|
$NAV_PATTERNS = ['wtp-unified-dock.js', 'opus-xlinks', 'wtp-sidebar', 'v130-xnav'];
|
|
$EXCLUDE = ['.bak', 'gold_'];
|
|
// SEO_VERIFICATION_EXEMPT - files that must NOT have dock (SEO verification tokens)
|
|
$SEO_EXEMPT = ['googlecba1a80ba979325c.html', 'google-site-verification.html'];
|
|
// PUBLIC_EXEMPT - pages publiques (vitrine weval-consulting.com)
|
|
// Doctrine: le dock WTP_UDOCK est UNIQUEMENT pour les pages internes/outils
|
|
// JAMAIS sur pages user-facing externes (SEO landings, homepage, contact, etc.)
|
|
$PUBLIC_EXEMPT = ['index.html', 'contact.html', 'solutions.html', 'pricing.html', 'landing-industrie.html', 'landing-ocp.html', 'landing-banque.html', 'landing-retail.html', 'case-studies.html', 'use-cases.html', 'pitch.html', 'register.html', 'booking.html', 'apps.html', 'cgu.html', 'living-proof.html', 'ecosysteme-ia-maroc.html', 'intelligence-artificielle-france-consulting.html', 'consulting-intelligence-artificielle-maroc.html', 'consulting-pharma-supply-chain.html', 'consulting-sap-erp-vistex-maroc.html', 'crm-pharma-marketing-pharmaceutique.html', 'cybersécurité-maroc-audit-conseil.html', 'digitalisation-processus-gouvernance-it.html', 'erp-pme-eti-sap-odoo-sage.html', 'finance-controlling-sap-fico.html', 'formation-ia-sap-cloud-maroc.html', 'marketing-digital-maroc.html', 'offshore-nearshore-maroc-france-canada.html', 'recrutement-talent-it-maroc.html', 'transformation-digitale-consulting-france-international.html', 'achats-purchasing-sap-mm-procurement.html', 'bpm-automatisation-processus-métier.html', 'cloud-infrastructure-système-information.html', 'faq-techniques.html', 'faq-knowledge-base.html', 'candidates-pool.html', 'wepredict.html'];
|
|
|
|
$files = glob($DIR . '/*.html') ?: [];
|
|
$total = 0;
|
|
$covered = 0;
|
|
$by_pattern = array_fill_keys($NAV_PATTERNS, 0);
|
|
$uncovered = [];
|
|
$chattr_i_count = 0;
|
|
|
|
$detail = isset($_GET['detail']) && $_GET['detail'] === '1';
|
|
|
|
foreach ($files as $f) {
|
|
$name = basename($f);
|
|
$skip = false;
|
|
foreach ($EXCLUDE as $ex) { if (strpos($name, $ex) !== false) { $skip = true; break; } }
|
|
// SEO exempt: don't count these in total (they must stay minimal)
|
|
if (in_array($name, $SEO_EXEMPT)) { $skip = true; }
|
|
// Public pages exempt: doctrine "NAV JAMAIS sur pages vitrine publiques"
|
|
if (in_array($name, $PUBLIC_EXEMPT)) { $skip = true; }
|
|
if ($skip || strpos($name, '_') === 0) continue;
|
|
$total++;
|
|
|
|
$content = @file_get_contents($f);
|
|
if ($content === false) continue;
|
|
|
|
$has_nav = false;
|
|
foreach ($NAV_PATTERNS as $pat) {
|
|
if (strpos($content, $pat) !== false) {
|
|
$by_pattern[$pat]++;
|
|
$has_nav = true;
|
|
break; // count first matched pattern only (avoid double-count)
|
|
}
|
|
}
|
|
if ($has_nav) {
|
|
$covered++;
|
|
} else {
|
|
// Check if chattr+i
|
|
$is_immutable = false;
|
|
$lsattr_out = @shell_exec("lsattr " . escapeshellarg($f) . " 2>/dev/null");
|
|
if ($lsattr_out && preg_match('/^----i/', $lsattr_out)) {
|
|
$is_immutable = true;
|
|
$chattr_i_count++;
|
|
}
|
|
$size = @filesize($f);
|
|
$uncovered[] = [
|
|
'name' => $name,
|
|
'size' => $size,
|
|
'immutable' => $is_immutable,
|
|
'size_human' => $size ? round($size/1024, 1) . ' KB' : '?'
|
|
];
|
|
}
|
|
}
|
|
|
|
$response = [
|
|
'ts' => date('c'),
|
|
'source' => 'wtp-udock-coverage v1',
|
|
'total_pages' => $total,
|
|
'covered' => $covered,
|
|
'uncovered' => count($uncovered),
|
|
'coverage_pct' => $total > 0 ? round(100 * $covered / $total, 1) : 0,
|
|
'by_pattern' => [
|
|
'wtp-unified-dock.js' => $by_pattern['wtp-unified-dock.js'],
|
|
'opus-xlinks' => $by_pattern['opus-xlinks'],
|
|
'wtp-sidebar' => $by_pattern['wtp-sidebar'],
|
|
'v130-xnav' => $by_pattern['v130-xnav']
|
|
],
|
|
'immutable_blocked' => $chattr_i_count,
|
|
'target_100pct_remaining' => $total - $covered
|
|
];
|
|
|
|
if ($detail) {
|
|
// Sort uncovered by size desc, take top 30
|
|
usort($uncovered, function($a, $b) { return ($b['size'] ?? 0) - ($a['size'] ?? 0); });
|
|
$response['uncovered_top30'] = array_slice($uncovered, 0, 30);
|
|
}
|
|
|
|
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|