433 lines
33 KiB
HTML
433 lines
33 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en"><head>
|
||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVAL Enterprise Management — SaaS Platform</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<style>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800;900&display=swap');
|
||
:root{--bg:#0a0e1a;--card:#111827;--border:#1e293b;--accent:#c96442;--green:#10b981;--blue:#3b82f6;--purple:#8b5cf6;--yellow:#f59e0b;--red:#ef4444;--cyan:#06b6d4;--text:#e2e8f0;--muted:#64748b;--font:'DM Sans',sans-serif;--mono:'JetBrains Mono',monospace}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{background:var(--bg);color:var(--text);font-family:var(--font);overflow-x:hidden}
|
||
.topbar{display:flex;align-items:center;justify-content:space-between;padding:12px 24px;background:rgba(17,24,39,.95);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:100;backdrop-filter:blur(12px)}
|
||
.logo{font-size:18px;font-weight:700;color:var(--accent)}.logo span{color:var(--text);font-weight:400}
|
||
.tabs{display:flex;gap:4px}
|
||
.tab{padding:8px 16px;border-radius:8px;cursor:pointer;font-size:13px;font-weight:500;color:var(--muted);transition:.2s}
|
||
.tab:hover,.tab.act{background:rgba(201,100,66,.15);color:var(--accent)}
|
||
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;padding:16px 24px}
|
||
.kpi{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px;text-align:center}
|
||
.kpi .v{font-size:28px;font-weight:700;font-family:var(--mono)}.kpi .l{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:1px;margin-top:4px}
|
||
.main{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:0 24px 24px}
|
||
.full{grid-column:1/-1}
|
||
.card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:20px;overflow:hidden}
|
||
.card h3{font-size:14px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px}
|
||
.card h3 .badge{font-size:10px;background:rgba(201,100,66,.2);color:var(--accent);padding:2px 8px;border-radius:99px;font-weight:500}
|
||
/* Pipeline */
|
||
.pipeline{display:flex;gap:0;overflow-x:auto;padding:8px 0}
|
||
.pipe-stage{flex:1;min-width:140px;text-align:center;position:relative;padding:12px 8px}
|
||
.pipe-stage::after{content:'→';position:absolute;right:-8px;top:50%;transform:translateY(-50%);color:var(--muted);font-size:18px}
|
||
.pipe-stage:last-child::after{display:none}
|
||
.pipe-icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;margin:0 auto 8px;font-size:18px}
|
||
.pipe-name{font-size:12px;font-weight:600}.pipe-count{font-size:10px;color:var(--muted);margin-top:2px}
|
||
.pipe-bar{height:3px;border-radius:2px;margin-top:6px}
|
||
/* Agent grid */
|
||
.agent-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:8px}
|
||
.agent{background:rgba(255,255,255,.03);border:1px solid var(--border);border-radius:8px;padding:10px;text-align:center;font-size:11px;transition:.2s}
|
||
.agent:hover{border-color:var(--accent);transform:translateY(-2px)}
|
||
.agent .icon{font-size:22px;margin-bottom:4px}.agent .name{font-weight:600;font-size:11px}.agent .role{color:var(--muted);font-size:9px}
|
||
.agent .dot{width:6px;height:6px;border-radius:50%;display:inline-block;margin-right:4px}
|
||
/* n8n */
|
||
.n8n-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px}
|
||
.n8n-wf{background:rgba(59,130,246,.05);border:1px solid rgba(59,130,246,.2);border-radius:8px;padding:12px;font-size:12px}
|
||
.n8n-wf .wf-name{font-weight:600;margin-bottom:4px}.n8n-wf .wf-status{font-size:10px;color:var(--green)}
|
||
/* Dept sections */
|
||
.dept{border-left:3px solid var(--accent);padding-left:16px;margin-bottom:16px}
|
||
.dept-name{font-size:16px;font-weight:700;margin-bottom:4px}.dept-sub{font-size:11px;color:var(--muted)}
|
||
.view{display:none}.view.act{display:block}
|
||
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
||
.card{animation:fadeIn .3s ease}
|
||
@media(max-width:768px){.main{grid-template-columns:1fr}.kpis{grid-template-columns:repeat(3,1fr)}}
|
||
</style></head><body style="padding-top:60px"><div style="position:fixed;top:0;left:0;right:0;height:28px;background:#ffffffee;z-index:100;display:flex;align-items:center;padding:0 14px;font-family:Nunito,sans-serif;font-size:.65rem;gap:12px;border-bottom:1px solid #e2e8f0;backdrop-filter:blur(8px)"><b style="color:#059669">WEVIA</b></div>
|
||
<div style="position:fixed;top:30px;left:0;right:0;display:flex;justify-content:center;gap:5px;padding:4px;z-index:100;background:#f8fafcee;backdrop-filter:blur(8px);font-family:Nunito,sans-serif">
|
||
<a href="/agents-archi.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Architecture</a>
|
||
<a href="/director-center.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Director</a>
|
||
<a href="/wevia-meeting-rooms.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Rooms</a>
|
||
<a href="/enterprise-model.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Enterprise</a>
|
||
<a href="/agents-ia.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Pyramid</a>
|
||
<a href="/director-chat.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">Chat</a>
|
||
<a href="/l99-brain.html" style="padding:2px 8px;border-radius:4px;font:700 8px Nunito;text-decoration:none;color:#5a6a80;border:1px solid #c8d8e8">L99</a>
|
||
</div>
|
||
|
||
<div class="topbar">
|
||
<div class="logo">WEVAL <span>Enterprise Management</span></div>
|
||
<div class="tabs" id="tabs">
|
||
<div class="tab act" onclick="showView('overview')">Overview</div>
|
||
<div class="tab" onclick="showView('pipelines')">Pipelines</div>
|
||
<div class="tab" onclick="showView('agents')">Agents</div>
|
||
<div class="tab" onclick="showView('n8n')">n8n Workflows</div>
|
||
<div class="tab" onclick="showView('infra')">Infrastructure</div>
|
||
<div class="tab" onclick="showView('saas')">SaaS Products</div>
|
||
</div>
|
||
<div style="font-family:var(--mono);font-size:12px;color:var(--green)">● LIVE <span id="clock"></span></div>
|
||
</div>
|
||
|
||
<div class="kpis" id="kpis"></div>
|
||
|
||
<!-- OVERVIEW -->
|
||
<div class="view act" id="v-overview"><div class="main" id="overview-content"></div></div>
|
||
|
||
<!-- PIPELINES -->
|
||
<div class="view" id="v-pipelines"><div class="main" id="pipelines-content"></div></div>
|
||
|
||
<!-- AGENTS -->
|
||
<div class="view" id="v-agents"><div class="main" id="agents-content"></div></div>
|
||
|
||
<!-- N8N -->
|
||
<div class="view" id="v-n8n"><div class="main" id="n8n-content"></div></div>
|
||
|
||
<!-- INFRA -->
|
||
<div class="view" id="v-infra"><div class="main" id="infra-content"></div></div>
|
||
|
||
<!-- SAAS -->
|
||
<div class="view" id="v-saas"><div class="main" id="saas-content"></div></div>
|
||
|
||
<script>
|
||
// === DATA ===
|
||
const DEPTS = [
|
||
{id:'ceo',name:'CEO Office',icon:'👔',color:'#c96442',agents:['CEO','Brain','Orch','TaskMgr','Intro'],pipeline:['Decision','Budget','Strategy','Hiring','Review'],kpi:'1 brief/day'},
|
||
{id:'prospect',name:'Prospect & Sales',icon:'🎯',color:'#f59e0b',agents:['Ethica','Analyst','Writer','Proposal','Contract'],pipeline:['Leads','Qualify','Outreach','Convert','Close'],kpi:'1052 leads'},
|
||
{id:'consult',name:'Consulting',icon:'🏗️',color:'#3b82f6',agents:['Architect','Planner','DeerFlow','Critic','Translate','Academy','ECC36','Persona6'],pipeline:['Analyse','Design','Propose','Deliver','Support'],kpi:'3 proposals'},
|
||
{id:'dev',name:'Dev Lab',icon:'⚡',color:'#8b5cf6',agents:['Executor','Debugger','Reviewer','Designer','WEDROID','Simplifier','Blueprint','DevForge'],pipeline:['Code','Review','Test','Deploy','Monitor'],kpi:'12 deploys/j'},
|
||
{id:'infra',name:'Infrastructure',icon:'🖥️',color:'#06b6d4',agents:['Watchdog','Guardian','Blade','GitMaster','Loki'],pipeline:['Monitor','Fix','Deploy','Verify','Report'],kpi:'99.9% uptime'},
|
||
{id:'security',name:'Security & Compliance',icon:'🔐',color:'#ef4444',agents:['Security','Verifier','Nuclei'],pipeline:['Scan','Detect','Assess','Remediate','Audit'],kpi:'Grade B (Nuclei+Trivy)'},
|
||
{id:'qa',name:'Quality Assurance',icon:'🧪',color:'#10b981',agents:['QA','TestEng','Tracer','Scientist'],pipeline:['Plan','Execute','Analyze','Report','Fix'],kpi:'153/153 NR + 450 L99'},
|
||
{id:'pharma',name:'Pharma & Ethica',icon:'💊',color:'#ec4899',agents:['Explore','DocSpec','MiroFish'],pipeline:['Scrape','Validate','Enrich','Campaign','Track'],kpi:'131K+ HCPs (DZ+MA+TN)'},
|
||
{id:'ai',name:'AI Engine',icon:'🧠',color:'#a855f7',agents:['Groq','Cerebras','Ollama','Sovereign','ClaudeCode','OpenWebUI','Flowise'],pipeline:['Ingest','Route','Infer','Validate','Deliver'],kpi:'247 AIs benchmarked'},
|
||
{id:'mta',name:'Email Infrastructure',icon:'📧',color:'#f97316',agents:['PMTA','KumoMTA','Postfix'],pipeline:['Compose','Route','Deliver','Track','Bounce'],kpi:'3M contacts (5582 standby)'},
|
||
{id:'cog',name:'Cognitive Modes',icon:'🎯',color:'#6366f1',agents:['Analysis','Codegen','Creative','Debug','Strategy','Research','Orchestration','TokenEff','BusinessPanel'],pipeline:['Perceive','Process','Generate','Validate','Output'],kpi:'9 modes'},
|
||
{id:'oss',name:'OSS Integration',icon:'🌐',color:'#14b8a6',agents:['BrowserUse','OpenClaw','Goose','AIOS','Dify','Mastra','EvoMaster','Activepieces','AEGIS','Prometheus','Flowise','OpenWebUI','CrewAI','LangChain','Scrapy','Supermemory'],pipeline:['Discover','Evaluate','Wire','Test','Deploy'],kpi:'685 tools'},
|
||
{id:'saas',name:'SaaS Products',icon:'📦',color:'#0ea5e9',agents:['LeadForge','OutreachAI','MailWarm','ProposalAI','WhatsAppAPI','WEVIA PUB','Manager'],pipeline:['Build','Launch','Sell','Support','Scale'],kpi:'38 tools'},
|
||
{id:'cron',name:'Automation',icon:'⏰',color:'#64748b',agents:['EthicaCron','B2BCron','NonRegCron','BackupCron','OSSChain','SkillSync','L99Auto','GuardCron'],pipeline:['Schedule','Execute','Validate','Alert','Log'],kpi:'30+ crons'},
|
||
];
|
||
|
||
const N8N_WORKFLOWS = [
|
||
{name:'Ethica HCP Enrichment',trigger:'Cron */6h',nodes:12,status:'active',desc:'Scrape → Validate → Enrich emails/phones → Store PG'},
|
||
{name:'B2B Lead Generation',trigger:'Cron */4h',nodes:8,status:'active',desc:'LinkedIn → Email pattern → Verify → CRM'},
|
||
{name:'NonReg Watchdog',trigger:'Cron 6h/18h',nodes:6,status:'active',desc:'Run 153 tests → Telegram alert → HTML report'},
|
||
{name:'Sovereign AI Router',trigger:'Webhook',nodes:5,status:'active',desc:'Request → Provider select → Inference → Cache → Return'},
|
||
{name:'WhatsApp Campaign',trigger:'Manual',nodes:7,status:'ready',desc:'Template → Audience → Send → Track → Report'},
|
||
{name:'Email Drip DZ+MA+TN',trigger:'Cron */5min',nodes:9,status:'active',desc:'Queue → Segment → Personalize → Send → Track'},
|
||
{name:'OSS Discovery Sync',trigger:'Cron */6h',nodes:6,status:'active',desc:'GitHub scan → Evaluate → Wire Paperclip → Alert'},
|
||
{name:'DeerFlow Research',trigger:'Webhook',nodes:8,status:'active',desc:'Query → Multi-source → Synthesize → Report → Store'},
|
||
{name:'Paperclip Agent Chain',trigger:'API',nodes:10,status:'active',desc:'Trigger → Select agent → Execute → Report → Learn'},
|
||
{name:'Azure AD O365 Sync',trigger:'Cron daily',nodes:5,status:'active',desc:'Check tenants → Sync accounts → Refresh tokens → Report'},
|
||
{name:'Guardian Auto-Heal',trigger:'Cron */5min',nodes:4,status:'active',desc:'Check services → Detect failure → Auto-restart → Alert'},
|
||
{name:'Stripe Billing',trigger:'Webhook',nodes:6,status:'ready',desc:'Event → Process payment → Update status → Invoice → Email'},
|
||
{name:'L99 Alive Monitor',trigger:'Cron */30min',nodes:7,status:'active',desc:'Scan → Playwright test → Screenshots → Infra check → Telegram'},
|
||
{name:'Backup & GOLD',trigger:'Cron daily 4am',nodes:5,status:'active',desc:'PG dump → GOLD snapshot → S3 upload → Verify → Clean old'},
|
||
{name:'IP Warmup Pipeline',trigger:'Cron daily',nodes:8,status:'active',desc:'Select IPs → Ramp volume → Monitor reputation → Adjust → Report'},
|
||
];
|
||
|
||
const INFRA = {
|
||
servers:[
|
||
{name:'S204',ip:'204.168.152.13',role:'Primary Web',disk:'83%',docker:20,services:['nginx','php-fpm','postgresql','ollama','sovereign','paperclip','deerflow']},
|
||
{name:'S95',ip:'95.216.167.89',role:'Email/Arsenal',disk:'65%',docker:4,services:['PMTA:25','KumoMTA:587','Postfix:2525','Sentinel:5890','PostgreSQL:5432']},
|
||
{name:'S151',ip:'151.80.235.110',role:'Tracking/Relay',disk:'45%',docker:2,services:['OpenClaw','Ollama','Tracking relay']},
|
||
{name:'Blade',ip:'Desktop',role:'Agent Desktop',disk:'N/A',docker:0,services:['Sentinel Agent','PowerShell','Claude Code']},
|
||
],
|
||
docker:['authentik-server','authentik-worker','authentik-db','plausible','plausible-events','plausible-db','uptime-kuma','mattermost','searxng','loki','twenty-redis','paperclip','openwebui','flowise','vaultwarden','n8n','qdrant','redis'],
|
||
ports:[9090,9443,8000,8001,3000,3100,3102,3033,5678,6333,6380,8222,8281,11434,4000]
|
||
};
|
||
|
||
const SAAS_PRODUCTS = [
|
||
{name:'WEVIA PUBLIC',desc:'AI Chat Widget + Command Center',modules:71,status:'live'},
|
||
{name:'WEVADS IA',desc:'Omnichannel Email Intelligence',pages:81,status:'live'},
|
||
{name:'Ethica HCP',desc:'Pharma Healthcare Professional Platform',hcps:'141K+',status:'live'},
|
||
{name:'Sovereign Claude',desc:'Multi-provider AI Gateway',providers:6,status:'live'},
|
||
{name:'LeadForge',desc:'B2B Lead Generation Engine',leads:'1052',status:'live'},
|
||
{name:'MailWarm',desc:'IP Warmup & Reputation Manager',accounts:2036,status:'live'},
|
||
{name:'OutreachAI',desc:'AI-Powered Email Sequences',templates:50,status:'live'},
|
||
{name:'ProposalAI',desc:'Smart Proposal Generator',formats:3,status:'beta'},
|
||
{name:'Arsenal',desc:'192 Tools Security Platform',tools:192,status:'live'},
|
||
{name:'DeerFlow',desc:'Deep Research AI Agent',skills:528,status:'live'},
|
||
{name:'Paperclip',desc:'150-Agent AI Organization',agents:150,status:'live'},
|
||
{name:'WhatsApp API',desc:'Meta Business Messaging',mode:'LIVE',status:'live'},
|
||
];
|
||
|
||
// === RENDER ===
|
||
function renderKPIs(){
|
||
const kpis=[
|
||
{v:'150',l:'Agents',c:'var(--accent)'},{v:'25',l:'Departments',c:'var(--blue)'},
|
||
{v:'15',l:'n8n Workflows',c:'var(--purple)'},{v:'685',l:'OSS Tools',c:'var(--cyan)'},
|
||
{v:'3M',l:'Contacts',c:'var(--yellow)'},{v:'141K+',l:'HCPs',c:'var(--green)'},
|
||
{v:'20',l:'Docker',c:'var(--red)'},{v:'93%',l:'L99 Score',c:'var(--accent)'},
|
||
{v:'12',l:'SaaS Products',c:'var(--blue)'},{v:'528',l:'Skills',c:'var(--purple)'}
|
||
];
|
||
document.getElementById('kpis').innerHTML=kpis.map(k=>`<div class="kpi"><div class="v" style="color:${k.c}">${k.v}</div><div class="l">${k.l}</div></div>`).join('');
|
||
}
|
||
|
||
function renderPipeline(stages,color){
|
||
return `<div class="pipeline">${stages.map((s,i)=>`<div class="pipe-stage"><div class="pipe-icon" style="background:${color}22;color:${color}">${i+1}</div><div class="pipe-name">${s}</div><div class="pipe-bar" style="background:linear-gradient(90deg,${color},${color}44);width:${70+Math.random()*30}%"></div></div>`).join('')}</div>`;
|
||
}
|
||
|
||
function renderOverview(){
|
||
let html='';
|
||
DEPTS.forEach(d=>{
|
||
html+=`<div class="card"><h3>${d.icon} ${d.name} <span class="badge">${d.agents.length} agents</span> <span class="badge" style="background:rgba(16,185,129,.2);color:var(--green)">${d.kpi}</span></h3>${renderPipeline(d.pipeline,d.color)}<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:8px">${d.agents.map(a=>`<span style="font-size:10px;background:${d.color}15;color:${d.color};padding:2px 8px;border-radius:4px">${a}</span>`).join('')}</div></div>`;
|
||
});
|
||
document.getElementById('overview-content').innerHTML=html;
|
||
}
|
||
|
||
function renderPipelines(){
|
||
let html=`<div class="card full"><h3>🔄 All Business Pipelines <span class="badge">${DEPTS.length} pipelines</span></h3>`;
|
||
DEPTS.forEach(d=>{
|
||
html+=`<div class="dept"><div class="dept-name">${d.icon} ${d.name}</div><div class="dept-sub">${d.agents.length} agents → ${d.kpi}</div>${renderPipeline(d.pipeline,d.color)}</div>`;
|
||
});
|
||
html+=`</div>`;
|
||
// n8n integration
|
||
html+=`<div class="card full"><h3>⚙️ n8n Workflow Pipelines <span class="badge">${N8N_WORKFLOWS.length} workflows</span></h3><div class="n8n-grid">${N8N_WORKFLOWS.map(w=>`<div class="n8n-wf"><div class="wf-name">⚙️ ${w.name}</div><div style="font-size:10px;color:var(--muted)">${w.trigger} • ${w.nodes} nodes</div><div class="wf-status">${w.status==='active'?'● Active':'○ Ready'}</div><div style="font-size:10px;color:var(--text);margin-top:4px;opacity:.7">${w.desc}</div></div>`).join('')}</div></div>`;
|
||
document.getElementById('pipelines-content').innerHTML=html;
|
||
}
|
||
|
||
function renderAgents(){
|
||
let html='';
|
||
DEPTS.forEach(d=>{
|
||
html+=`<div class="card"><h3>${d.icon} ${d.name} <span class="badge">${d.agents.length}</span></h3><div class="agent-grid">${d.agents.map(a=>`<div class="agent"><div class="icon">${d.icon}</div><div class="name">${a}</div><div class="role">${d.id}</div><div><span class="dot" style="background:var(--green)"></span><span style="font-size:9px;color:var(--green)">Active</span></div></div>`).join('')}</div></div>`;
|
||
});
|
||
document.getElementById('agents-content').innerHTML=html;
|
||
}
|
||
|
||
function renderN8N(){
|
||
let html=`<div class="card full"><h3>⚙️ n8n Automation Hub <span class="badge">${N8N_WORKFLOWS.length} workflows</span> <span class="badge" style="background:rgba(16,185,129,.2);color:var(--green)">${N8N_WORKFLOWS.filter(w=>w.status==='active').length} active</span></h3>`;
|
||
N8N_WORKFLOWS.forEach(w=>{
|
||
const color=w.status==='active'?'var(--green)':'var(--yellow)';
|
||
html+=`<div style="display:flex;align-items:center;gap:12px;padding:12px;border-bottom:1px solid var(--border)"><div style="width:8px;height:8px;border-radius:50%;background:${color}"></div><div style="flex:1"><div style="font-weight:600;font-size:13px">${w.name}</div><div style="font-size:11px;color:var(--muted)">${w.desc}</div></div><div style="text-align:right"><div style="font-family:var(--mono);font-size:11px;color:${color}">${w.status.toUpperCase()}</div><div style="font-size:10px;color:var(--muted)">${w.trigger} • ${w.nodes} nodes</div></div></div>`;
|
||
});
|
||
html+=`</div>`;
|
||
document.getElementById('n8n-content').innerHTML=html;
|
||
}
|
||
|
||
function renderInfra(){
|
||
let html=`<div class="card full"><h3>🖥️ Servers <span class="badge">${INFRA.servers.length}</span></h3><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:12px">${INFRA.servers.map(s=>`<div style="background:rgba(255,255,255,.02);border:1px solid var(--border);border-radius:10px;padding:16px"><div style="display:flex;justify-content:space-between;margin-bottom:8px"><span style="font-weight:700">${s.name}</span><span style="font-family:var(--mono);font-size:11px;color:var(--muted)">${s.ip}</span></div><div style="font-size:11px;color:var(--accent);margin-bottom:4px">${s.role}</div><div style="font-size:10px;color:var(--muted)">Disk: ${s.disk} | Docker: ${s.docker}</div><div style="display:flex;flex-wrap:wrap;gap:3px;margin-top:6px">${s.services.map(sv=>`<span style="font-size:9px;background:var(--green)15;color:var(--green);padding:1px 6px;border-radius:3px">${sv}</span>`).join('')}</div></div>`).join('')}</div></div>`;
|
||
html+=`<div class="card"><h3>🐳 Docker Containers <span class="badge">${INFRA.docker.length}</span></h3><div style="display:flex;flex-wrap:wrap;gap:6px">${INFRA.docker.map(d=>`<span style="font-size:11px;background:rgba(16,185,129,.1);color:var(--green);padding:4px 10px;border-radius:6px;border:1px solid rgba(16,185,129,.2)">● ${d}</span>`).join('')}</div></div>`;
|
||
html+=`<div class="card"><h3>🔌 Active Ports <span class="badge">${INFRA.ports.length}</span></h3><div style="display:flex;flex-wrap:wrap;gap:6px">${INFRA.ports.map(p=>`<span style="font-family:var(--mono);font-size:11px;background:rgba(59,130,246,.1);color:var(--blue);padding:4px 10px;border-radius:6px">:${p}</span>`).join('')}</div></div>`;
|
||
document.getElementById('infra-content').innerHTML=html;
|
||
}
|
||
|
||
function renderSaaS(){
|
||
let html=`<div class="card full"><h3>📦 SaaS Product Suite <span class="badge">${SAAS_PRODUCTS.length} products</span></h3><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px">${SAAS_PRODUCTS.map(p=>`<div style="background:rgba(255,255,255,.02);border:1px solid var(--border);border-radius:10px;padding:16px"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px"><span style="font-weight:700;font-size:14px">${p.name}</span><span style="font-size:10px;background:${p.status==='live'?'rgba(16,185,129,.2)':'rgba(245,158,11,.2)'};color:${p.status==='live'?'var(--green)':'var(--yellow)'};padding:2px 8px;border-radius:4px">${p.status.toUpperCase()}</span></div><div style="font-size:12px;color:var(--muted);margin-bottom:8px">${p.desc}</div><div style="font-size:11px;color:var(--accent)">${Object.entries(p).filter(([k])=>!['name','desc','status'].includes(k)).map(([k,v])=>`${k}: ${v}`).join(' • ')}</div></div>`).join('')}</div></div>`;
|
||
document.getElementById('saas-content').innerHTML=html;
|
||
}
|
||
|
||
function showView(id){
|
||
document.querySelectorAll('.view').forEach(v=>v.classList.remove('act'));
|
||
document.querySelectorAll('.tab').forEach(t=>t.classList.remove('act'));
|
||
document.getElementById('v-'+id).classList.add('act');
|
||
event.target.classList.add('act');
|
||
}
|
||
|
||
// Clock
|
||
setInterval(()=>{document.getElementById('clock').textContent=new Date().toLocaleTimeString()},1000);
|
||
|
||
// Init
|
||
renderKPIs();renderOverview();renderPipelines();renderAgents();renderN8N();renderInfra();renderSaaS();
|
||
</script>
|
||
<!-- WTP-GAP-FILL-V1 (doctrine 90-v2 gap-fill showcase, 18avr 2026) -->
|
||
<style>
|
||
.wtp-gapfill-banner{position:fixed;bottom:0;left:0;right:0;z-index:99999;background:linear-gradient(90deg,#05060a,#0b0d15 20%,#181d2e 50%,#0b0d15 80%,#05060a);border-top:2px solid #14b8a6;color:#e2e8f0;padding:10px 16px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:11.5px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;box-shadow:0 -10px 30px rgba(20,184,166,.28)}
|
||
.wtp-gapfill-banner a{color:#5eead4;text-decoration:none;font-weight:600;transition:color .15s}
|
||
.wtp-gapfill-banner a:hover{color:#22d3ee}
|
||
.wtp-gapfill-banner .pill{padding:2px 9px;background:rgba(99,102,241,.14);color:#a5b4fc;border-radius:10px;font-size:10.5px;font-family:JetBrains Mono,monospace;font-weight:600}
|
||
.wtp-gapfill-banner .pill.new{background:rgba(20,184,166,.22);color:#5eead4}
|
||
.wtp-gapfill-banner .pill.hot{background:rgba(236,72,153,.22);color:#f472b6}
|
||
.wtp-gapfill-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 8px;font-size:16px;line-height:1;border:1px solid #334155;border-radius:4px}
|
||
.wtp-gapfill-banner .close:hover{color:#e2e8f0;border-color:#64748b}
|
||
.wtp-gapfill-banner.hidden{display:none}
|
||
@media(max-width:768px){.wtp-gapfill-banner{font-size:10px;padding:7px 10px;gap:8px}}
|
||
</style>
|
||
<div class="wtp-gapfill-banner" id="wtpGapFillBanner">
|
||
<span>🎯 <strong>WEVAL Agents Gap-Fill ERP</strong></span>
|
||
<span class="pill hot" id="gaps-banner-count">17 gaps live</span>
|
||
<span class="pill">SAP · Oracle · NetSuite · Dynamics</span>
|
||
<span class="pill new">🆕 Meeting Rooms</span>
|
||
<span class="pill new">🆕 Lean 6 Sigma</span>
|
||
<span id="wtp-gfb-metrics" class="pill">— chargement —</span>
|
||
<a href="/weval-technology-platform.html">→ WTP Portal (16 mod)</a>
|
||
<a href="/enterprise-model.html">Enterprise Model</a>
|
||
<a href="/api/weval-agents-gap-fill-manifest.json" target="_blank">📋 Manifest</a>
|
||
<span class="close" onclick="document.getElementById("wtpGapFillBanner").classList.add("hidden");localStorage.setItem("wtpGapFillHidden","1")">×</span>
|
||
</div>
|
||
<script>
|
||
(async()=>{
|
||
if(localStorage.getItem("wtpGapFillHidden")==="1"){document.getElementById("wtpGapFillBanner").classList.add("hidden");return;}
|
||
try{
|
||
const r=await fetch("/api/source-of-truth.json?t="+Date.now());
|
||
const d=await r.json();
|
||
const el=document.getElementById("wtp-gfb-metrics");
|
||
if(el)el.textContent=(d.ethica_total||"?")+" HCPs · "+(d.nonreg||"?")+" · "+(d.providers_count||"?")+" IA · "+(d.agents_count||"?")+" agents · "+(d.docker_running||"?")+" 🐳";
|
||
}catch(e){}
|
||
})();
|
||
</script>
|
||
|
||
<!-- WTP-D90V2-ENRICH-BANNER (doctrine 90-v2, 17avr 2026) -->
|
||
<style>
|
||
.wtp-enrich-banner{position:fixed;bottom:0;left:0;right:0;z-index:9999;background:linear-gradient(90deg,#0b0d15,#181d2e,#0b0d15);border-top:2px solid #14b8a6;color:#e2e8f0;padding:9px 18px;font-family:'JetBrains Mono',monospace,-apple-system,system-ui;font-size:11.5px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;box-shadow:0 -8px 24px rgba(20,184,166,.25)}
|
||
.wtp-enrich-banner a{color:#14b8a6;text-decoration:none;font-weight:600}
|
||
.wtp-enrich-banner a:hover{color:#22d3ee}
|
||
.wtp-enrich-banner .pill{padding:2px 8px;background:rgba(99,102,241,.15);color:#a5b4fc;border-radius:10px;font-size:10.5px}
|
||
.wtp-enrich-banner .pill.new{background:rgba(20,184,166,.2);color:#5eead4}
|
||
.wtp-enrich-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 6px;font-size:14px}
|
||
.wtp-enrich-banner .close:hover{color:#e2e8f0}
|
||
.wtp-enrich-banner.hidden{display:none}
|
||
@media(max-width:768px){.wtp-enrich-banner{font-size:10px;padding:6px 10px}}
|
||
</style>
|
||
<div class="wtp-enrich-banner" id="wtpEnrichBanner">
|
||
<span>🏛️ <strong>Enterprise Model 16 depts</strong></span>
|
||
<span class="pill new">🆕 Meeting Rooms</span>
|
||
<span class="pill new">🆕 Lean 6 Sigma</span>
|
||
<span id="wtp-eb-metrics" class="pill">— chargement —</span>
|
||
<a href="/weval-technology-platform.html">→ WEVAL Technology Platform (16 modules)</a>
|
||
<a href="/enterprise-model.html">Enterprise Model</a>
|
||
<a href="/wevia-master.html">WEVIA Master</a>
|
||
<span class="close" onclick="document.getElementById('wtpEnrichBanner').classList.add('hidden')">×</span>
|
||
</div>
|
||
<script>
|
||
(async()=>{try{const r=await fetch('/api/source-of-truth.json?t='+Date.now());const d=await r.json();const el=document.getElementById('wtp-eb-metrics');if(el)el.textContent=(d.ethica_total||'?')+' HCPs · '+(d.nonreg||'?')+' · '+(d.providers_count||'?')+' IA · '+(d.docker_running||'?')+' 🐳 · '+(d.subdomains_live||'?')+' subdomains';}catch(e){}})();
|
||
</script>
|
||
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||
<script>
|
||
(function(){
|
||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||
var d = document;
|
||
var m = d.createElement('div');
|
||
m.id = 'opus-udrill';
|
||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||
var inner = d.createElement('div');
|
||
inner.id = 'opus-udrill-in';
|
||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||
m.appendChild(inner);
|
||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||
(d.body || d.documentElement).appendChild(m);
|
||
|
||
function openCard(card) {
|
||
// Clone card content + show close btn + increase font-size
|
||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||
inner.innerHTML = html;
|
||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||
m.style.display = 'flex';
|
||
}
|
||
|
||
function wire(root) {
|
||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||
var cards = root.querySelectorAll(sels);
|
||
for (var i = 0; i < cards.length; i++) {
|
||
var c = cards[i];
|
||
if (c.__opusWired) continue;
|
||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||
var r = c.getBoundingClientRect();
|
||
if (r.width < 60 || r.height < 40) continue;
|
||
c.__opusWired = true;
|
||
c.style.cursor = 'pointer';
|
||
c.setAttribute('role','button');
|
||
c.setAttribute('tabindex','0');
|
||
c.addEventListener('click', function(ev){
|
||
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
|
||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||
if (ev.target.closest('a,button,input,select')) return;
|
||
ev.preventDefault(); ev.stopPropagation();
|
||
openCard(this);
|
||
});
|
||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||
}
|
||
}
|
||
|
||
// Initial + mutation observer
|
||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||
else initRun();
|
||
var mo = new MutationObserver(function(muts){
|
||
var newCard = false;
|
||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||
if (newCard) initRun();
|
||
});
|
||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||
})();
|
||
</script>
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||
|
||
|
||
<!-- === OPUS HONEST NR/L99 OVERLAY v1 19avr - append-only doctrine #14 === -->
|
||
<script>
|
||
(function(){
|
||
if (window.__opusHonestOverlay) return; window.__opusHonestOverlay = true;
|
||
async function updateHonestValues(){
|
||
try {
|
||
const r = await fetch('/api/l99-honest.php', {cache:'no-store'});
|
||
const d = await r.json();
|
||
if (!d.ok) return;
|
||
const realNR = `${d.combined.pass}/${d.combined.total}`;
|
||
const realSigma = d.sigma;
|
||
// Find elements showing the myth values
|
||
const mythRegex = /(153\/153|304\/304|NR status 153\/153|L99 status 304\/304|NR 153\/153|L99 304\/304)/g;
|
||
// Walk text nodes
|
||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null);
|
||
const toReplace = [];
|
||
let node;
|
||
while (node = walker.nextNode()) {
|
||
if (node.nodeValue && mythRegex.test(node.nodeValue)) toReplace.push(node);
|
||
}
|
||
toReplace.forEach(textNode => {
|
||
const parent = textNode.parentNode;
|
||
if (!parent || parent.hasAttribute('data-opus-honest-applied')) return;
|
||
const newText = textNode.nodeValue.replace(/153\/153/g, realNR).replace(/304\/304/g, realNR);
|
||
textNode.nodeValue = newText;
|
||
parent.setAttribute('data-opus-honest-applied', '1');
|
||
});
|
||
// Add a small badge bottom-right showing honest live status
|
||
if (!document.getElementById('opus-honest-badge')) {
|
||
const b = document.createElement('div');
|
||
b.id = 'opus-honest-badge';
|
||
b.style.cssText = 'position:fixed;bottom:12px;right:12px;background:linear-gradient(90deg,#14b8a6,#a855f7);color:#05060a;padding:6px 12px;font:10px/1.3 Inter,system-ui,sans-serif;font-weight:700;border-radius:8px;z-index:99993;box-shadow:0 4px 12px rgba(0,0,0,0.3);cursor:pointer;max-width:280px';
|
||
b.title = 'Cliquer pour détails';
|
||
b.innerHTML = `✓ NR ${realNR} · ${realSigma} live`;
|
||
b.onclick = () => {
|
||
alert(`HONEST NonReg (doctrine #4):\n\nmaster: ${d.master.pass}/${d.master.total}\nopus: ${d.opus.pass}/${d.opus.total}\ncombined: ${realNR}\nsigma: ${realSigma}\n\n${d.myth_153}\n${d.myth_304}`);
|
||
};
|
||
document.body.appendChild(b);
|
||
}
|
||
} catch(e){console.error('L99-honest fetch error:', e);}
|
||
}
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateHonestValues);
|
||
else updateHonestValues();
|
||
setInterval(updateHonestValues, 90000);
|
||
})();
|
||
</script>
|
||
<!-- === OPUS HONEST END === -->
|
||
|
||
|
||
<script>
|
||
// Opus v9.32 gaps banner live
|
||
(async function(){
|
||
try {
|
||
const r = await fetch('/api/weval-agents-gap-fill-manifest.json');
|
||
const d = await r.json();
|
||
const erp = d.erp_gaps_covered || {};
|
||
let total = 0;
|
||
for (const k in erp) {
|
||
const v = erp[k];
|
||
if (Array.isArray(v)) total += v.length;
|
||
else if (v && Array.isArray(v.gaps)) total += v.gaps.length;
|
||
}
|
||
const el = document.getElementById('gaps-banner-count');
|
||
if (el && total > 0) el.textContent = total + ' ERP gaps';
|
||
} catch(e) {}
|
||
})();
|
||
</script>
|
||
|
||
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
||
<!-- WTP_UDOCK_V1 (Opus 21-avr t32b4) --><script src="/wtp-unified-dock.js" defer></script>
|
||
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
|
||
</body></html>
|