<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nguồn dữ liệu & lịch chạy — Nolimit Ads Manager</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'Noto Sans SC', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
colors: {
ink: {
50: '#fafafa',
100: '#f4f4f5',
200: '#e5e7eb',
300: '#d4d4d8',
400: '#a1a1aa',
500: '#71717a',
600: '#52525b',
700: '#3f3f46',
800: '#27272a',
900: '#18181b',
950: '#0a0a0a',
},
brand: {
50: '#eef4ff',
100: '#dce8ff',
500: '#4f46e5',
600: '#4338ca',
700: '#3730a3',
900: '#1e1b4b',
},
accent: '#f97316',
}
}
}
}
</script>
<style>
html { scroll-behavior: smooth; }
body { font-feature-settings: "cv02","cv03","cv04","cv11"; }
.prose-doc { max-width: 72ch; }
.prose-doc p { line-height: 1.75; }
.prose-doc h2 { scroll-margin-top: 80px; }
.prose-doc h3 { scroll-margin-top: 80px; }
.prose-doc h4 { scroll-margin-top: 80px; }
.toc-link { transition: all 0.15s ease; border-left: 2px solid transparent; }
.toc-link.active { color: rgb(79 70 229); border-left-color: rgb(79 70 229); font-weight: 500; background: rgba(79,70,229,0.05); }
.dark .toc-link.active { color: #a5b4fc; border-left-color: #a5b4fc; background: rgba(165,180,252,0.08); }
.nav-link.active { background: rgba(79,70,229,0.08); color: rgb(79 70 229); font-weight: 500; }
.dark .nav-link.active { background: rgba(165,180,252,0.1); color: #a5b4fc; }
pre code { font-family: 'JetBrains Mono', monospace; font-size: 13px; line-height: 1.65; }
.code-block { position: relative; }
.copy-btn { opacity: 0; transition: opacity 0.2s; }
.code-block:hover .copy-btn { opacity: 1; }
details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
details[open] > summary .chev { transform: rotate(90deg); }
.chev { transition: transform 0.2s; }
.fade-in { animation: fadeIn 0.4s ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
table { border-collapse: collapse; }
.badge-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 4px; }
.dark ::-webkit-scrollbar-thumb { background: #3f3f46; }
::-webkit-scrollbar-track { background: transparent; }
.grid-pattern {
background-image: linear-gradient(to right, rgba(0,0,0,0.04) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0,0,0,0.04) 1px, transparent 1px);
background-size: 24px 24px;
}
.dark .grid-pattern {
background-image: linear-gradient(to right, rgba(255,255,255,0.04) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255,255,255,0.04) 1px, transparent 1px);
}
.bot-row td { vertical-align: top; }
.freq-pill { font-variant-numeric: tabular-nums; font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 600; }
</style>
</head>
<body class="bg-ink-50 text-ink-900 dark:bg-ink-950 dark:text-ink-100 font-sans antialiased">
<!-- TOP BAR -->
<header class="sticky top-0 z-50 bg-ink-50/85 dark:bg-ink-950/85 backdrop-blur-md border-b border-ink-200 dark:border-ink-800">
<div class="max-w-[1600px] mx-auto px-6 h-14 flex items-center gap-6">
<div class="flex items-center gap-2.5">
<div class="w-7 h-7 rounded-lg bg-gradient-to-br from-brand-500 to-brand-700 flex items-center justify-center text-white font-bold text-xs">N</div>
<div>
<div class="text-[13px] font-semibold leading-tight">Nolimit Ads Manager</div>
<div class="text-[10px] text-ink-500 leading-tight">Data Sources & Bot Schedule</div>
</div>
</div>
<div class="flex-1 max-w-md">
<div class="relative">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-ink-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>
<input id="searchInput" type="text" placeholder="Tìm trong tài liệu... (Ctrl + K)" class="w-full bg-ink-100 dark:bg-ink-900 border border-ink-200 dark:border-ink-800 rounded-lg pl-9 pr-16 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500/30 focus:border-brand-500/50">
<kbd class="absolute right-3 top-1/2 -translate-y-1/2 text-[10px] text-ink-500 font-mono bg-ink-200 dark:bg-ink-800 px-1.5 py-0.5 rounded">⌘K</kbd>
</div>
</div>
<div class="hidden md:flex items-center gap-3 text-xs">
<div class="flex items-center gap-1.5 px-2.5 py-1 rounded-md bg-ink-100 dark:bg-ink-900 border border-ink-200 dark:border-ink-800">
<span class="badge-dot bg-emerald-500"></span>
<span class="text-ink-600 dark:text-ink-400 font-mono">v2026.06.18</span>
</div>
<div class="text-ink-500 dark:text-ink-400">Cập nhật: <span class="font-mono text-ink-700 dark:text-ink-300">2026-06-18</span></div>
</div>
<button id="themeToggle" class="p-2 rounded-lg hover:bg-ink-100 dark:hover:bg-ink-900 transition-colors" aria-label="Toggle theme">
<svg class="w-4 h-4 dark:hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
<svg class="w-4 h-4 hidden dark:block" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
</button>
<a href="https://nolimitadsmanager.com" class="hidden lg:flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg bg-brand-500 hover:bg-brand-600 text-white font-medium transition-colors">
Hub
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>
</a>
</div>
</header>
<div class="max-w-[1600px] mx-auto px-6 grid grid-cols-12 gap-8">
<!-- LEFT NAV -->
<aside class="hidden lg:block col-span-2 sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-8 pr-2">
<nav id="leftNav" class="space-y-6 text-[13px]">
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-400 font-semibold mb-2 px-2">Tổng quan</div>
<a href="#overview" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Bức tranh tổng thể</a>
<a href="#glossary" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Cách đọc tên nguồn</a>
<a href="#summary" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Tổng kết thực tế</a>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-400 font-semibold mb-2 px-2">14 Bot</div>
<a href="#default-state" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Trạng thái mặc định</a>
<a href="#schedule" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Lịch chạy</a>
<a href="#group-continuous" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-600 dark:text-ink-400 text-xs pl-5">↳ Liên tục</a>
<a href="#group-hourly" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-600 dark:text-ink-400 text-xs pl-5">↳ Theo giờ</a>
<a href="#group-halfday" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-600 dark:text-ink-400 text-xs pl-5">↳ Nửa ngày</a>
<a href="#group-daily" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-600 dark:text-ink-400 text-xs pl-5">↳ Ngày / 1-lần</a>
<a href="#two-axes" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Hai trục chính</a>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-400 font-semibold mb-2 px-2">Sidebar Khách</div>
<a href="#sb-home" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">🏠 Trang chủ</a>
<a href="#sb-dashboard" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">📊 Dashboard</a>
<a href="#sb-asset" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">📦 Tài sản</a>
<a href="#sb-finance" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">💰 Tài chính</a>
<a href="#sb-connect" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">🔗 Kết nối</a>
<a href="#sb-support" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">🆘 Hỗ trợ</a>
<a href="#sb-bell" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">🔔 Bell thông báo</a>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-400 font-semibold mb-2 px-2">Admin & Khác</div>
<a href="#admin" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">🛡 Admin functions</a>
<a href="#misc" class="nav-link block px-2 py-1.5 rounded-md hover:bg-ink-100 dark:hover:bg-ink-900 text-ink-700 dark:text-ink-300">Khác</a>
</div>
</nav>
</aside>
<!-- ARTICLE BODY -->
<main class="col-span-12 lg:col-span-8 xl:col-span-7 py-10">
<!-- HERO -->
<div class="mb-12 fade-in">
<div class="flex items-center gap-2 text-xs text-ink-500 mb-4">
<span class="px-2 py-0.5 rounded-md bg-brand-50 dark:bg-brand-900/30 text-brand-700 dark:text-brand-100 font-medium">Tài liệu vận hành</span>
<span>·</span>
<span>Hệ thống nội bộ</span>
<span>·</span>
<span class="font-mono">14 bot</span>
</div>
<h1 class="text-4xl md:text-5xl font-bold tracking-tight leading-[1.1] mb-4">
Nguồn dữ liệu & lịch chạy
<span class="block text-2xl md:text-3xl text-ink-500 dark:text-ink-400 font-normal mt-2">Hệ thống Nolimit Ads Manager</span>
</h1>
<p class="text-lg text-ink-600 dark:text-ink-400 leading-relaxed max-w-2xl">
Tất cả nguồn data web Khách lấy về + lịch chạy <strong class="text-ink-900 dark:text-ink-100">14 bot tự động</strong> + cách chúng phối hợp.
</p>
<div class="mt-8 grid grid-cols-2 md:grid-cols-4 gap-3">
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900 p-4">
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold">Tổng số bot</div>
<div class="text-2xl font-bold mt-1 font-mono">14</div>
<div class="text-[11px] text-ink-500 mt-0.5">tự động</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900 p-4">
<div class="text-[10px] uppercase tracking-wider text-emerald-600 dark:text-emerald-400 font-semibold">Bật mặc định</div>
<div class="text-2xl font-bold mt-1 font-mono text-emerald-600 dark:text-emerald-400">10</div>
<div class="text-[11px] text-ink-500 mt-0.5">bot</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900 p-4">
<div class="text-[10px] uppercase tracking-wider text-amber-600 dark:text-amber-400 font-semibold">Tắt mặc định</div>
<div class="text-2xl font-bold mt-1 font-mono text-amber-600 dark:text-amber-400">3</div>
<div class="text-[11px] text-ink-500 mt-0.5">admin bật khi cần</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900 p-4">
<div class="text-[10px] uppercase tracking-wider text-brand-600 dark:text-brand-100 font-semibold">Topup riêng</div>
<div class="text-2xl font-bold mt-1 font-mono text-brand-600 dark:text-brand-100">2</div>
<div class="text-[11px] text-ink-500 mt-0.5">kết nối ngoài</div>
</div>
</div>
</div>
<article class="prose-doc">
<!-- OVERVIEW -->
<section id="overview" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§1</span>
Bức tranh tổng thể
</h2>
<p class="text-ink-700 dark:text-ink-300">Web Khách hiển thị data đến từ <strong>3 nguồn</strong>:</p>
<div class="grid md:grid-cols-3 gap-4 my-6 not-prose">
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-gradient-to-br from-brand-50 to-white dark:from-brand-900/20 dark:to-ink-900 p-5">
<div class="text-xs text-brand-700 dark:text-brand-100 font-mono font-semibold mb-2">SOURCE 01</div>
<div class="font-semibold text-base mb-1">14 bot tự động</div>
<div class="text-sm text-ink-600 dark:text-ink-400 leading-relaxed">Chạy 24/7 ở server — refresh đa số data Facebook quan trọng (trạng thái TKQC, bill, chi tiêu, BM info, alert thẻ…).</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-gradient-to-br from-emerald-50 to-white dark:from-emerald-900/20 dark:to-ink-900 p-5">
<div class="text-xs text-emerald-700 dark:text-emerald-300 font-mono font-semibold mb-2">SOURCE 02</div>
<div class="font-semibold text-base mb-1">Extension Chrome</div>
<div class="text-sm text-ink-600 dark:text-ink-400 leading-relaxed">Chạy trên trình duyệt user — bổ sung data theo phiên FB live (cookie, EAAG, EAAB, billing hub…).</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 bg-gradient-to-br from-amber-50 to-white dark:from-amber-900/20 dark:to-ink-900 p-5">
<div class="text-xs text-amber-700 dark:text-amber-300 font-mono font-semibold mb-2">SOURCE 03</div>
<div class="font-semibold text-base mb-1">Thủ công</div>
<div class="text-sm text-ink-600 dark:text-ink-400 leading-relaxed">User bấm "Đồng bộ" khi muốn data tươi NGAY, không đợi bot / extension.</div>
</div>
</div>
<div class="rounded-lg border-l-4 border-brand-500 bg-brand-50 dark:bg-brand-900/20 p-4 my-6 not-prose">
<div class="flex gap-3">
<svg class="w-5 h-5 text-brand-600 dark:text-brand-100 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
<div class="text-sm text-ink-700 dark:text-ink-200">
<strong class="text-brand-700 dark:text-brand-100">Key insight:</strong> User KHÔNG cài extension vẫn có data tươi nhờ bot. Extension là kênh <strong>bổ sung</strong> chứ không phải duy nhất.
</div>
</div>
</div>
</section>
<!-- GLOSSARY -->
<section id="glossary" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§2</span>
Cách đọc tên các nguồn
</h2>
<p class="text-ink-700 dark:text-ink-300 mb-6">Glossary các thuật ngữ về nguồn dữ liệu xuất hiện trong toàn bộ tài liệu.</p>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left">
<tr>
<th class="px-4 py-3 font-semibold text-ink-700 dark:text-ink-300 w-1/3">Tên nguồn</th>
<th class="px-4 py-3 font-semibold text-ink-700 dark:text-ink-300">Nghĩa là gì</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr><td class="px-4 py-3 font-medium"><span class="font-mono text-xs px-1.5 py-0.5 rounded bg-brand-50 dark:bg-brand-900/40 text-brand-700 dark:text-brand-100">Bot tự động</span></td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Service chạy server-side, đập vào FB rồi ghi vào DB chung. Web Khách đọc từ DB là thấy.</td></tr>
<tr><td class="px-4 py-3 font-medium">Token hệ thống BM</td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Token cấp ở Business Manager. Không cần cookie, không cần proxy.</td></tr>
<tr><td class="px-4 py-3 font-medium">Token OAuth</td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Token user xin qua OAuth (hiện tại chưa xin được).</td></tr>
<tr><td class="px-4 py-3 font-medium">Token user <span class="font-mono text-xs">EAAG</span> / <span class="font-mono text-xs">EAAB</span></td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Token trích từ HTML Facebook. <strong>Bắt buộc</strong> cookie + proxy của VIA.</td></tr>
<tr><td class="px-4 py-3 font-medium">Cookie phiên Facebook</td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Cookie <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">c_user, xs, datr…</code> Bắt buộc proxy. Dùng cho thẻ BM, billing.</td></tr>
<tr><td class="px-4 py-3 font-medium">Extension Chrome</td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Extension trên trình duyệt user, chạy nền đẩy data lên server.</td></tr>
<tr><td class="px-4 py-3 font-medium">DB nội bộ <span class="font-mono text-xs text-ink-500">(Supabase + ClickHouse)</span></td><td class="px-4 py-3 text-ink-700 dark:text-ink-300">Data đã được bot / extension / user sync về từ trước.</td></tr>
</tbody>
</table>
</div>
</section>
<!-- SUMMARY -->
<section id="summary" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§3</span>
Tổng kết theo cách hiểu thực tế
</h2>
<p class="text-ink-700 dark:text-ink-300 mb-6">6 nguyên tắc cốt lõi cần nắm trước khi đọc tiếp.</p>
<div class="space-y-3 not-prose">
<div class="flex gap-4 p-4 rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-brand-50 dark:bg-brand-900/40 flex items-center justify-center text-brand-700 dark:text-brand-100 font-bold text-sm">1</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-ink-900 dark:text-ink-100">Data FB quan trọng được bot auto-refresh</strong> chu kỳ 5 giây → 12 giờ tuỳ loại. Không phải thủ công.
</div>
</div>
<div class="flex gap-4 p-4 rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-brand-50 dark:bg-brand-900/40 flex items-center justify-center text-brand-700 dark:text-brand-100 font-bold text-sm">2</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-ink-900 dark:text-ink-100">Bot cào activity log (3h) là trung tâm</strong> — 3 bot khác phụ thuộc vào nó: sync campaign, check bill, heat-score đều dùng output của bot này.
</div>
</div>
<div class="flex gap-4 p-4 rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-brand-50 dark:bg-brand-900/40 flex items-center justify-center text-brand-700 dark:text-brand-100 font-bold text-sm">3</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-ink-900 dark:text-ink-100">Bot thông báo (5s) là đầu ra cuối</strong> — mọi bot khác đẩy vào <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1.5 py-0.5 rounded">notification_queue</code>, bot này lo gửi đi (web bell + Telegram).
</div>
</div>
<div class="flex gap-4 p-4 rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-brand-50 dark:bg-brand-900/40 flex items-center justify-center text-brand-700 dark:text-brand-100 font-bold text-sm">4</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-ink-900 dark:text-ink-100">Mặc định chạy 10 bot.</strong> 3 bot tắt (admin bật khi cần) + 2 bot Topup cần admin bật riêng vì kết nối hệ thống ngoài.
</div>
</div>
<div class="flex gap-4 p-4 rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-900">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-brand-50 dark:bg-brand-900/40 flex items-center justify-center text-brand-700 dark:text-brand-100 font-bold text-sm">5</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-ink-900 dark:text-ink-100">Bill và thẻ BM cứng credential</strong>:
<ul class="mt-2 space-y-1 ml-1">
<li class="flex gap-2"><span class="text-brand-500">▸</span><span><strong>Bill TKQC:</strong> PHẢI cookie VIA + token user.</span></li>
<li class="flex gap-2"><span class="text-brand-500">▸</span><span><strong>Thẻ BM (Billing Hub):</strong> PHẢI cookie + dtsg.</span></li>
</ul>
</div>
</div>
<div class="flex gap-4 p-4 rounded-xl border-l-4 border-l-rose-500 border border-ink-200 dark:border-ink-800 bg-rose-50/40 dark:bg-rose-950/20">
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-rose-100 dark:bg-rose-900/40 flex items-center justify-center text-rose-700 dark:text-rose-300 font-bold text-sm">6</div>
<div class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">
<strong class="text-rose-700 dark:text-rose-300">Cookie hết hạn → không tự fallback sang token</strong> cho operation đòi cookie.
</div>
</div>
</div>
</section>
<!-- DEFAULT STATE -->
<section id="default-state" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§4</span>
Trạng thái mặc định 14 bot
</h2>
<div class="space-y-3 not-prose">
<div class="rounded-xl border border-emerald-200 dark:border-emerald-900/50 bg-emerald-50/50 dark:bg-emerald-950/20 p-5">
<div class="flex items-center gap-3 mb-3">
<div class="w-8 h-8 rounded-lg bg-emerald-500 text-white flex items-center justify-center font-bold">✓</div>
<div>
<div class="font-semibold text-emerald-900 dark:text-emerald-200">Bật mặc định <span class="font-mono text-xs ml-1">(10 bot)</span></div>
<div class="text-xs text-emerald-700 dark:text-emerald-400">Chạy ngay khi service khởi động</div>
</div>
</div>
<div class="flex flex-wrap gap-1.5 text-xs">
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Thông báo</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Check status TKQC</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Check bill</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Cào activity</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Heat-score</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Sync campaign</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Check chi tiêu</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Cảnh báo thẻ hết hạn</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Sync BM gắn sao — info</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-emerald-900/40 border border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200">Sync BM gắn sao — limit</span>
</div>
</div>
<div class="rounded-xl border border-amber-200 dark:border-amber-900/50 bg-amber-50/50 dark:bg-amber-950/20 p-5">
<div class="flex items-center gap-3 mb-3">
<div class="w-8 h-8 rounded-lg bg-amber-500 text-white flex items-center justify-center font-bold">⚙</div>
<div>
<div class="font-semibold text-amber-900 dark:text-amber-200">Tắt mặc định <span class="font-mono text-xs ml-1">(3 bot)</span></div>
<div class="text-xs text-amber-700 dark:text-amber-400">Admin bật khi cần</div>
</div>
</div>
<div class="flex flex-wrap gap-1.5 text-xs">
<span class="px-2 py-1 rounded-md bg-white dark:bg-amber-900/40 border border-amber-200 dark:border-amber-800 text-amber-900 dark:text-amber-200">Reset limit chi tiêu</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-amber-900/40 border border-amber-200 dark:border-amber-800 text-amber-900 dark:text-amber-200">Backfill chi tiêu</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-amber-900/40 border border-amber-200 dark:border-amber-800 text-amber-900 dark:text-amber-200">Test bill</span>
</div>
</div>
<div class="rounded-xl border border-brand-200 dark:border-brand-700/50 bg-brand-50/50 dark:bg-brand-900/20 p-5">
<div class="flex items-center gap-3 mb-3">
<div class="w-8 h-8 rounded-lg bg-brand-500 text-white flex items-center justify-center font-bold">🔌</div>
<div>
<div class="font-semibold text-brand-900 dark:text-brand-100">Cần admin bật riêng <span class="font-mono text-xs ml-1">(2 bot)</span></div>
<div class="text-xs text-brand-700 dark:text-brand-100">Kết nối Topup ngoài</div>
</div>
</div>
<div class="flex flex-wrap gap-1.5 text-xs">
<span class="px-2 py-1 rounded-md bg-white dark:bg-brand-900/40 border border-brand-200 dark:border-brand-800 text-brand-900 dark:text-brand-100">Auto share TKQC</span>
<span class="px-2 py-1 rounded-md bg-white dark:bg-brand-900/40 border border-brand-200 dark:border-brand-800 text-brand-900 dark:text-brand-100">Auto gỡ TKQC</span>
</div>
</div>
</div>
</section>
<!-- SCHEDULE -->
<section id="schedule" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-2 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§5</span>
Lịch chạy 14 bot tự động
</h2>
<p class="text-ink-700 dark:text-ink-300 mb-6">Chia theo chu kỳ chạy. Ký hiệu: <span class="font-mono">⚙</span> = tắt mặc định, <span class="font-mono">🔌</span> = cần admin bật riêng (kết nối ngoài), <span class="font-mono">🔵</span> = bot trung tâm.</p>
<!-- CONTINUOUS -->
<h3 id="group-continuous" class="text-lg font-semibold mt-10 mb-3 flex items-center gap-3">
<span class="badge-dot bg-rose-500"></span>
Nhóm LIÊN TỤC <span class="text-sm text-ink-500 font-normal">(giây / phút) — cập nhật tức thì</span>
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-10">#</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Bot</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-20">Mỗi</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Việc làm</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">01</td>
<td class="px-3 py-3 font-medium">Thông báo</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-950/40 text-rose-700 dark:text-rose-300">5 s</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Quét <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">notification_queue</code>, đẩy lên chuông web + Telegram + NolimitHub. 1h/lần dọn rác noti cũ.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">02</td>
<td class="px-3 py-3 font-medium">Auto gỡ TKQC <span class="text-brand-500">🔌</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-950/40 text-rose-700 dark:text-rose-300">10 s</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Check Topup có đơn cần gỡ → unshare từng cặp (TKQC, BM). Tối đa 20 đơn/lần.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">03</td>
<td class="px-3 py-3 font-medium">Auto share TKQC <span class="text-brand-500">🔌</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-950/40 text-rose-700 dark:text-rose-300">30 s</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Check Topup có đơn cần share → chia kho TKQC chưa share, share từng cái, báo lại Topup.</td>
</tr>
</tbody>
</table>
</div>
<!-- HOURLY -->
<h3 id="group-hourly" class="text-lg font-semibold mt-10 mb-3 flex items-center gap-3">
<span class="badge-dot bg-amber-500"></span>
Nhóm theo GIỜ <span class="text-sm text-ink-500 font-normal">— cập nhật từ Facebook</span>
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-10">#</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Bot</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-20">Mỗi</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Việc làm</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">04</td>
<td class="px-3 py-3 font-medium">Check trạng thái TKQC</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">1 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Gọi FB Graph <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">/me/adaccounts</code> qua mọi token sống. TKQC đổi status (active→disabled) → ghi history + notify.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">05</td>
<td class="px-3 py-3 font-medium">Check hoá đơn (bill)</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">1 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Đọc ClickHouse activity 10 ngày → bill chưa fetch → dùng cookie VIA gọi GraphQL BillingHub lấy chi tiết bill. Bill FB không trả → notify "FB nợ bill".</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">06</td>
<td class="px-3 py-3 font-medium">Reset limit chi tiêu <span class="text-amber-500">⚙</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">2 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">TKQC die còn cap → confirm FB → set <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">spend_cap=0</code>, đợi 8s, set <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">0.01 USD / 1 VND</code>.</td>
</tr>
<tr class="bot-row bg-brand-50/30 dark:bg-brand-900/10">
<td class="px-3 py-3 font-mono text-brand-600 dark:text-brand-300 font-bold">07</td>
<td class="px-3 py-3 font-semibold">Cào activity log <span class="text-brand-500">🔵</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-brand-100 dark:bg-brand-900/60 text-brand-700 dark:text-brand-100">3 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Gọi <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">/act_X/activities</code> cho TKQC eligible từ checkpoint → bulk insert ClickHouse. <strong>Là nguồn cho bot #05, #08, #09.</strong></td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">08</td>
<td class="px-3 py-3 font-medium">Heat-score (điểm nóng)</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">3 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Đếm ngày chi tiêu 30 ngày qua → tính điểm: starred <strong>+10</strong>, BM die <strong>−3</strong>, ≥20 ngày active <strong>+5</strong>… → ghi <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">heat_score</code> để hiển thị badge.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">09</td>
<td class="px-3 py-3 font-medium">Sync campaign/adset/ad</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">~3 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300"><span class="text-xs text-ink-500">(sau bot #07 ~1h)</span> Poll checkpoint mỗi 15p. Khi bot activity vừa chạy xong + flush 1h → query CH lấy TKQC có thay đổi structure → gọi FB lấy chi tiết campaign/adset/ad → UPSERT Postgres.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">10</td>
<td class="px-3 py-3 font-medium">Check chi tiêu</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300">6 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Gọi FB Insights, overlap 3 ngày để chống stale, ghi đủ mỗi ngày kể cả spend=0 vào ClickHouse.</td>
</tr>
</tbody>
</table>
</div>
<!-- HALF-DAY -->
<h3 id="group-halfday" class="text-lg font-semibold mt-10 mb-3 flex items-center gap-3">
<span class="badge-dot bg-sky-500"></span>
Nhóm NỬA NGÀY <span class="text-sm text-ink-500 font-normal">— việc ít gấp</span>
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-10">#</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Bot</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-28">Mỗi</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Việc làm</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">11</td>
<td class="px-3 py-3 font-medium">Cảnh báo thẻ hết hạn</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-sky-50 dark:bg-sky-950/40 text-sky-700 dark:text-sky-300">12 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Quét <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">fb_payment_instruments</code>, thẻ ≤30 ngày hết hạn → push notify (dedup 24h).</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">12</td>
<td class="px-3 py-3 font-medium">Sync BM gắn sao — info</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-sky-50 dark:bg-sky-950/40 text-sky-700 dark:text-sky-300">12 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Batch 20 BM/lần, gọi FB Graph cào: name, status, verification, profile. Service này chạy 2 loop song song với bot #13.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">13</td>
<td class="px-3 py-3 font-medium">Sync BM gắn sao — limit</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-sky-50 dark:bg-sky-950/40 text-sky-700 dark:text-sky-300 leading-tight">9 h + 14 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300"><strong>9h sáng + 14h chiều VN.</strong> Tick 5 phút, check giờ VN. Đúng slot → gọi BillingHub bằng <strong>cookie VIA</strong> cào <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">ad_account_limit</code> (không có trong Graph API).</td>
</tr>
</tbody>
</table>
</div>
<!-- DAILY -->
<h3 id="group-daily" class="text-lg font-semibold mt-10 mb-3 flex items-center gap-3">
<span class="badge-dot bg-violet-500"></span>
Nhóm NGÀY / 1-LẦN <span class="text-sm text-ink-500 font-normal">— công cụ vận hành</span>
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-10">#</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Bot</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-20">Mỗi</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Việc làm</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">14</td>
<td class="px-3 py-3 font-medium">Backfill chi tiêu <span class="text-amber-500">⚙</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-violet-50 dark:bg-violet-950/40 text-violet-700 dark:text-violet-300">24 h</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Lấp lỗ trống lịch sử mà bot #10 (chỉ overlap 3 ngày) không phát hiện ra.</td>
</tr>
<tr class="bot-row">
<td class="px-3 py-3 font-mono text-ink-500">—</td>
<td class="px-3 py-3 font-medium">Test bill <span class="text-amber-500">⚙</span></td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-ink-100 dark:bg-ink-800 text-ink-600 dark:text-ink-400">1 lần</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">Debug 1 TKQC cụ thể khi nghi bill có vấn đề. Chạy xong dừng luôn.</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- TWO AXES -->
<section id="two-axes" class="mb-16">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§6</span>
Hai trục chính
</h2>
<div class="grid md:grid-cols-2 gap-4 not-prose">
<div class="rounded-xl border-2 border-brand-200 dark:border-brand-700 bg-gradient-to-br from-brand-50 to-white dark:from-brand-900/30 dark:to-ink-900 p-5">
<div class="flex items-center gap-2 mb-3">
<span class="text-2xl">🔵</span>
<div>
<div class="text-[10px] uppercase tracking-wider font-semibold text-brand-700 dark:text-brand-100">Trục SỰ KIỆN</div>
<div class="font-bold text-base">Bot #07 — Cào activity</div>
</div>
</div>
<p class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">Là <strong>nguồn sự kiện trung tâm</strong>. 3 bot phụ thuộc trực tiếp:</p>
<ul class="mt-2 space-y-1 text-sm text-ink-700 dark:text-ink-300">
<li class="flex gap-2"><span class="text-brand-500 font-mono">→</span> Bot <strong>#05</strong> check bill</li>
<li class="flex gap-2"><span class="text-brand-500 font-mono">→</span> Bot <strong>#09</strong> sync campaign</li>
<li class="flex gap-2"><span class="text-brand-500 font-mono">→</span> Gián tiếp: <strong>#08</strong> heat-score</li>
</ul>
</div>
<div class="rounded-xl border-2 border-rose-200 dark:border-rose-700 bg-gradient-to-br from-rose-50 to-white dark:from-rose-900/30 dark:to-ink-900 p-5">
<div class="flex items-center gap-2 mb-3">
<span class="text-2xl">📤</span>
<div>
<div class="text-[10px] uppercase tracking-wider font-semibold text-rose-700 dark:text-rose-300">Trục ĐẦU RA</div>
<div class="font-bold text-base">Bot #01 — Thông báo</div>
</div>
</div>
<p class="text-sm text-ink-700 dark:text-ink-300 leading-relaxed">Là <strong>đầu ra cuối</strong> của hệ thống.</p>
<ul class="mt-2 space-y-1 text-sm text-ink-700 dark:text-ink-300">
<li class="flex gap-2"><span class="text-rose-500 font-mono">→</span> Mọi bot khác push vào <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">notification_queue</code></li>
<li class="flex gap-2"><span class="text-rose-500 font-mono">→</span> Bot #01 lo gửi đi: web bell, Telegram, NolimitHub</li>
</ul>
</div>
</div>
</section>
<!-- SIDEBAR DETAIL HEADING -->
<section class="mb-10">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§7</span>
Chi tiết theo thanh toolbar bên trái
</h2>
<p class="text-ink-700 dark:text-ink-300">Mỗi mục dưới đây tương ứng với 1 mục trên sidebar khách. Cột "Auto" = bot / extension nào tự refresh và mỗi bao lâu. Cột "Thủ công" = có nút "Đồng bộ" trên trang đó không.</p>
</section>
<!-- 🏠 HOME -->
<section id="sb-home" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">🏠</span> Trang chủ
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-32">Auto refresh</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-24">Thủ công</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Onboarding home <span class="text-xs text-ink-500">(chào mừng, link nhanh)</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB nội bộ</td>
<td class="px-3 py-3 text-ink-500">—</td>
<td class="px-3 py-3 text-ink-500">—</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- 📊 DASHBOARD -->
<section id="sb-dashboard" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">📊</span> Dashboard
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-x-auto not-prose">
<table class="w-full text-sm min-w-[700px]">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-44">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn data</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Auto refresh</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-44">Thủ công</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Dashboard VIA</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB <span class="text-ink-500">(status VIA, cookie / token status)</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Extension (alarm <span class="font-mono">15p</span>) cập nhật cookie / EAAG / EAAB</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Đồng bộ" trên từng VIA</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Dashboard BM</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB <span class="text-ink-500">(info, verification, status)</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#12</strong> (BM gắn sao) <span class="font-mono">12h</span> • Extension cho BM thường (alarm <code class="font-mono text-[10px] bg-ink-100 dark:bg-ink-800 px-1 rounded">CHECK_BM</code>)</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Đồng bộ" từng BM</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Dashboard ADS</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB <span class="text-ink-500">(TKQC: status, balance, spend, threshold)</span></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#04</strong> status <span class="font-mono">1h</span> • Bot <strong>#10</strong> spend <span class="font-mono">6h</span> • Bot <strong>#08</strong> heat <span class="font-mono">3h</span> • Extension (<code class="font-mono text-[10px] bg-ink-100 dark:bg-ink-800 px-1 rounded">SYNC_ADS_DETAIL</code>) 30–60p</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Đồng bộ" / "Check Ads"</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Dashboard Hoá đơn</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB + ClickHouse</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#05</strong> bill <span class="font-mono">1h</span> • Bot <strong>#11</strong> cảnh báo thẻ <span class="font-mono">12h</span></td>
<td class="px-3 py-3 text-ink-500 text-xs">— (data từ bot)</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- 📦 ASSET -->
<section id="sb-asset" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">📦</span> Tài sản
</h3>
<div class="space-y-3 not-prose">
<details open class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-950">
<summary class="px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="chev w-3 h-3 text-ink-500" fill="currentColor" viewBox="0 0 8 8"><path d="M2 1l4 3-4 3z"/></svg>
<strong>Quản lý VIA</strong>
</div>
<span class="text-xs text-ink-500">DB · Extension · Đồng bộ thủ công</span>
</summary>
<div class="px-4 pb-4 text-sm grid md:grid-cols-3 gap-4 border-t border-ink-200 dark:border-ink-800 pt-4">
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Nguồn data</div>
<div class="text-ink-700 dark:text-ink-300">DB <span class="text-xs text-ink-500">(danh sách VIA, cookie / token status, proxy)</span></div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Auto refresh</div>
<div class="text-ink-700 dark:text-ink-300">Extension đẩy cookie / EAAG / EAAB khi user import / refresh</div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-emerald-600 dark:text-emerald-400 font-semibold mb-1">Thủ công</div>
<div class="text-ink-700 dark:text-ink-300">✅ "Đồng bộ" 1 VIA → OAuth → fallback EAAG → EAAB. Chặn nếu sync < 15p trước.</div>
</div>
</div>
</details>
<details open class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-950">
<summary class="px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="chev w-3 h-3 text-ink-500" fill="currentColor" viewBox="0 0 8 8"><path d="M2 1l4 3-4 3z"/></svg>
<strong>Quản lý BM</strong>
</div>
<span class="text-xs text-ink-500">Bot #12 · Extension · Rate-limit 30s</span>
</summary>
<div class="px-4 pb-4 text-sm grid md:grid-cols-3 gap-4 border-t border-ink-200 dark:border-ink-800 pt-4">
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Nguồn data</div>
<div class="text-ink-700 dark:text-ink-300">DB <span class="text-xs text-ink-500">(BM info, verification, ad accounts liên kết)</span></div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Auto refresh</div>
<div class="text-ink-700 dark:text-ink-300">Bot <strong>#12</strong> cho BM <strong>gắn sao</strong> (<span class="font-mono">12h</span>) • Extension cho BM thường (alarm <code class="font-mono text-[10px] bg-ink-100 dark:bg-ink-800 px-1 rounded">CHECK_BM</code>)</div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-emerald-600 dark:text-emerald-400 font-semibold mb-1">Thủ công</div>
<div class="text-ink-700 dark:text-ink-300">✅ "Đồng bộ" 1 BM (token hệ thống BM → OAuth → EAAB → EAAG). Rate-limit 30s.</div>
</div>
</div>
</details>
<details open class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-950">
<summary class="px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="chev w-3 h-3 text-ink-500" fill="currentColor" viewBox="0 0 8 8"><path d="M2 1l4 3-4 3z"/></svg>
<strong>Quản lý ADS</strong> <span class="text-xs text-ink-500">(TKQC)</span>
</div>
<span class="text-xs text-ink-500">5 bot + Extension</span>
</summary>
<div class="px-4 pb-4 text-sm grid md:grid-cols-3 gap-4 border-t border-ink-200 dark:border-ink-800 pt-4">
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Nguồn data</div>
<div class="text-ink-700 dark:text-ink-300">DB <span class="text-xs text-ink-500">(TKQC info, status, spend, limit, bill)</span></div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Auto refresh</div>
<div class="text-ink-700 dark:text-ink-300 text-xs leading-relaxed">
Bot <strong>#04</strong> status <span class="font-mono">1h</span> • Bot <strong>#10</strong> spend <span class="font-mono">6h</span> • Bot <strong>#05</strong> bill <span class="font-mono">1h</span> • Bot <strong>#07</strong> activity <span class="font-mono">3h</span> • Bot <strong>#08</strong> heat <span class="font-mono">3h</span> • Extension <code class="font-mono text-[10px] bg-ink-100 dark:bg-ink-800 px-1 rounded">SYNC_ADS_DETAIL</code> 30–60p
</div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-emerald-600 dark:text-emerald-400 font-semibold mb-1">Thủ công</div>
<div class="text-ink-700 dark:text-ink-300 text-xs leading-relaxed">✅ "Đồng bộ", "Check basic / advanced", "Check bill" (EAAG / EAAB bắt buộc), "Sync linked BMs"</div>
</div>
</div>
</details>
<details open class="rounded-xl border border-ink-200 dark:border-ink-800 bg-white dark:bg-ink-950">
<summary class="px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="chev w-3 h-3 text-ink-500" fill="currentColor" viewBox="0 0 8 8"><path d="M2 1l4 3-4 3z"/></svg>
<strong>Quản lý Campaign</strong>
</div>
<span class="text-xs text-ink-500">Bot #09 + Bot #10</span>
</summary>
<div class="px-4 pb-4 text-sm grid md:grid-cols-3 gap-4 border-t border-ink-200 dark:border-ink-800 pt-4">
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Nguồn data</div>
<div class="text-ink-700 dark:text-ink-300 text-xs">DB Postgres <span class="text-ink-500">(campaign / adset / ad info)</span> + ClickHouse <span class="text-ink-500">(insights, spend daily)</span></div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-1">Auto refresh</div>
<div class="text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#09</strong> sync campaign <span class="font-mono">~3h</span> (sau bot #07) • Bot <strong>#10</strong> spend <span class="font-mono">6h</span></div>
</div>
<div>
<div class="text-[10px] uppercase tracking-wider text-emerald-600 dark:text-emerald-400 font-semibold mb-1">Thủ công</div>
<div class="text-ink-700 dark:text-ink-300 text-xs">✅ "Đồng bộ" (trong flow sync VIA) • Bulk create / pause / rename / toggle</div>
</div>
</div>
</details>
</div>
</section>
<!-- 💰 FINANCE -->
<section id="sb-finance" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">💰</span> Tài chính
</h3>
<div class="rounded-lg border-l-4 border-amber-500 bg-amber-50 dark:bg-amber-950/20 p-4 my-4 not-prose">
<div class="flex gap-3">
<svg class="w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/></svg>
<div class="text-sm text-amber-900 dark:text-amber-200"><strong>Warning:</strong> Bill và thẻ BM <strong>cứng credential</strong>. Bill TKQC PHẢI cookie VIA + token user. Thẻ BM (Billing Hub) PHẢI cookie + dtsg.</div>
</div>
</div>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-x-auto not-prose">
<table class="w-full text-sm min-w-[700px]">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-40">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn data</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Auto refresh</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Thủ công</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Quản lý thẻ</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB (thẻ FB của BM + thẻ tự nhập + map giữa 2 loại)</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs"><strong>Thẻ FB:</strong> extension đẩy khi user mở Billing Hub • <strong>Cảnh báo hết hạn:</strong> Bot <strong>#11</strong> (<span class="font-mono">12h</span>)</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Đồng bộ thẻ BM" (cookie + dtsg bắt buộc) • CRUD thẻ thủ công • "+ Add" map thẻ tay với thẻ FB</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Hoá đơn</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB (bill từ FB Billing) + ClickHouse activity</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#05</strong> (<span class="font-mono">1h</span>) — cookie VIA gọi GraphQL BillingHub</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Check bill" 1 TKQC (EAAG / EAAB bắt buộc)</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Đối soát chi tiêu</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB + ClickHouse aggregate</td>
<td class="px-3 py-3 text-ink-500 text-xs">— (đọc data có sẵn)</td>
<td class="px-3 py-3 text-ink-500 text-xs">— (chỉ filter / xem)</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- 🔗 CONNECT -->
<section id="sb-connect" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">🔗</span> Kết nối
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-x-auto not-prose">
<table class="w-full text-sm min-w-[700px]">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-44">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn data</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Auto refresh</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Thủ công</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Cài đặt Extension</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">extension_releases</code></td>
<td class="px-3 py-3 text-ink-500">—</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Tải về / Update khi có version mới (chấm đỏ nhắc)</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Proxy</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB</td>
<td class="px-3 py-3 text-rose-700 dark:text-rose-400 text-xs">— <strong>KHÔNG</strong> có bot auto-check</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ "Check" proxy sống / chết (gọi <code class="font-mono text-[11px]">ifconfig.io</code> + <code class="font-mono text-[11px]">facebook.com</code> qua proxy)</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Mail đã lưu</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">ClickHouse <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">mails</code> (IMAP đẩy qua extension)</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Extension đẩy khi user cần lấy code</td>
<td class="px-3 py-3 text-ink-500 text-xs">— (chỉ xem / filter)</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- 🆘 SUPPORT -->
<section id="sb-support" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">🆘</span> Hỗ trợ
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-x-auto not-prose">
<table class="w-full text-sm min-w-[700px]">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-40">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn data</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Auto refresh</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Thủ công</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Chat hỗ trợ</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bridge admin (server-to-server)</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Poll <strong>5 giây</strong> khi mở chat / <strong>25 giây</strong> khi đóng</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ Gửi tin</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Báo lỗi của bạn</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Hub admin (<code class="font-mono text-[11px]">admin.nolimitadsmanager.com</code>)</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Polling chi tiết bug <strong>15 giây</strong> • Webhook admin → Khach khi admin tạo ticket</td>
<td class="px-3 py-3 text-emerald-700 dark:text-emerald-400 text-xs">✅ Gửi báo lỗi mới • Comment trao đổi</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- 🔔 BELL -->
<section id="sb-bell" class="mb-12">
<h3 class="text-xl font-bold tracking-tight mb-4 flex items-center gap-2">
<span class="text-2xl">🔔</span> Bell thông báo <span class="text-sm text-ink-500 font-normal">(góc phải header)</span>
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-1/3">Loại</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-32">Mỗi</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr>
<td class="px-3 py-3 font-medium">Bell notification</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#01</strong> quét <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 rounded">notification_queue</code> (5s) + Supabase Realtime</td>
<td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-950/40 text-rose-700 dark:text-rose-300">~5 s</span></td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Welcome / Version / API key hết hạn</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Side-effect khi FE fetch bell</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Khi user mở dashboard</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Push FCM mobile</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Postgres trigger <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 rounded">pg_net</code></td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Event-driven</td>
</tr>
<tr>
<td class="px-3 py-3 font-medium">Telegram</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Bot <strong>#01</strong> (hoặc trigger <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 rounded">pg_net</code>)</td>
<td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Event-driven</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- ADMIN -->
<section id="admin" class="mb-12">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§8</span>
Chức năng admin <span class="text-base text-ink-500 font-normal">(sidebar khác — chỉ admin thấy)</span>
</h2>
<h3 class="text-base font-semibold mb-3 flex items-center gap-2">
<span class="text-xl">🛡</span> Tổng quan / Hệ thống / Audit / Risk / Quản lý
</h3>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-1/3">Trang</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-40">Mỗi</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr><td class="px-3 py-3 font-medium">Chrome remote / Servers</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB + WebSocket</td><td class="px-3 py-3"><span class="freq-pill px-2 py-0.5 rounded bg-emerald-50 dark:bg-emerald-950/40 text-emerald-700 dark:text-emerald-300">Real-time</span></td></tr>
<tr><td class="px-3 py-3 font-medium">Mail Service</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">ClickHouse <code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 rounded">mails</code> + cấu hình IMAP</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">Login Events</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">Audit log / Asset logs</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB + ClickHouse</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang (rate-limit 30s)</td></tr>
<tr><td class="px-3 py-3 font-medium">Changelog</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300"><code class="font-mono text-xs bg-ink-100 dark:bg-ink-800 px-1 py-0.5 rounded">lib/changelog.ts</code></td><td class="px-3 py-3 text-ink-500">—</td></tr>
<tr><td class="px-3 py-3 font-medium">Risk <span class="text-xs text-ink-500">(13 báo cáo)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">DB + ClickHouse</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">Members</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">Notifications <span class="text-xs text-ink-500">(CRUD channel, telegram config)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">API Keys</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
<tr><td class="px-3 py-3 font-medium">Settings workspace</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-500 text-xs">Mở trang</td></tr>
</tbody>
</table>
</div>
<div class="mt-4 rounded-lg border border-ink-200 dark:border-ink-800 bg-ink-50 dark:bg-ink-900/50 p-4 text-sm not-prose">
<div class="text-[10px] uppercase tracking-wider text-ink-500 font-semibold mb-2">Risk — 13 báo cáo:</div>
<div class="flex flex-wrap gap-1.5 text-xs">
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">protect rules</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">clipboard radar</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">staff monitor</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">client BM</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">no backup</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">VIA hotmail</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">disabled limit</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">starred in dead BM</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700">funded bills on starred</span>
<span class="px-2 py-0.5 rounded bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700 text-ink-500">+ 4 báo cáo khác</span>
</div>
</div>
</section>
<!-- MISC -->
<section id="misc" class="mb-12">
<h2 class="text-2xl font-bold tracking-tight mb-4 flex items-center gap-3">
<span class="text-brand-500 font-mono text-sm">§9</span>
Khác <span class="text-base text-ink-500 font-normal">(không nằm trong sidebar)</span>
</h2>
<div class="rounded-xl border border-ink-200 dark:border-ink-800 overflow-hidden not-prose">
<table class="w-full text-sm">
<thead class="bg-ink-100 dark:bg-ink-900 text-left text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Chức năng</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400">Nguồn</th>
<th class="px-3 py-2.5 text-ink-600 dark:text-ink-400 w-44">Mỗi</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200 dark:divide-ink-800 bg-white dark:bg-ink-950">
<tr><td class="px-3 py-3 font-medium">2FA TOTP <span class="text-xs text-ink-500">(lấy mã trên popup VIA)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">Decrypt secret VIA từ DB</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Khi user click</td></tr>
<tr><td class="px-3 py-3 font-medium">Mail recovery code <span class="text-xs text-ink-500">(extension popup VIA)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">IMAP server (qua extension)</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Khi user cần</td></tr>
<tr><td class="px-3 py-3 font-medium">Get password FB <span class="text-xs text-ink-500">(popup VIA)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">Decrypt từ DB</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Khi user click</td></tr>
<tr><td class="px-3 py-3 font-medium">Trash management</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Thủ công <span class="text-rose-700 dark:text-rose-400 font-medium">(KHÔNG auto-purge)</span></td></tr>
<tr><td class="px-3 py-3 font-medium">Transfer ownership workspace</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">Email + DB</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Thủ công</td></tr>
<tr><td class="px-3 py-3 font-medium">VIA transfer requests</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">DB</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs">Thủ công</td></tr>
<tr><td class="px-3 py-3 font-medium">Topup share / gỡ TKQC tự động</td><td class="px-3 py-3 text-ink-700 dark:text-ink-300">Bot <strong>#02</strong> + Bot <strong>#03</strong> <span class="text-xs text-ink-500">(cần admin bật riêng)</span></td><td class="px-3 py-3 text-ink-700 dark:text-ink-300 text-xs"><span class="font-mono">10s</span> / <span class="font-mono">30s</span></td></tr>
</tbody>
</table>
</div>
</section>
<!-- FOOTER -->
<footer class="mt-20 pt-8 border-t border-ink-200 dark:border-ink-800">
<div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-4 text-xs text-ink-500">
<div>
<div class="font-semibold text-ink-700 dark:text-ink-300">Nolimit Ads Manager — Data Sources Documentation</div>
<div class="mt-1">Cập nhật: <span class="font-mono">2026-06-18</span> · Tài liệu nội bộ</div>
</div>
<div class="flex gap-3">
<a href="#overview" class="px-2.5 py-1 rounded-md border border-ink-200 dark:border-ink-800 hover:bg-ink-100 dark:hover:bg-ink-900 transition-colors">↑ Về đầu trang</a>
</div>
</div>
</footer>
</article>
</main>
<!-- RIGHT TOC -->
<aside class="hidden xl:block col-span-3 sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-10 pl-4">
<div class="text-[10px] uppercase tracking-wider text-ink-400 font-semibold mb-3">Trong trang này</div>
<nav id="rightToc" class="text-[12px] space-y-0.5"></nav>
<div class="mt-10 p-4 rounded-xl bg-gradient-to-br from-brand-50 to-white dark:from-brand-900/30 dark:to-ink-900 border border-brand-200 dark:border-brand-700">
<div class="text-[10px] uppercase tracking-wider text-brand-700 dark:text-brand-100 font-semibold mb-2">Quick fact</div>
<div class="text-xs text-ink-700 dark:text-ink-300 leading-relaxed">
Mỗi <strong>3 giờ</strong>, Bot <strong>#07</strong> kích hoạt chuỗi: activity log → bill (#05) → sync campaign (#09) → heat-score (#08).
</div>
</div>
</aside>
</div>
<script>
// Theme toggle
const themeToggle = document.getElementById('themeToggle');
const root = document.documentElement;
const storedTheme = localStorage.getItem('theme');
if (storedTheme === 'dark' || (!storedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
root.classList.add('dark');
}
themeToggle.addEventListener('click', () => {
root.classList.toggle('dark');
localStorage.setItem('theme', root.classList.contains('dark') ? 'dark' : 'light');
});
// Build right TOC from h2/h3 inside main
const tocContainer = document.getElementById('rightToc');
const headings = document.querySelectorAll('main h2[id], main h3[id]');
headings.forEach(h => {
const a = document.createElement('a');
a.href = '#' + h.id;
const isH3 = h.tagName === 'H3';
a.className = 'toc-link block px-3 py-1 text-ink-600 dark:text-ink-400 hover:text-brand-600 dark:hover:text-brand-100' + (isH3 ? ' pl-6 text-[11px]' : '');
a.textContent = h.textContent.replace(/§\d+/g, '').trim().slice(0, 50);
a.dataset.target = h.id;
tocContainer.appendChild(a);
});
// Scroll-spy
const tocLinks = document.querySelectorAll('#rightToc .toc-link');
const navLinks = document.querySelectorAll('#leftNav .nav-link');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.id;
tocLinks.forEach(l => l.classList.toggle('active', l.dataset.target === id));
navLinks.forEach(l => l.classList.toggle('active', l.getAttribute('href') === '#' + id));
}
});
}, { rootMargin: '-80px 0px -70% 0px', threshold: 0 });
headings.forEach(h => observer.observe(h));
// Search filter (highlight matching sections)
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('input', (e) => {
const q = e.target.value.toLowerCase().trim();
document.querySelectorAll('main section').forEach(s => {
if (!q) { s.style.display = ''; return; }
s.style.display = s.textContent.toLowerCase().includes(q) ? '' : 'none';
});
});
document.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
searchInput.focus();
}
});
</script>
</body>
</html>
Số dòng: 1131