Diff -- /var/www/vhosts/3dshawn.com/site1/TEMPLATES/dashboard.html

O Operator
Diff

/var/www/vhosts/3dshawn.com/site1/TEMPLATES/dashboard.html

modified on local at 2026-07-12 00:35:27

Added
+50
lines
Removed
-7
lines
Context
264
unchanged
Blobs
from a0ec3199a428
to a96f3bacde65
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
11<div class="page-head">
22 <span class="page-eyebrow"><span class="dot"></span> Overview</span>
33 <h1 class="page-title">Dashboard</h1>
44 <p class="page-subtitle">Portfolio-wide health at a glance. Every file change, every schema change, every drifted container -- captured silently, restorable to any moment, no workflow discipline required.</p>
5</div>
6
7<div class="ds-guide">
8 <div class="dsg-icon">i</div>
9 <div>
10 <span class="dsg-title">New here?</span>
11 This is your control tower. Every module below is a live view of what DriftSense has captured. Hover any <span class="ds-help" data-help-title="You just hovered a help chip!" data-help-body="These chips are scattered across DriftSense to explain what you're looking at. Hover, focus with keyboard, or click through to related docs. If you get lost anywhere, look for the <strong>?</strong>."></span> chip for a plain-English explanation. Start with <a href="/file_changes.cgi">File changes</a> to see recent activity, or hit <a href="/pin_hotspots.cgi">Pin hotspots</a> to freeze the most-edited files.
12 </div>
513</div>
614
715<!-- KPI row -->
816<div class="dash-grid">
917 <div class="module glow-teal">
1018 <div class="module-head"><div class="left">
1119 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg></div>
12 <div class="module-title">File changes</div>
20 <div class="module-title">File changes<span class="ds-help" data-help-title="File changes captured" data-help-body="Total <strong>file additions, modifications, and deletions</strong> DriftSense saw in the last 24 hours across every configured File Monitor. Each capture is content-addressed by SHA-256 and gzipped in <code>BLOB_STORE</code>, so 100 versions of the same file cost one copy plus a refcount." data-help-link="/file_changes.cgi" data-help-link-label="Open file changes"></span></div>
1321 <span class="module-subtitle">Captured in the last 24 hours across every monitored path on every server.</span>
1422 </div></div>
1523 <div class="module-body kpi kpi-teal">
1624 <div class="num">$kpi_file_today</div>
1725 <div class="lbl">Last 24h</div>
1826 <div class="sub">All watched paths + containers</div>
1927 </div>
2028 </div>
2129
2230 <div class="module glow-amber">
2331 <div class="module-head"><div class="left">
2432 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v6c0 1.7 4 3 9 3s9-1.3 9-3V5"/><path d="M3 11v6c0 1.7 4 3 9 3s9-1.3 9-3v-6"/></svg></div>
25 <div class="module-title">Schema changes</div>
33 <div class="module-title">Schema changes<span class="ds-help" data-help-title="Schema DDL captured" data-help-body="Every <code>CREATE TABLE</code> / <code>ALTER TABLE</code> / <code>DROP</code> across your monitored MariaDB / MySQL databases in the last 7 days. The scanner uses <code>information_schema.TABLES.UPDATE_TIME</code> for a cheap early-exit -- unchanged tables aren't re-snapshotted." data-help-link="/schema_changes.cgi" data-help-link-label="Open schema changes"></span></div>
2634 <span class="module-subtitle">DDL diffs across every monitored DB in the last 7 days -- caught even if no one committed them.</span>
2735 </div></div>
2836 <div class="module-body kpi kpi-amber">
2937 <div class="num">$kpi_schema_7d</div>
3038 <div class="lbl">Last 7 days</div>
3139 <div class="sub">Across all monitored databases</div>
3240 </div>
3341 </div>
3442
3543 <div class="module glow-emerald">
3644 <div class="module-head"><div class="left">
3745 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 13V7a2 2 0 0 0-2-2h-4l-2-3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h5"/><path d="M14 19l2 2 4-4"/></svg></div>
38 <div class="module-title">Named releases</div>
46 <div class="module-title">Named releases<span class="ds-help" data-help-title="Named releases" data-help-body="Retroactive bookmarks that pin captured content forever. A release can be <strong>portfolio-wide</strong> (protect everything captured up to that moment) or <strong>scoped</strong> to a single site. Explicit pins (via <a href='/pin_hotspots.cgi'>Pin hotspots</a>) protect specific blobs regardless of scope. Auto-purge always respects pins." data-help-link="/named_releases.cgi" data-help-link-label="Open releases"></span></div>
3947 <span class="module-subtitle">Bookmark moments you've saved. Auto-purge respects these -- their blobs stay forever.</span>
4048 </div></div>
4149 <div class="module-body kpi kpi-emerald">
4250 <div class="num">$kpi_releases</div>
4351 <div class="lbl">Bookmarked</div>
4452 <div class="sub">Point-in-time restore anchors</div>
4553 </div>
4654 </div>
4755
4856 <div class="module glow-rose">
4957 <div class="module-head"><div class="left">
5058 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
51 <div class="module-title">Drift alerts</div>
59 <div class="module-title">Drift alerts<span class="ds-help" data-help-title="Container drift alerts" data-help-body="Containers you told DriftSense should be <strong>immutable</strong> (never change at runtime) but which had files change inside them. Any non-zero count here is a compliance signal worth investigating. Coming in the container-awareness release (host-side OverlayFS reader)."></span></div>
5260 <span class="module-subtitle">Containers that were supposed to stay immutable but got modified at runtime. Compliance signal.</span>
5361 </div></div>
5462 <div class="module-body kpi kpi-rose">
5563 <div class="num">$kpi_drifted</div>
5664 <div class="lbl">Active drift</div>
5765 <div class="sub">On supposedly-immutable containers</div>
5866 </div>
5967 </div>
6068</div>
6169
6270<!-- 90-day activity timeline -->
6371<div class="module glow-teal" style="margin-bottom:20px">
6472 <div class="module-head"><div class="left">
6573 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3v18h18"/><rect x="6" y="12" width="3" height="6"/><rect x="11" y="7" width="3" height="11"/><rect x="16" y="10" width="3" height="8"/></svg></div>
6674 <div class="module-title">Activity, last 90 days</div>
6775 <span class="module-subtitle">Every captured change, stacked by kind. Teal is files, amber is schema DDL. Hover for exact daily counts.</span>
6876 </div></div>
6977 <div class="module-body" style="padding-top:10px">
7078 $timeline_svg
7179 </div>
7280</div>
7381
7482<!-- ============================ Per-site health ============================ -->
7583[if:$has_per_site]
7684<div class="module glow-emerald" style="margin-bottom:20px">
7785 <div class="module-head"><div class="left">
7886 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg></div>
79 <div class="module-title">Per-site health</div>
87 <div class="module-title">Per-site health<span class="ds-help" data-help-title="Per-site health" data-help-body="One row per active <code>FILE_MONITOR_SETTINGS</code> row. <strong>Active files</strong> = distinct filenames that haven't been marked deleted. <strong>Captures</strong> = total change rows ever recorded. <strong>Last 24h</strong> = the noisy signal you probably care about. Click a row to filter <code>/file_changes.cgi</code> to just that site."></span></div>
8088 <span class="module-subtitle">One row per active monitor. Sparkline is the last 30 days of change activity. Click a row to drill into that site's file changes.</span>
8189 </div></div>
8290 <div class="module-body tight">
8391 <table class="tbl">
8492 <thead><tr>
8593 <th style="width:36%">Site / scan</th>
8694 <th style="width:120px">30-day rhythm</th>
8795 <th style="width:100px" class="mono">Active files</th>
8896 <th style="width:100px" class="mono">Captures</th>
8997 <th style="width:100px" class="mono">Last 24h</th>
9098 <th style="width:170px">Last change</th>
9199 </tr></thead>
92100 <tbody>
93101 [loop:@per_site]
94102 <tr>
95103 <td>
96104 <a href="$drilldown_url" style="color:var(--accent-hi);text-decoration:none">
97105 <strong>$scan_name</strong>
98106 </a>
99107 <div class="mono dim" style="font-size:11px">$path_short <span class="pill $kind_pill" style="margin-left:6px;font-size:9.5px">$server_kind</span></div>
100108 </td>
101109 <td>$spark_svg</td>
102110 <td class="mono">$active_files</td>
103111 <td class="mono">$captured_ct</td>
104112 <td class="mono" style="color:var(--accent-hi)">$changes_24h</td>
105113 <td class="mono dim"><span class="ts" data-ts="$last_change_epoch" data-fmt="relative">$last_change_h</span></td>
106114 </tr>
107115 [/loop]
108116 </tbody>
109117 </table>
110118 </div>
111119</div>
112120[/if]
113121
114122<!-- ============================ Change-frequency ranking ============================ -->
115123[if:$has_top_files]
116124<div class="dash-grid" style="grid-template-columns:2fr 1fr;margin-bottom:20px">
117125 <div class="module glow-amber">
118126 <div class="module-head"><div class="left">
119127 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 17 9 11 13 15 21 7"/><polyline points="14 7 21 7 21 14"/></svg></div>
120 <div class="module-title">Change-frequency ranking</div>
128 <div class="module-title">Change-frequency ranking<span class="ds-help" data-help-title="What is the &quot;live-config heatmap&quot;?" data-help-body="Files listed here change most often over the last 30 days. In practice they're usually <strong>self-updating config files</strong> (nginx access logs mid-rotation, cache files, security-tool state files) or <strong>files being actively edited by humans</strong>. Either way, they're the files most worth pinning to a Named Release &mdash; and the ones most likely to trigger a false-alarm alert if you don't." data-help-link="/pin_hotspots.cgi" data-help-link-label="Bulk-pin them"></span></div>
121129 <span class="module-subtitle">Top 20 files by change count in the last 30 days &mdash; the "live-config heatmap". Files that show up here are likely candidates for pinning to a Named Release.</span>
122130 </div>
123131 <a href="/pin_hotspots.cgi?n=20&days=30" class="tr-chip is-active" style="border:none;margin-left:auto">Pin these &rarr;</a>
124132 </div>
125133 <div class="module-body tight" style="max-height:520px;overflow:auto">
126134 <table class="tbl">
127135 <thead><tr>
128136 <th style="width:60px">Rank</th>
129137 <th>File</th>
130138 <th style="width:120px">Site</th>
131139 <th style="width:70px">Changes</th>
132140 <th style="width:150px">Latest</th>
133141 </tr></thead>
134142 <tbody>
135143 [loop:@top_files]
136144 <tr>
137145 <td class="mono" style="color:var(--accent-warn)"><strong>#</strong></td>
138146 <td class="mono" style="font-size:11.5px"><a href="$diff_url" style="color:var(--accent-hi);text-decoration:none">$file_short</a></td>
139147 <td class="dim" style="font-size:11.5px">$scan_name</td>
140148 <td class="mono" style="color:var(--accent-warn);font-weight:700">$change_ct</td>
141149 <td class="mono dim"><span class="ts" data-ts="$latest_epoch" data-fmt="relative">$latest_h</span></td>
142150 </tr>
143151 [/loop]
144152 </tbody>
145153 </table>
146154 </div>
147155 </div>
148156
149157 <!-- ============================ Cross-site dedup ============================ -->
150158 <div class="module glow-teal">
151159 <div class="module-head"><div class="left">
152160 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg></div>
153 <div class="module-title">Cross-site dedup</div>
161 <div class="module-title">Cross-site dedup<span class="ds-help" data-help-title="Why does this matter?" data-help-body="These blobs are <strong>byte-identical across multiple sites</strong> in your portfolio. BLOB_STORE was already storing one physical copy plus a refcount, so the disk savings are automatic &mdash; but making the list visible surfaces <strong>shared code</strong> (a template.pl your team copy-pasted across sister apps) so you can consider extracting it into a real library, or spot a shared file that <em>shouldn't</em> be identical anymore." data-help-link="/sync.cgi" data-help-link-label="Cross-site sync"></span></div>
154162 <span class="module-subtitle">Byte-identical files that appear on multiple sites. BLOB_STORE already deduplicates &mdash; but seeing this list makes the shared files visible.</span>
155163 </div></div>
156164 <div class="module-body tight" style="max-height:520px;overflow:auto">
157165 [if:$has_shared_blobs]
158166 <table class="tbl">
159167 <thead><tr><th style="width:60px">Sites</th><th>Blob</th><th style="width:70px">Size</th></tr></thead>
160168 <tbody>
161169 [loop:@shared_blobs]
162170 <tr>
163171 <td class="mono"><strong style="color:var(--accent-hi)">$site_ct</strong></td>
164172 <td class="mono" style="font-size:11px">
165173 <a href="$diff_url" style="color:var(--accent-hi);text-decoration:none">$sha_short</a>
166174 <div class="dim" style="font-size:10.5px;line-height:1.4">$scans_h</div>
167175 </td>
168176 <td class="mono dim">$size_h</td>
169177 </tr>
170178 [/loop]
171179 </tbody>
172180 </table>
173181 [/if]
174182 [if:!$has_shared_blobs]
175183 <div style="padding:26px 14px;text-align:center;color:var(--text-dim);font-size:12.5px">
176184 Nothing shared across sites yet.
177185 </div>
178186 [/if]
179187 </div>
188 </div>
189</div>
190[/if]
191
192<!-- Pin drift tile (Wave 5 F1) -->
193[if:$has_drifts]
194<div class="module glow-rose" style="margin-bottom:20px">
195 <div class="module-head"><div class="left">
196 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
197 <div class="module-title">Pinned files that drifted<span class="ds-help" data-help-title="Pinned drift" data-help-body="Named releases with explicit <code>NAMED_RELEASE_PINS</code> rows are supposed to freeze content forever. When the current-latest SHA of any pinned file no longer matches the pinned SHA, it shows up here. Restore the release to bring every drifted file back to the pinned state at once."></span></div>
198 <span class="module-subtitle"><strong>$drifted_ct</strong> pinned file(s) currently differ from their pinned SHA across <strong>$releases_affected</strong> release(s). Restore or acknowledge each below.</span>
199 </div></div>
200 <div class="module-body tight">
201 <table class="tbl">
202 <thead><tr>
203 <th>File</th>
204 <th style="width:170px">Release</th>
205 <th style="width:110px">Pinned SHA</th>
206 <th style="width:110px">Current SHA</th>
207 <th style="width:150px">Detected</th>
208 <th style="width:100px"></th>
209 </tr></thead>
210 <tbody>
211 [loop:@drift_rows]
212 <tr>
213 <td class="mono" style="font-size:11.5px">$file_short</td>
214 <td class="dim">$release_name</td>
215 <td class="mono dim">$pinned_short</td>
216 <td class="mono" style="color:var(--accent-danger-hi)">$current_short</td>
217 <td class="mono dim"><span class="ts" data-ts="$detected_epoch" data-fmt="relative">$detected_h</span></td>
218 <td><a href="$restore_url" class="tr-chip" style="padding:3px 10px;font-size:11px">Fix</a></td>
219 </tr>
220 [/loop]
221 </tbody>
222 </table>
180223 </div>
181224</div>
182225[/if]
183226
184227<!-- Recent activity -->
185228<div class="module glow-teal" style="margin-bottom:20px">
186229 <div class="module-head"><div class="left">
187230 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></div>
188231 <div class="module-title">Recent activity</div>
189232 <span class="module-subtitle">Newest first. Click any row to open its full diff. File + schema changes merged into one timeline.</span>
190233 </div></div>
191234 <div class="module-body tight">
192235 [if:$has_recent]
193236 <table class="tbl">
194237 <thead><tr>
195238 <th style="width:80px">Type</th>
196239 <th>What</th>
197240 <th>Detail</th>
198241 <th style="width:170px">When</th>
199242 </tr></thead>
200243 <tbody>
201244 [loop:@recent]
202245 <tr>
203246 <td><span class="pill $kind_pill">$kind</span></td>
204247 <td class="mono" style="font-size:12.5px"><a href="$diff_url" style="color:var(--accent-hi);text-decoration:none">$what</a></td>
205248 <td class="dim" style="font-size:12.5px">$detail</td>
206249 <td class="mono dim"><span class="ts" data-ts="$ts_epoch" data-fmt="datetime">$ts</span></td>
207250 </tr>
208251 [/loop]
209252 </tbody>
210253 </table>
211254 [/if]
212255 [if:!$has_recent]
213256 <div style="padding:36px 14px;text-align:center;color:var(--text-dim);font-size:13.5px">
214257 No activity captured yet. Start a file monitor or point at a database in the <a href="[url:file_monitors]" style="color:var(--accent-hi)">config</a> to begin capture.
215258 </div>
216259 [/if]
217260 </div>
218261</div>
219262
220263<div class="dash-grid" style="grid-template-columns:2fr 1fr">
221264 <div class="module glow-emerald">
222265 <div class="module-head"><div class="left">
223266 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg></div>
224267 <div class="module-title">Named releases</div>
225268 <span class="module-subtitle">Recent bookmarks. Any file blob referenced from a named release is protected from auto-purge.</span>
226269 </div></div>
227270 <div class="module-body tight">
228271 [if:$has_releases]
229272 <table class="tbl">
230273 <thead><tr><th>Name</th><th>By</th><th style="width:130px">When</th></tr></thead>
231274 <tbody>
232275 [loop:@releases]
233276 <tr>
234277 <td><strong>$name</strong><div class="dim" style="font-size:11.5px">$description</div></td>
235278 <td class="dim">$released_by</td>
236279 <td class="mono dim"><span class="ts" data-ts="$released_epoch" data-fmt="date">$released_h</span></td>
237280 </tr>
238281 [/loop]
239282 </tbody>
240283 </table>
241284 [/if]
242285 [if:!$has_releases]
243286 <div style="padding:28px 14px;text-align:center;color:var(--text-dim);font-size:13.5px">
244287 No named releases yet. Bookmark a moment to protect it from auto-purge.
245288 </div>
246289 [/if]
247290 </div>
248291 </div>
249292
250293 <div class="module glow-sky">
251294 <div class="module-head"><div class="left">
252295 <div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/></svg></div>
253296 <div class="module-title">Servers</div>
254297 <span class="module-subtitle">Central + agent nodes.</span>
255298 </div></div>
256299 <div class="module-body tight">
257300 <table class="tbl">
258301 <thead><tr><th>Name</th><th>Status</th><th class="dim" style="width:100px">Last seen</th></tr></thead>
259302 <tbody>
260303 [loop:@servers]
261304 <tr>
262305 <td><strong>$server_name</strong> <span class="dim mono" style="font-size:11px">$role</span></td>
263306 <td><span class="pill $status_pill">$status</span></td>
264307 <td class="mono dim"><span class="ts" data-ts="$heartbeat_epoch" data-fmt="relative">$last_heartbeat_h</span></td>
265308 </tr>
266309 [/loop]
267310 </tbody>
268311 </table>
269312 </div>
270313 </div>
271314</div>