Default the public catalog to colored PDFs
Some checks are pending
offline / test (push) Waiting to run

Render published markdown with pandoc + WeasyPrint (indigo tables,
dark code). Home page links to PDFs with a top-right switch to
Markdown indexes. Serve CONSOLE.pdf from the operator console.
This commit is contained in:
George Lambert 2026-09-11 14:23:19 -04:00
parent cf4ef9e3af
commit 5ad3222def
9 changed files with 957 additions and 182 deletions

View file

@ -1,8 +1,8 @@
# Documentation index
Read **high-level first**, then **architecture**, then the rest. Live catalog: https://zapier.georgelambert.org/
Read **high-level first**, then **architecture**, then the rest. Live catalog (PDF by default): https://zapier.georgelambert.org/ — [Markdown indexes](https://zapier.georgelambert.org/index-md.html)
Operator console (loopback): http://127.0.0.1:3850/
Operator console (loopback): http://127.0.0.1:3850/ · [CONSOLE.pdf](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf)
## 1. High-level (non-technical)
@ -24,25 +24,25 @@ Operator console (loopback): http://127.0.0.1:3850/
| Address routing | [06-address-routing.md](06-address-routing.md) |
| External resources | [07-external-resources.md](07-external-resources.md) |
| Diagrams | [08-diagrams.md](08-diagrams.md) |
| Catalog home | https://zapier.georgelambert.org/ |
| Composition | https://zapier.georgelambert.org/docs/02-architecture/composition.html |
| NATS gateway | https://zapier.georgelambert.org/docs/02-architecture/nats-gateway.html |
| NATS subjects | https://zapier.georgelambert.org/docs/02-architecture/nats-subjects.html |
| Archive / bloom | https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html |
| Module NATS map | https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html |
| Tree nodes | https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html |
| Fleet | https://zapier.georgelambert.org/docs/02-architecture/fleet.html |
| Catalog home | https://zapier.georgelambert.org/ (PDF) · [Markdown indexes](https://zapier.georgelambert.org/index-md.html) |
| Composition | https://zapier.georgelambert.org/docs/02-architecture/composition.pdf |
| NATS gateway | https://zapier.georgelambert.org/docs/02-architecture/nats-gateway.pdf |
| NATS subjects | https://zapier.georgelambert.org/docs/02-architecture/nats-subjects.pdf |
| Archive / bloom | https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf |
| Module NATS map | https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf |
| Tree nodes | https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf |
| Fleet | https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf |
## 3. Remaining documentation
| Document | URL |
|----------|-----|
| Expansion template | [09-expansion-template.md](09-expansion-template.md) |
| Operator console | https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md |
| User guide | https://zapier.georgelambert.org/user-docs/README.md |
| Tree-node lookup (users) | https://zapier.georgelambert.org/packages/zapier-user-docs/09-lookup-tree-nodes.html |
| Zapier developer setup | https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html |
| docs-master | https://zapier.georgelambert.org/docs-master/README.md |
| Operator console | https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf |
| User guide | https://zapier.georgelambert.org/user-docs/README.pdf |
| Tree-node lookup (users) | https://zapier.georgelambert.org/packages/zapier-user-docs/09-lookup-tree-nodes.pdf |
| Zapier developer setup | https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf |
| docs-master | https://zapier.georgelambert.org/docs-master/README.pdf |
## Independent git repositories

View file

