Tighten control plane flow and status presentation
This commit is contained in:
+16
-24
@@ -24,7 +24,7 @@
|
||||
|
||||
<div class="control-state">
|
||||
<span class="status-dot"></span>
|
||||
<span>LAB CONFIGURATION / VERIFIED OCT 2026</span>
|
||||
<span>LIVE TELEMETRY / CONFIG VERIFIED OCT 2026</span>
|
||||
</div>
|
||||
|
||||
<nav aria-label="Control plane navigation">
|
||||
@@ -150,14 +150,10 @@
|
||||
|
||||
<aside class="activity-panel">
|
||||
<div class="panel-title">
|
||||
<span>OPERATIONAL CAPABILITIES</span>
|
||||
<span>PLATFORM CONTROLS</span>
|
||||
<small>DOCUMENTED</small>
|
||||
</div>
|
||||
<ol class="event-list">
|
||||
<li>
|
||||
<span class="event-ok">DEPLOY</span>
|
||||
<p>Automated deployment through Woodpecker CI</p>
|
||||
</li>
|
||||
<li>
|
||||
<span class="event-info">AUTH</span>
|
||||
<p>OIDC authentication through Authentik</p>
|
||||
@@ -166,10 +162,6 @@
|
||||
<span class="event-ok">BACKUP</span>
|
||||
<p>Persistent data backup and documented recovery procedures</p>
|
||||
</li>
|
||||
<li>
|
||||
<span class="event-warn">SEC</span>
|
||||
<p>CrowdSec threat detection and decision evidence</p>
|
||||
</li>
|
||||
<li>
|
||||
<span class="event-info">TLS</span>
|
||||
<p>Certificate and HTTPS management through the reverse proxy</p>
|
||||
@@ -248,7 +240,7 @@
|
||||
<a href="assets/images/portfolio-grafana-logs.png" target="_blank">
|
||||
<img src="assets/images/portfolio-grafana-logs.png" alt="Centralized logs snapshot in Grafana" />
|
||||
</a>
|
||||
<p class="evidence-note">CAPTURED OCT 2026 · LOGGING EVIDENCE SNAPSHOT · VALUES SHOWN ARE FROM CAPTURE TIME</p>
|
||||
<p class="evidence-note">OCT 2026 · LOGGING EVIDENCE</p>
|
||||
</figure>
|
||||
|
||||
<div class="coverage-matrix">
|
||||
@@ -282,15 +274,15 @@
|
||||
<div class="service-layout">
|
||||
<div class="service-table" role="table" aria-label="Service inventory">
|
||||
<div class="service-row service-head" role="row">
|
||||
<span>Service</span><span>Role</span><span>Access</span><span>State</span>
|
||||
<span>Service</span><span>Role</span><span>Access</span>
|
||||
</div>
|
||||
<div class="service-row"><strong>Gitea</strong><span>Source control</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Wiki.js</strong><span>Documentation</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Dashy</strong><span>Service portal</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Vaultwarden</strong><span>Secrets</span><span>DIRECT</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Stirling PDF</strong><span>Document tools</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>IT Tools</strong><span>Utilities</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Uptime Kuma</strong><span>Availability</span><span>SSO</span><i>CONFIGURED</i></div>
|
||||
<div class="service-row"><strong>Gitea</strong><span>Source control</span><span>SSO</span></div>
|
||||
<div class="service-row"><strong>Wiki.js</strong><span>Documentation</span><span>SSO</span></div>
|
||||
<div class="service-row"><strong>Dashy</strong><span>Service portal</span><span>SSO</span></div>
|
||||
<div class="service-row"><strong>Vaultwarden</strong><span>Secrets</span><span>DIRECT</span></div>
|
||||
<div class="service-row"><strong>Stirling PDF</strong><span>Document tools</span><span>SSO</span></div>
|
||||
<div class="service-row"><strong>IT Tools</strong><span>Utilities</span><span>SSO</span></div>
|
||||
<div class="service-row"><strong>Uptime Kuma</strong><span>Availability</span><span>SSO</span></div>
|
||||
</div>
|
||||
|
||||
<div class="portal-shot live-service-panel" aria-label="Live service health">
|
||||
@@ -299,7 +291,7 @@
|
||||
<small>SANITIZED ENDPOINT CHECKS</small>
|
||||
</figcaption>
|
||||
<div class="service-health-grid">
|
||||
<div><span>GITEA</span><strong id="health-gitea">CHECKING</strong><small id="gitea-version">VERSION --</small></div>
|
||||
<div><span>GITEA</span><strong id="health-gitea">CHECKING</strong><small>SOURCE CONTROL</small></div>
|
||||
<div><span>WOODPECKER</span><strong id="health-woodpecker">CHECKING</strong><small>CI / DELIVERY</small></div>
|
||||
<div><span>UPTIME KUMA</span><strong id="health-kuma">CHECKING</strong><small>AVAILABILITY</small></div>
|
||||
<div><span>PROMETHEUS</span><strong id="health-prometheus">CHECKING</strong><small>METRICS</small></div>
|
||||
@@ -336,7 +328,7 @@
|
||||
<div class="delivery-state">
|
||||
<span class="delivery-kicker">SERVICE STATE</span>
|
||||
<strong id="pipeline-gitea-state">CHECKING</strong>
|
||||
<small id="pipeline-gitea-version">VERSION --</small>
|
||||
<small>REPOSITORY HOST</small>
|
||||
</div>
|
||||
<div class="delivery-meta">
|
||||
<span>ROLE</span><strong>REPOSITORY HOST</strong>
|
||||
@@ -392,7 +384,7 @@
|
||||
<a href="assets/images/portfolio-crowdsec-decisions.png" target="_blank">
|
||||
<img src="assets/images/portfolio-crowdsec-decisions.png" alt="CrowdSec firewall decision evidence snapshot" />
|
||||
</a>
|
||||
<p class="evidence-note">CAPTURED OCT 2026 · SECURITY EVIDENCE SNAPSHOT · NOT A LIVE DECISION FEED</p>
|
||||
<p class="evidence-note">OCT 2026 · DECISION-HISTORY EVIDENCE</p>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
@@ -418,7 +410,7 @@
|
||||
<a href="assets/images/portfolio-wiki-disaster-recovery.png" target="_blank">
|
||||
<img src="assets/images/portfolio-wiki-disaster-recovery.png" alt="ByteGeist disaster recovery runbook documentation snapshot" />
|
||||
</a>
|
||||
<p class="evidence-note">CAPTURED OCT 2026 · DOCUMENTED RECOVERY PROCEDURE</p>
|
||||
<p class="evidence-note">OCT 2026 · RUNBOOK CAPTURE</p>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
@@ -429,7 +421,7 @@
|
||||
<img src="assets/images/bytegeist-logo.png" alt="" />
|
||||
<div><strong>BYTEGEIST</strong><span>KEITH CASKO / INFRASTRUCTURE LAB</span></div>
|
||||
</div>
|
||||
<p>PLAIN HTML / CSS / JAVASCRIPT</p>
|
||||
<p>HTML / CSS / JAVASCRIPT · PYTHON STATUS API · NGINX</p>
|
||||
<p>VERIFICATION: <span class="status-text">OCT 2026</span></p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
@@ -19,9 +19,7 @@ const fields = {
|
||||
healthWoodpecker: document.querySelector("#health-woodpecker"),
|
||||
healthKuma: document.querySelector("#health-kuma"),
|
||||
healthPrometheus: document.querySelector("#health-prometheus"),
|
||||
giteaVersion: document.querySelector("#gitea-version"),
|
||||
pipelineGiteaState: document.querySelector("#pipeline-gitea-state"),
|
||||
pipelineGiteaVersion: document.querySelector("#pipeline-gitea-version"),
|
||||
pipelineWoodpeckerState: document.querySelector("#pipeline-woodpecker-state"),
|
||||
deployedCommit: document.querySelector("#deployed-commit"),
|
||||
};
|
||||
@@ -31,7 +29,7 @@ const telemetryHistory = {
|
||||
memory: [],
|
||||
};
|
||||
|
||||
let lastSuccessfulUpdate = null;
|
||||
let lastSampledAt = null;
|
||||
let requestInFlight = false;
|
||||
|
||||
function updateClock() {
|
||||
@@ -80,8 +78,6 @@ function setUnavailable() {
|
||||
element.classList.add("status-down");
|
||||
}
|
||||
}
|
||||
fields.giteaVersion.textContent = "VERSION --";
|
||||
fields.pipelineGiteaVersion.textContent = "VERSION --";
|
||||
fields.deployedCommit.textContent = "-------";
|
||||
refreshElement.textContent = "TELEMETRY UNAVAILABLE";
|
||||
refreshElement.classList.add("telemetry-error");
|
||||
@@ -104,10 +100,6 @@ function pushHistory(series, value) {
|
||||
if (series.length > 24) series.shift();
|
||||
}
|
||||
|
||||
function serviceLabel(service) {
|
||||
return service && service.up ? "ONLINE" : "UNAVAILABLE";
|
||||
}
|
||||
|
||||
function setServiceState(element, service) {
|
||||
if (!element) return;
|
||||
const up = Boolean(service && service.up);
|
||||
@@ -143,11 +135,6 @@ function renderStatus(data) {
|
||||
setServiceState(fields.pipelineGiteaState, services.gitea);
|
||||
setServiceState(fields.pipelineWoodpeckerState, services.woodpecker);
|
||||
|
||||
const giteaVersion = services.gitea && services.gitea.version
|
||||
? "VERSION " + services.gitea.version
|
||||
: "VERSION --";
|
||||
fields.giteaVersion.textContent = giteaVersion;
|
||||
fields.pipelineGiteaVersion.textContent = giteaVersion;
|
||||
fields.deployedCommit.textContent = data.deployment && data.deployment.commit
|
||||
? data.deployment.commit
|
||||
: "-------";
|
||||
@@ -159,14 +146,21 @@ function renderStatus(data) {
|
||||
fields.telemetry.classList.remove("metric-error");
|
||||
refreshElement.classList.remove("telemetry-error");
|
||||
|
||||
lastSuccessfulUpdate = Date.now();
|
||||
lastSampledAt = Number(data.sampled_at) * 1000;
|
||||
updateRefreshLabel();
|
||||
}
|
||||
|
||||
function updateRefreshLabel() {
|
||||
if (!lastSuccessfulUpdate) return;
|
||||
const ageSeconds = Math.max(0, Math.floor((Date.now() - lastSuccessfulUpdate) / 1000));
|
||||
refreshElement.textContent = "LIVE TELEMETRY | UPDATED " + String(ageSeconds).padStart(2, "0") + "s AGO";
|
||||
if (!lastSampledAt) return;
|
||||
const ageSeconds = Math.max(0, Math.floor((Date.now() - lastSampledAt) / 1000));
|
||||
const stale = ageSeconds > 45;
|
||||
|
||||
refreshElement.textContent = (stale ? "TELEMETRY STALE | SAMPLE " : "LIVE TELEMETRY | SAMPLE ")
|
||||
+ String(ageSeconds).padStart(2, "0") + "s AGO";
|
||||
refreshElement.classList.toggle("telemetry-error", stale);
|
||||
|
||||
fields.telemetry.textContent = stale ? "STALE" : "LIVE";
|
||||
fields.telemetry.classList.toggle("metric-error", stale);
|
||||
}
|
||||
|
||||
async function refreshTelemetry() {
|
||||
@@ -198,4 +192,3 @@ refreshTelemetry();
|
||||
window.setInterval(updateClock, 1000);
|
||||
window.setInterval(updateRefreshLabel, 1000);
|
||||
window.setInterval(refreshTelemetry, 15000);
|
||||
|
||||
|
||||
@@ -63,11 +63,6 @@ def check_services():
|
||||
try:
|
||||
status, body = get_text(url)
|
||||
services[name] = {"up": 200 <= status < 400, "status": status}
|
||||
if name == "gitea":
|
||||
try:
|
||||
services[name]["version"] = json.loads(body).get("version")
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
services[name] = {"up": False, "status": None}
|
||||
return services
|
||||
|
||||
@@ -664,10 +664,10 @@ h1 {
|
||||
.module-header {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(260px, .75fr) auto;
|
||||
gap: 40px;
|
||||
gap: 28px;
|
||||
align-items: end;
|
||||
min-height: 132px;
|
||||
padding: 28px 30px;
|
||||
min-height: 108px;
|
||||
padding: 22px 28px;
|
||||
border-bottom: 1px solid var(--line-strong);
|
||||
}
|
||||
|
||||
@@ -679,7 +679,7 @@ h1 {
|
||||
|
||||
.module h2 {
|
||||
margin: 7px 0 0;
|
||||
font-size: clamp(1.8rem, 3vw, 3.3rem);
|
||||
font-size: clamp(1.65rem, 2.5vw, 2.7rem);
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
letter-spacing: -.05em;
|
||||
@@ -868,7 +868,7 @@ h1 {
|
||||
|
||||
.service-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.2fr .65fr .55fr;
|
||||
grid-template-columns: 1fr 1.25fr .7fr;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
min-height: 53px;
|
||||
@@ -1331,7 +1331,7 @@ footer {
|
||||
|
||||
.service-row span:nth-child(3),
|
||||
.service-head span:nth-child(3) {
|
||||
display: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.system-map {
|
||||
@@ -1376,3 +1376,57 @@ footer {
|
||||
animation-iteration-count: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Final rhythm and evidence polish */
|
||||
.module + .module {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.module + .module::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: 28px;
|
||||
width: 48px;
|
||||
height: 1px;
|
||||
background: var(--purple-low);
|
||||
}
|
||||
|
||||
.evidence-note {
|
||||
opacity: .72;
|
||||
font-size: .49rem;
|
||||
letter-spacing: .05em;
|
||||
}
|
||||
|
||||
.evidence-wide img,
|
||||
.crowdsec-shot img,
|
||||
.recovery-layout img {
|
||||
max-height: 430px;
|
||||
object-fit: contain;
|
||||
object-position: top center;
|
||||
background: #050608;
|
||||
}
|
||||
|
||||
.activity-panel .event-list li {
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.activity-panel .event-list p {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.module-header {
|
||||
min-height: auto;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.module + .module::before {
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.service-row {
|
||||
grid-template-columns: 1fr 1fr auto;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user