Restyle staff and console UIs; add UI-Docs walkthrough and review PDF.
Some checks are pending
offline / test (push) Waiting to run

Match CS/sales/accounting/access-staff to the portal indigo system with
dollar amounts, skip links, and empty states. Fleet replica actions move
into overflow menus, roles become chips, Docs become cards, and the
header copy reflects the 0.0.0.0 bind. Simulator uses the same shell
(orange only for faults). Portal API keys are masked; admin customers
edit in a drawer. Catalog uses system-ui. New UI-Docs repo holds
screenshots, usage notes, and UI-REVIEW.pdf.
This commit is contained in:
George Lambert 2026-09-11 18:01:33 -04:00
parent ddf772454b
commit cb07f5b321
72 changed files with 3284 additions and 242 deletions

View file

@ -28,7 +28,7 @@ Faults you can inject: edge 401/402, chain timeout, NATS watch/events drop, arch
The monitor panel flags broken assumptions (Zapier talking to NATS, file bytes on chain, bloom miss sending a reply) and suggests changes (tree-node search, wait+hook pairing, 402 upgrade URL, archive quorum).
**Catalog:** https://zapier.georgelambert.org/packages/verae-zapier-simulator/README.pdf
**Live sample UI (loopback):** http://127.0.0.1:3847/ — also inside the operator console Trace tab.
**Live sample UI:** http://0.0.0.0:3847/ — also inside the operator console Trace tab. Chrome matches the operator indigo shell; orange is fault inject only.
**Static copy:** https://zapier.georgelambert.org/simulator/
Clone: `ssh://git@git.georgelambert.org:2223/marchon/verae-zapier-simulator.git`

View file

@ -4,18 +4,21 @@
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Verae × Zapier simulator</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%234f46e5'/%3E%3C/svg%3E"/>
<style>
:root {
--ink: #12202c; --muted: #5b6d78; --line: #d5dee4; --bg: #f3efe8;
--panel: #fff; --accent: #ff4a00; --ok: #0f6e56; --err: #a32020;
--warn: #8a5a00; --silent: #6a7a86; --nats: #1d4f91;
--ink: #171a26; --muted: #6b7186; --line: #e5e7f0; --bg: #f4f5fb;
--panel: #fff; --accent: #4f46e5; --fault: #ea580c; --ok: #047857; --err: #dc2626;
--warn: #8a5a00; --silent: #6a7a86; --nats: #4f46e5;
}
* { box-sizing: border-box; }
body { margin: 0; font: 14px/1.45 system-ui, sans-serif; color: var(--ink); background: var(--bg); }
header { background: var(--ink); color: #f6f3ee; padding: .9rem 1.1rem; display: flex; gap: 1rem; align-items: baseline; flex-wrap: wrap; }
body { margin: 0; font: 14px/1.45 -apple-system,"SF Pro Text","Segoe UI",sans-serif; color: var(--ink); background: var(--bg); }
.skip { position:absolute; left:-999px; }
.skip:focus { left:1rem; top:1rem; z-index:20; background:#fff; color:var(--accent); padding:.5rem .9rem; border-radius:8px; }
header { background: linear-gradient(160deg,#312e81 0%,#4f46e5 60%,#7c74f0 100%); color: #eef0fe; padding: .9rem 1.1rem; display: flex; gap: 1rem; align-items: baseline; flex-wrap: wrap; }
header h1 { font-size: 1.05rem; margin: 0; font-weight: 650; }
header .kicker { letter-spacing: .12em; text-transform: uppercase; font: 700 10px system-ui; opacity: .7; }
header p { margin: 0; color: #c5d0d8; font-size: 13px; }
header .kicker { letter-spacing: .12em; text-transform: uppercase; font: 700 10px system-ui; opacity: .75; }
header p { margin: 0; color: #e4e7ff; font-size: 13px; }
.layout { display: grid; grid-template-columns: minmax(280px, 360px) 1fr; min-height: calc(100vh - 52px); }
@media (max-width: 900px) { .layout { grid-template-columns: 1fr; } }
aside { background: var(--panel); border-right: 1px solid var(--line); padding: 1rem; }
@ -26,14 +29,18 @@
.row { display: flex; gap: .5rem; flex-wrap: wrap; }
.checks label { display: flex; gap: .4rem; align-items: center; font-size: 13px; color: var(--ink); margin: .2rem 0; }
.checks input { width: auto; }
button { background: var(--accent); color: #fff; border: 0; border-radius: 6px; padding: .55rem .9rem; font: 650 13px system-ui; cursor: pointer; }
button.ghost { background: #e8eeef; color: var(--ink); }
button { background: var(--accent); color: #fff; border: 0; border-radius: 8px; padding: .55rem .9rem; font: 650 13px system-ui; cursor: pointer; }
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button.ghost { background: #fff; color: var(--ink); border: 1px solid var(--line); }
button.fault { background: var(--fault); }
.faults { border: 1px solid #fed7aa; background: #fff7ed; border-radius: 10px; padding: .55rem .7rem; }
.main { display: grid; grid-template-rows: auto 1fr auto; min-height: 0; }
.response, .monitors { background: var(--panel); border-bottom: 1px solid var(--line); padding: .8rem 1rem; }
.monitors { border-bottom: 0; border-top: 1px solid var(--line); max-height: 34vh; overflow: auto; }
pre { margin: 0; font: 12px/1.4 ui-monospace, Menlo, monospace; white-space: pre-wrap; }
.console { background: #0f171d; color: #d7e2ea; padding: .6rem 0; overflow: auto; min-height: 220px; }
.hop { display: grid; grid-template-columns: 52px 18px 150px 1fr; gap: .45rem; padding: .28rem .8rem; font: 12px/1.35 ui-monospace, Menlo, monospace; border-left: 3px solid transparent; }
.hop { display: grid; grid-template-columns: 4.5rem 1.2rem minmax(7rem,11rem) minmax(0,1fr); gap: .45rem; padding: .28rem .8rem; font: 12px/1.35 ui-monospace, Menlo, monospace; border-left: 3px solid transparent; }
.hop .mod, .hop .addr, .hop strong { overflow-wrap: anywhere; word-break: break-word; }
.hop:hover { background: #18232c; }
.hop.ok { border-color: var(--ok); }
.hop.error { border-color: var(--err); color: #ffb4b0; }
@ -51,14 +58,15 @@
</style>
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<header>
<div>
<div class="kicker">simulator · not live Zapier</div>
<div class="kicker">simulator · not live Zapier · binds 0.0.0.0:3847</div>
<h1>Verae Time × Zapier trace console</h1>
</div>
<p>Every hop from Zap input → zappier-edge → middleware → splitter → chain / WORM / tree nodes → Zap output. NATS addresses are in-process. Loopback only.</p>
<p>Every hop from Zap input → zappier-edge → middleware → splitter → chain / WORM / tree nodes → Zap output. NATS addresses are in-process. HTTP on all interfaces; NATS stays private.</p>
</header>
<div class="layout">
<div class="layout" id="main">
<aside>
<h2>Zapier step</h2>
<label>Action</label>
@ -78,7 +86,8 @@
<label><input type="checkbox" id="includeTree"/> includeTree (query tree nodes)</label>
</div>
<h2>Inject faults</h2>
<div class="checks">
<div class="faults checks">
<p style="color:var(--muted);font-size:12px;margin:.1rem 0 .4rem">Orange is the fault accent only.</p>
<label><input type="checkbox" id="failEdge401"/> edge 401</label>
<label><input type="checkbox" id="failEdge402"/> edge 402 quota</label>
<label><input type="checkbox" id="failChainTimeout"/> chain timeout</label>