@ -3,7 +3,7 @@
High-level description of the whole system: what it is, which **independent git repositories** implement it, how it stays up, how it behaves when the local network fails, and how it talks to the **central Verae NATS.IO 3-server cluster**. New work is added by **new address routing**, not by teaching Zapier about NATS.
**This repo:** https://git.georgelambert.org/marchon/overview
**Live catalog:** https://zapier.georgelambert.org/
**Live catalog (PDF by default):** https://zapier.georgelambert.org/ · [Markdown indexes](https://zapier.georgelambert.org/index-md.html)
**Clone:** `ssh://git@git.georgelambert.org:2223/marchon/overview.git`
## Table of contents
@ -49,7 +49,7 @@ Clone any of them: `git clone ssh://git@git.georgelambert.org:2223/marchon/<name
## Operator console (loopback)
Fleet, message **Trace**, and **Docs** share one shell at http://127.0.0.1:3850/ (`verae-fleet`). Not public. See [verae-fleet CONSOLE.md](https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md).
Fleet, message **Trace**, and **Docs** share one shell at http://127.0.0.1:3850/ (`verae-fleet`). Not public. See [CONSOLE.pdf](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf).
![Fleet tab](screenshots/console-fleet.png)
@ -80,11 +80,11 @@ Start at the top. Architecture is second. Everything else is reference.
| [Address routing](06-address-routing.md) | Unplanned functions as new subjects |
| [External resources](07-external-resources.md) | Chain, WORM, tree-node search |
| [Diagrams](08-diagrams.md) | SVG + mermaid |
| [Fleet](https://zapier.georgelambert.org/docs/02-architecture/fleet.html) | Operator replica control |
| [Module NATS map](https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html) | Address table |
| [Archive / bloom](https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html) | Multipart and multi-receipt |
| [Tree nodes](https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html) | Bulk Merkle leaves |
| [Composition](https://zapier.georgelambert.org/docs/02-architecture/composition.html) | zappier + middleware HTTPS |
| [Fleet](https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf) | Operator replica control |
| [Module NATS map](https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf) | Address table |
| [Archive / bloom](https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf) | Multipart and multi-receipt |
| [Tree nodes](https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf) | Bulk Merkle leaves |
| [Composition](https://zapier.georgelambert.org/docs/02-architecture/composition.pdf) | zappier + middleware HTTPS |
### 3. Remaining documentation
@ -92,10 +92,10 @@ Start at the top. Architecture is second. Everything else is reference.
|----------|------------|
| [Documentation index](INDEX.md) | AZ and catalog URLs |
| [Expansion template](09-expansion-template.md) / [verae-nats-process](https://git.georgelambert.org/marchon/verae-nats-process) | Copy this to add an address |
| [Operator console](https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md) | Screenshots of Fleet / Trace / Docs |
| [Operator console](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf) | Screenshots of Fleet / Trace / Docs |
| [Simulator](https://git.georgelambert.org/marchon/verae-zapier-simulator) | Standalone trace (also inside the console) |
| [Zapier developer setup](https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html) | CLI / login / push |
| Live catalog | https://zapier.georgelambert.org/ |
| [Zapier developer setup](https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf) | CLI / login / push |
| Live catalog | https://zapier.georgelambert.org/ (PDF) · [Markdown indexes](https://zapier.georgelambert.org/index-md.html) |
---

View file

@ -35,7 +35,7 @@ node src/cli.js ssh-check ns1 # marchon@70.88.205.138 with ~/.ssh/id_ed25519
Private keys stay on disk (`~/.ssh/id_ed25519`); git stores only the path. Optional overrides: `machines.secrets.json` (gitignored).
Operator console (Fleet · Trace · Docs) at http://127.0.0.1:3850/ — see [docs/CONSOLE.md](docs/CONSOLE.md). Message-processing **min / avg / p50 / p90** RTT is on the Fleet tab.
Operator console (Fleet · Trace · Docs) at http://127.0.0.1:3850/ — [docs/CONSOLE.md](docs/CONSOLE.md) · [CONSOLE.pdf](docs/CONSOLE.pdf) (also https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf). Message-processing **min / avg / p50 / p90** RTT is on the Fleet tab.
Zapier cloud apps are listed but **not spawned**. NATS on NS1 is **monitored only** (loopback `:4222`, never a public bind).

View file

@ -0,0 +1,426 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Operator console</title>
<style>
/* Default styles provided by pandoc.
** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
*/
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
svg {
height: auto;
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
border: none;
border-top: 1px solid #1a1a1a;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
/* CSS for syntax highlighting */
html { -webkit-text-size-adjust: 100%; }
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
background-color: #232629;
color: #7a7c7d;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
div.sourceCode
{ color: #cfcfc2; background-color: #232629; }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span { color: #cfcfc2; } /* Normal */
code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
code span.an { color: #3f8058; } /* Annotation */
code span.at { color: #2980b9; } /* Attribute */
code span.bn { color: #f67400; } /* BaseN */
code span.bu { color: #7f8c8d; } /* BuiltIn */
code span.cf { color: #fdbc4b; font-weight: bold; } /* ControlFlow */
code span.ch { color: #3daee9; } /* Char */
code span.cn { color: #27aeae; font-weight: bold; } /* Constant */
code span.co { color: #7a7c7d; } /* Comment */
code span.cv { color: #7f8c8d; } /* CommentVar */
code span.do { color: #a43340; } /* Documentation */
code span.dt { color: #2980b9; } /* DataType */
code span.dv { color: #f67400; } /* DecVal */
code span.er { color: #da4453; text-decoration: underline; } /* Error */
code span.ex { color: #0099ff; font-weight: bold; } /* Extension */
code span.fl { color: #f67400; } /* Float */
code span.fu { color: #8e44ad; } /* Function */
code span.im { color: #27ae60; } /* Import */
code span.in { color: #c45b00; } /* Information */
code span.kw { color: #cfcfc2; font-weight: bold; } /* Keyword */
code span.op { color: #cfcfc2; } /* Operator */
code span.ot { color: #27ae60; } /* Other */
code span.pp { color: #27ae60; } /* Preprocessor */
code span.re { color: #2980b9; background-color: #153042; } /* RegionMarker */
code span.sc { color: #3daee9; } /* SpecialChar */
code span.ss { color: #da4453; } /* SpecialString */
code span.st { color: #f44f4f; } /* String */
code span.va { color: #27aeae; } /* Variable */
code span.vs { color: #da4453; } /* VerbatimString */
code span.wa { color: #da4453; } /* Warning */
</style>
<style>/* Colored print + screen stylesheet for zapier.georgelambert.org */
:root {
--ink: #171a26;
--muted: #5b6178;
--line: #d9dce8;
--bg: #f4f5fb;
--paper: #ffffff;
--accent: #4f46e5;
--accent-deep: #312e81;
--accent-soft: #eef0fe;
--ok: #047857;
--warn: #8a5a00;
--code-bg: #1b1f33;
--code-fg: #e8ecff;
}
html { background: var(--bg); }
body {
margin: 0 auto;
padding: 1.5rem 1.25rem 3rem;
max-width: 48rem;
font: 15px/1.55 -apple-system, "Segoe UI", Georgia, serif;
color: var(--ink);
background: var(--paper);
}
.doc-banner {
background: linear-gradient(160deg, #312e81 0%, #4f46e5 60%, #7c74f0 100%);
color: #eef0fe;
margin: -1.5rem -1.25rem 1.5rem;
padding: 1.1rem 1.25rem 1rem;
}
.doc-banner a { color: #fff; }
.doc-banner .kicker {
letter-spacing: 0.12em;
text-transform: uppercase;
font: 700 10px system-ui, sans-serif;
opacity: 0.8;
}
.doc-banner h1 { margin: 0.25rem 0 0; font-size: 1.45rem; color: #fff; }
h1, h2, h3, h4 { color: var(--accent-deep); page-break-after: avoid; }
h1 { font-size: 1.7rem; }
h2 {
font-size: 1.2rem;
border-bottom: 2px solid var(--accent);
padding-bottom: 0.2rem;
margin-top: 1.6rem;
}
h3 { font-size: 1.05rem; color: var(--accent); }
a { color: var(--accent); }
p, li { orphans: 3; widows: 3; }
code {
font-family: ui-monospace, Menlo, Consolas, monospace;
font-size: 0.86em;
background: var(--accent-soft);
color: var(--accent-deep);
padding: 0.08em 0.28em;
border-radius: 4px;
}
pre, div.sourceCode, div.sourceCode pre {
background: var(--code-bg) !important;
color: var(--code-fg) !important;
padding: 0.85rem 1rem;
border-radius: 10px;
overflow: auto;
font-size: 0.78rem;
line-height: 1.4;
page-break-inside: avoid;
}
pre code { background: transparent; color: inherit; padding: 0; }
#title-block-header, header#title-block-header, h1.title { display: none; }
.doc-banner + h1 { display: none; }
table {
border-collapse: collapse;
width: 100%;
margin: 0.8rem 0 1.2rem;
font-size: 0.9rem;
page-break-inside: avoid;
}
th, td { border: 1px solid var(--line); padding: 0.38rem 0.55rem; text-align: left; vertical-align: top; }
th {
background: var(--accent);
color: #fff;
font: 650 12px system-ui, sans-serif;
}
tr:nth-child(even) td { background: var(--accent-soft); }
blockquote {
margin: 1rem 0;
padding: 0.4rem 0.9rem;
border-left: 4px solid var(--accent);
background: var(--accent-soft);
color: var(--accent-deep);
}
img { max-width: 100%; height: auto; border-radius: 8px; page-break-inside: avoid; }
hr { border: 0; border-top: 1px solid var(--line); }
ul, ol { padding-left: 1.25rem; }
nav.site { font: 13px system-ui, sans-serif; margin-bottom: 0.4rem; }
.source-path { font: 11px ui-monospace, Menlo, monospace; color: var(--muted); }
@page {
size: letter;
margin: 0.65in 0.7in 0.8in 0.7in;
@top-left {
content: "Verae Time × Zapier";
font: 700 8pt system-ui, sans-serif;
color: #4f46e5;
}
@top-right {
content: "zapier.georgelambert.org";
font: 8pt system-ui, sans-serif;
color: #6b7186;
}
@bottom-center {
content: counter(page) " / " counter(pages);
font: 8pt system-ui, sans-serif;
color: #6b7186;
}
}
@media print {
html, body { background: #fff; max-width: none; padding: 0; }
.doc-banner { margin: 0 0 1rem; border-radius: 8px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
a { text-decoration: none; }
th, tr:nth-child(even) td, pre, blockquote, code { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
</style>
</head>
<body>
<div class="doc-banner"><nav class="site"><a href="/">zapier.georgelambert.org</a> · <a href="/index-md.html">Markdown indexes</a></nav><div class="kicker">Verae Time × Zapier</div><h1>Operator console</h1><div class="source-path">packages/verae-fleet/docs/CONSOLE.md</div></div>
<header id="title-block-header">
<h1 class="title">Operator console</h1>
</header>
<h1 id="operator-console">Operator console</h1>
<p>Loopback UI at <strong>http://127.0.0.1:3850/</strong> — Fleet, Trace
(simulator), and Docs in one shell. Not a public site. NATS stays
private; SSH identity files stay on disk.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> packages/verae-fleet</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">node</span> src/cli.js serve</span></code></pre></div>
<h2 id="tabs">Tabs</h2>
<table>
<colgroup>
<col style="width: 35%" />
<col style="width: 64%" />
</colgroup>
<thead>
<tr>
<th>Tab</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Fleet</strong></td>
<td>Machines (SSH/local), replica floors, green/yellow/red, RTT
min/avg/p50/p90 spark, pause/restart/off with confirm, ssh-check
toast</td>
</tr>
<tr>
<td><strong>Trace</strong></td>
<td>In-process Zapier simulator: run a step, hop log,
monitors/suggestions</td>
</tr>
<tr>
<td><strong>Docs</strong></td>
<td>Reading order: overview → module summaries → architecture →
remaining docs</td>
</tr>
</tbody>
</table>
<h2 id="screenshots">Screenshots</h2>
<figure>
<img src="screenshots/console-fleet.png" alt="Fleet" />
<figcaption aria-hidden="true">Fleet</figcaption>
</figure>
<figure>
<img src="screenshots/console-trace.png" alt="Trace" />
<figcaption aria-hidden="true">Trace</figcaption>
</figure>
<figure>
<img src="screenshots/console-docs.png" alt="Docs" />
<figcaption aria-hidden="true">Docs</figcaption>
</figure>
<p>Design tokens match the zappier portal/admin (indigo shell). Customer
portal is unchanged.</p>
<p>See <a
href="https://git.georgelambert.org/marchon/overview">overview</a>.</p>
</body>
</html>

Binary file not shown.

View file

@ -44,8 +44,8 @@
.pill.good { background:#c8efd4; color:var(--ok); }
.pill.warn { background:#ffe08a; color:var(--warn); }
.pill.bad { background:#f3c0c0; color:var(--err); }
button.act { margin:.15rem .2rem 0 0; border:1px solid var(--line); background:#fff; border-radius:8px; padding:.28rem .5rem; font:650 12px system-ui; cursor:pointer; }
button.act.primary { background:var(--accent); color:#fff; border:0; }
button.act, a.act { margin:.15rem .2rem 0 0; border:1px solid var(--line); background:#fff; border-radius:8px; padding:.28rem .5rem; font:650 12px system-ui; cursor:pointer; text-decoration:none; color:var(--ink); display:inline-block; }
button.act.primary, a.act.primary { background:var(--accent); color:#fff; border:0; }
button.act.danger { color:var(--err); }
table { width:100%; border-collapse:collapse; background:var(--panel); border-radius:var(--radius); overflow:hidden; box-shadow:var(--shadow); }
th,td { text-align:left; padding:.45rem .6rem; border-bottom:1px solid var(--line); font-size:13px; vertical-align:top; }
@ -150,33 +150,36 @@ invoice-1003</textarea>
</div>
</section>
<section id="docs" class="panel docs">
<p class="muted">Reading order: high-level first, then architecture, then the rest. Operator console is loopback only.</p>
<p class="muted">Reading order: high-level first, then architecture, then the rest. Catalog defaults to colored PDFs. Operator console is loopback only.</p>
<p><a class="act primary" href="/docs/CONSOLE.pdf" target="_blank" rel="noopener">Open CONSOLE.pdf</a>
· <a href="https://zapier.georgelambert.org/">PDF catalog</a>
· <a href="https://zapier.georgelambert.org/index-md.html">Markdown indexes</a></p>
<h2>High-level (start here)</h2>
<ul>
<li><a href="https://zapier.georgelambert.org/overview/README.md">Overview</a> — whole system in plain language</li>
<li><a href="https://zapier.georgelambert.org/overview/02-modules-and-repos.md">Modules and repositories</a> — short names of every independent repo</li>
<li><a href="https://zapier.georgelambert.org/docs-master/README.md">docs-master</a> — one-line SUMMARY + NATS for each module</li>
<li><a href="https://zapier.georgelambert.org/user-docs/README.md">User guide</a> — signup → register → lookup (non-operator)</li>
<li><a href="https://zapier.georgelambert.org/overview/README.pdf">Overview</a> — whole system in plain language</li>
<li><a href="https://zapier.georgelambert.org/overview/02-modules-and-repos.pdf">Modules and repositories</a> — short names of every independent repo</li>
<li><a href="https://zapier.georgelambert.org/docs-master/README.pdf">docs-master</a> — one-line SUMMARY + NATS for each module</li>
<li><a href="https://zapier.georgelambert.org/user-docs/README.pdf">User guide</a> — signup → register → lookup (non-operator)</li>
</ul>
<h2>Architecture</h2>
<ul>
<li><a href="https://zapier.georgelambert.org/overview/03-nats-cluster.md">NATS.IO 3-server cluster</a></li>
<li><a href="https://zapier.georgelambert.org/overview/04-uptime.md">Uptime / replica floors</a></li>
<li><a href="https://zapier.georgelambert.org/overview/05-network-failures.md">Local network failures</a></li>
<li><a href="https://zapier.georgelambert.org/overview/06-address-routing.md">Address routing</a></li>
<li><a href="https://zapier.georgelambert.org/overview/08-diagrams.md">Diagrams</a> · <a href="https://zapier.georgelambert.org/overview/diagrams/system.svg">system.svg</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/composition.html">Composition</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html">Module NATS map</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html">Archive / bloom</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html">Tree nodes</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/fleet.html">Fleet</a></li>
<li><a href="https://zapier.georgelambert.org/overview/03-nats-cluster.pdf">NATS.IO 3-server cluster</a></li>
<li><a href="https://zapier.georgelambert.org/overview/04-uptime.pdf">Uptime / replica floors</a></li>
<li><a href="https://zapier.georgelambert.org/overview/05-network-failures.pdf">Local network failures</a></li>
<li><a href="https://zapier.georgelambert.org/overview/06-address-routing.pdf">Address routing</a></li>
<li><a href="https://zapier.georgelambert.org/overview/08-diagrams.pdf">Diagrams</a> · <a href="https://zapier.georgelambert.org/overview/diagrams/system.svg">system.svg</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/composition.pdf">Composition</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf">Module NATS map</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf">Archive / bloom</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf">Tree nodes</a></li>
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf">Fleet</a></li>
</ul>
<h2>Remaining documentation</h2>
<ul>
<li><a href="https://zapier.georgelambert.org/overview/INDEX.md">Full documentation index</a></li>
<li><a href="https://zapier.georgelambert.org/overview/09-expansion-template.md">Expansion template</a> · <a href="https://git.georgelambert.org/marchon/verae-nats-process">verae-nats-process</a></li>
<li><a href="https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html">Zapier developer setup</a></li>
<li><a href="https://zapier.georgelambert.org/packages/verae-zapier-simulator/README.md">Simulator README</a></li>
<li><a href="https://zapier.georgelambert.org/overview/INDEX.pdf">Full documentation index</a></li>
<li><a href="https://zapier.georgelambert.org/overview/09-expansion-template.pdf">Expansion template</a> · <a href="https://git.georgelambert.org/marchon/verae-nats-process">verae-nats-process</a></li>
<li><a href="https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf">Zapier developer setup</a></li>
<li><a href="https://zapier.georgelambert.org/packages/verae-zapier-simulator/README.pdf">Simulator README</a></li>
<li><a href="https://git.georgelambert.org/marchon/verae-fleet">verae-fleet repo</a></li>
</ul>
</section>

View file

@ -108,11 +108,27 @@ export function startControlServer(sup, mon) {
fs.createReadStream(dest).pipe(res);
return;
}
if (req.method === 'GET' && url.pathname.startsWith('/docs/screenshots/')) {
if (req.method === 'GET' && url.pathname.startsWith('/docs/')) {
const dest = path.normalize(path.join(PUBLIC, '..', url.pathname));
const root = path.normalize(path.join(PUBLIC, '..'));
if (!dest.startsWith(root) || !fs.existsSync(dest)) return json(res, 404, { error: 'not found' });
res.writeHead(200, { 'content-type': 'image/png' });
const root = path.normalize(path.join(PUBLIC, '..', 'docs'));
if (
!(dest === root || dest.startsWith(root + path.sep)) ||
!fs.existsSync(dest) ||
!fs.statSync(dest).isFile()
) {
return json(res, 404, { error: 'not found' });
}
const ext = path.extname(dest).toLowerCase();
const types = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.svg': 'image/svg+xml',
'.pdf': 'application/pdf',
'.md': 'text/markdown; charset=utf-8',
'.html': 'text/html; charset=utf-8',
};
res.writeHead(200, { 'content-type': types[ext] || 'application/octet-stream' });
fs.createReadStream(dest).pipe(res);
return;
}