Add live HTTPS door cards and screenshots to the catalog.
Some checks are pending
offline / test (push) Waiting to run
Homepage bottom of zapier.georgelambert.org lists each public service with a description, screenshot, and link. UI-REVIEW.pdf and the walkthrough document those doors.
|
|
@ -125,3 +125,39 @@ Dashboard: API key is **masked**. **Reveal**, **Copy** (full key to clipboard),
|
|||
**https://zapier.georgelambert.org/** — system-ui on the indigo header (not Georgia).
|
||||
|
||||

|
||||
|
||||
## 13. Live HTTPS doors (NS1)
|
||||
|
||||
Public names on **NS1.GEORGELAMBERT.ORG** with Let's Encrypt. Caddy file: `packages/verae-ops/caddy/zapier-services.georgelambert.org.caddy`. NATS, keep, and archive workers stay on loopback.
|
||||
|
||||
| Door | URL |
|
||||
|------|-----|
|
||||
| Customer portal | https://portal.zapier.georgelambert.org/portal/ |
|
||||
| Customer API | https://api.zapier.georgelambert.org/ |
|
||||
| S2S leaf | https://leaf.zapier.georgelambert.org/ |
|
||||
| Zapier plane | https://zap.zapier.georgelambert.org/ |
|
||||
| Staff plane | https://staff.zapier.georgelambert.org/ |
|
||||
| Staff IAM | https://iam.zapier.georgelambert.org/ |
|
||||
| Staff session | https://login.zapier.georgelambert.org/ |
|
||||
| Customer service | https://cs.zapier.georgelambert.org/ |
|
||||
| Sales | https://sales.zapier.georgelambert.org/ |
|
||||
| Accounting | https://acct.zapier.georgelambert.org/ |
|
||||
| Middleware | https://mw.zapier.georgelambert.org/ |
|
||||
| Operator console | https://fleet.zapier.georgelambert.org/ |
|
||||
| This catalog | https://zapier.georgelambert.org/ |
|
||||
| Forgejo | https://git.georgelambert.org/ |
|
||||
|
||||
Staff HTML redirects to IAM login (`https://iam.zapier.georgelambert.org/login?next=…`).
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"description": "UI walkthrough, screenshots, and review PDF for Verae Time × Zapier",
|
||||
"scripts": {
|
||||
"walk": "node scripts/walkthrough.mjs",
|
||||
"live": "node scripts/capture-live.mjs",
|
||||
"pdf": "python3 scripts/build-review-pdf.py"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
|||
BIN
packages/ui-docs/screenshots/live/acct.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/api.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
packages/ui-docs/screenshots/live/cs.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/docs.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
packages/ui-docs/screenshots/live/fleet.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/git.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
packages/ui-docs/screenshots/live/iam.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/leaf.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
packages/ui-docs/screenshots/live/login.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/mw.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
packages/ui-docs/screenshots/live/portal.png
Normal file
|
After Width: | Height: | Size: 271 KiB |
BIN
packages/ui-docs/screenshots/live/sales.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/staff.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
packages/ui-docs/screenshots/live/zap.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -76,6 +76,34 @@ PAGES = [
|
|||
"Left as vendor Swagger. Do not treat it as the customer portal."),
|
||||
("22-catalog.png", "PDF catalog",
|
||||
"https://zapier.georgelambert.org/ uses system-ui on the indigo header, not Georgia."),
|
||||
("live/portal.png", "Live — customer portal",
|
||||
"https://portal.zapier.georgelambert.org/portal/ — public signup and sign-in. Let's Encrypt. Access-web on NS1."),
|
||||
("live/api.png", "Live — customer API",
|
||||
"https://api.zapier.georgelambert.org/health — direct customer API plane (x-api-key)."),
|
||||
("live/leaf.png", "Live — S2S leaf",
|
||||
"https://leaf.zapier.georgelambert.org/health — server-to-server leaf. No billing subjects."),
|
||||
("live/zap.png", "Live — Zapier plane",
|
||||
"https://zap.zapier.georgelambert.org/health — Zapier Platform HTTPS only. Cloud never talks to NATS."),
|
||||
("live/staff.png", "Live — staff plane",
|
||||
"https://staff.zapier.georgelambert.org/ — IAM login, then CS/sales/accounting door."),
|
||||
("live/iam.png", "Live — staff IAM",
|
||||
"https://iam.zapier.georgelambert.org/ — named users, roles, sessions. Seed admin / admin-dev-key."),
|
||||
("live/login.png", "Live — staff session",
|
||||
"https://login.zapier.georgelambert.org/ — shared staff cookie; proxies IAM."),
|
||||
("live/cs.png", "Live — customer service",
|
||||
"https://cs.zapier.georgelambert.org/ — review prepaid and credit in USD after IAM."),
|
||||
("live/sales.png", "Live — sales",
|
||||
"https://sales.zapier.georgelambert.org/ — per-customer quote after IAM."),
|
||||
("live/acct.png", "Live — accounting",
|
||||
"https://acct.zapier.georgelambert.org/ — QuickBooks IIF / CSV after IAM."),
|
||||
("live/mw.png", "Live — middleware",
|
||||
"https://mw.zapier.georgelambert.org/health — /zapier/v1, jobs, archive, MOCK_VERAE in lab."),
|
||||
("live/fleet.png", "Live — operator console",
|
||||
"https://fleet.zapier.georgelambert.org/ — Fleet / Trace / Docs. Pause/stop honored by keep."),
|
||||
("live/docs.png", "Live — documentation catalog",
|
||||
"https://zapier.georgelambert.org/ — colored PDF catalog. Live service cards at the bottom."),
|
||||
("live/git.png", "Live — Forgejo",
|
||||
"https://git.georgelambert.org/ — independent module repos, SSH port 2223."),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -126,12 +154,13 @@ def main():
|
|||
"Catalog body font is system-ui. Swagger /docs stays stock with an integrator banner only.",
|
||||
"CS and access-staff share verae-staff-ui review.html.",
|
||||
"Staff cookies accept STAFF_COOKIE_DOMAIN for a reverse-proxy host.",
|
||||
"Public HTTPS doors on *.zapier.georgelambert.org (Caddy + Let's Encrypt). Catalog homepage lists each with a screenshot.",
|
||||
]
|
||||
for it in items:
|
||||
story.append(p("• " + it, s["body"]))
|
||||
|
||||
story.append(p("How to use each surface", s["h1"]))
|
||||
story.append(p("Operator: open :3850, Fleet for replicas, Trace to inject a Zap step, Docs for PDFs. Staff: CS :3011 credit in USD; Sales :3012 quote; Accounting :3013 export; Staff plane :3025 after authz. Customers: /portal. Ops: /admin. Lab: simulator :3847.", s["body"]))
|
||||
story.append(p("Public HTTPS on NS1 (Let's Encrypt): portal.zapier.georgelambert.org/portal/ for customers; zap.zapier.georgelambert.org for Zapier; api.zapier.georgelambert.org for API keys; fleet / cs / sales / acct / staff / iam for operators after IAM login. Loopback still used for NATS, keep, archive workers, and zappier-edge :13000.", s["body"]))
|
||||
|
||||
story.append(p("Issues still to consider", s["h1"]))
|
||||
story.append(p("None. The designer-review backlog is empty.", s["body"]))
|
||||
|
|
|
|||
56
packages/ui-docs/scripts/capture-live.mjs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env node
|
||||
/** Screenshot every public HTTPS door on zapier.georgelambert.org. */
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import puppeteer from 'puppeteer-core';
|
||||
|
||||
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const SHOTS = path.join(ROOT, 'screenshots', 'live');
|
||||
const CHROME =
|
||||
process.env.CHROME_PATH ||
|
||||
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
||||
|
||||
fs.mkdirSync(SHOTS, { recursive: true });
|
||||
|
||||
const DOORS = [
|
||||
{ file: 'portal.png', url: 'https://portal.zapier.georgelambert.org/portal/' },
|
||||
{ file: 'api.png', url: 'https://api.zapier.georgelambert.org/health' },
|
||||
{ file: 'leaf.png', url: 'https://leaf.zapier.georgelambert.org/health' },
|
||||
{ file: 'zap.png', url: 'https://zap.zapier.georgelambert.org/health' },
|
||||
{ file: 'staff.png', url: 'https://staff.zapier.georgelambert.org/' },
|
||||
{ file: 'iam.png', url: 'https://iam.zapier.georgelambert.org/' },
|
||||
{ file: 'login.png', url: 'https://login.zapier.georgelambert.org/' },
|
||||
{ file: 'cs.png', url: 'https://cs.zapier.georgelambert.org/' },
|
||||
{ file: 'sales.png', url: 'https://sales.zapier.georgelambert.org/' },
|
||||
{ file: 'acct.png', url: 'https://acct.zapier.georgelambert.org/' },
|
||||
{ file: 'mw.png', url: 'https://mw.zapier.georgelambert.org/health' },
|
||||
{ file: 'fleet.png', url: 'https://fleet.zapier.georgelambert.org/' },
|
||||
{ file: 'docs.png', url: 'https://zapier.georgelambert.org/' },
|
||||
{ file: 'git.png', url: 'https://git.georgelambert.org/' },
|
||||
];
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
executablePath: CHROME,
|
||||
headless: 'new',
|
||||
args: ['--no-sandbox', '--window-size=1280,800', '--disable-dev-shm-usage'],
|
||||
defaultViewport: { width: 1280, height: 800 },
|
||||
});
|
||||
|
||||
try {
|
||||
for (const d of DOORS) {
|
||||
const page = await browser.newPage();
|
||||
try {
|
||||
await page.goto(d.url, { waitUntil: 'networkidle2', timeout: 25000 });
|
||||
} catch {
|
||||
await page.goto(d.url, { waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => {});
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
const dest = path.join(SHOTS, d.file);
|
||||
await page.screenshot({ path: dest, fullPage: false });
|
||||
process.stdout.write(`wrote ${dest}\n`);
|
||||
await page.close();
|
||||
}
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
|
|
@ -32,6 +32,11 @@
|
|||
- Disable lan-134 unless `FLEET_ENABLE_LAN134=1`.
|
||||
- SSH spawn timeout 8s; failed hosts skipped.
|
||||
|
||||
## 2026-09-11 — catalog live doors
|
||||
|
||||
- Bottom of https://zapier.georgelambert.org/ lists each HTTPS door with description, screenshot, and Open link.
|
||||
- UI-REVIEW.pdf includes the live-door atlas. Walkthrough §13.
|
||||
|
||||
## 2026-09-11 — Caddy host names live
|
||||
|
||||
- Installed `/etc/caddy/sites/zapier-services.georgelambert.org.caddy` on NS1. HTTPS: portal, api, leaf, zap, staff, iam, login, cs, sales, acct, mw, fleet.
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ def page_shell(now: str, body: str, switch_to_md: bool, title: str) -> str:
|
|||
padding:.4rem .75rem; border-radius:999px;
|
||||
}}
|
||||
.format-switch:hover {{ background:rgba(255,255,255,.28); }}
|
||||
main {{ max-width:52rem; margin:0 auto; padding:1.5rem 1.25rem 3rem; }}
|
||||
main {{ max-width:64rem; margin:0 auto; padding:1.5rem 1.25rem 3rem; }}
|
||||
h1 {{ margin:.4rem 0 .6rem; font-size:1.85rem; }}
|
||||
h2 {{ border-top:1px solid var(--line); padding-top:.8rem; margin-top:1.8rem; color:var(--accent-deep); }}
|
||||
ul {{ padding-left:1.2rem; }}
|
||||
|
|
@ -300,6 +300,14 @@ def page_shell(now: str, body: str, switch_to_md: bool, title: str) -> str:
|
|||
.card p {{ margin:0 0 .7rem; color:var(--muted); font-size:13px; }}
|
||||
.card a.act {{ display:inline-block; background:var(--accent); color:#fff; text-decoration:none;
|
||||
border-radius:8px; padding:.28rem .6rem; font:650 12px system-ui; }}
|
||||
.live {{ display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:.9rem; }}
|
||||
.live article {{ background:#fff; border:1px solid var(--line); border-radius:12px; overflow:hidden;
|
||||
box-shadow:0 1px 2px rgba(23,26,38,.05), 0 8px 24px rgba(23,26,38,.06); }}
|
||||
.live img {{ display:block; width:100%; height:140px; object-fit:cover; object-position:top; background:#eef0fe; }}
|
||||
.live .body {{ padding:.75rem .9rem 1rem; }}
|
||||
.live h3 {{ margin:0 0 .35rem; font-size:14px; }}
|
||||
.live p {{ margin:0 0 .65rem; color:var(--muted); font-size:13px; }}
|
||||
.live a.host {{ display:block; font:12px ui-monospace, Menlo, monospace; color:var(--accent); word-break:break-all; margin-bottom:.55rem; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -375,6 +383,8 @@ def main() -> None:
|
|||
"verae-staff-session",
|
||||
"verae-staff-ui",
|
||||
"verae-staff-iam",
|
||||
"verae-keep",
|
||||
"verae-bootstrap",
|
||||
):
|
||||
pkg_root = ROOT / "packages" / pkg
|
||||
if pkg in {"zapier-user-docs", "overview", "docs-master", "verae-ops"}:
|
||||
|
|
@ -401,6 +411,17 @@ def main() -> None:
|
|||
p = pkg_root / name
|
||||
if p.exists():
|
||||
copy_tree(p, SITE / "packages" / pkg / name)
|
||||
ui_docs = ROOT / "packages" / "ui-docs"
|
||||
for name in ("WALKTHROUGH.md", "REPORT.md", "UI-REVIEW.pdf"):
|
||||
p = ui_docs / name
|
||||
if p.exists():
|
||||
copy_tree(p, SITE / "packages" / "ui-docs" / name)
|
||||
copy_tree(
|
||||
ui_docs / "screenshots",
|
||||
SITE / "packages" / "ui-docs" / "screenshots",
|
||||
ignore=shutil.ignore_patterns(".DS_Store"),
|
||||
)
|
||||
|
||||
zap_app = ROOT / "packages" / "zappier" / "zapier-app" / "README.md"
|
||||
if zap_app.exists():
|
||||
copy_tree(zap_app, SITE / "packages" / "zappier" / "zapier-app" / "README.md")
|
||||
|
|
@ -547,6 +568,12 @@ def main() -> None:
|
|||
("verae-jobs-events", "jobs.events mailbox"),
|
||||
("verae-nats-accounts", "NATS leaf/internal policy"),
|
||||
("zapier-decisions", "Decisions and action log"),
|
||||
("UI-Docs", "UI walkthrough and screenshot PDF"),
|
||||
("verae-staff-session", "Staff cookie login"),
|
||||
("verae-staff-ui", "Shared staff review HTML"),
|
||||
("verae-staff-iam", "Staff users, roles, permissions"),
|
||||
("verae-keep", "Host keep-alive"),
|
||||
("verae-bootstrap", "Clone + deps per server type"),
|
||||
]
|
||||
git_lis = "".join(
|
||||
f'<li><a href="https://git.georgelambert.org/marchon/{name}">{name}</a> '
|
||||
|
|
@ -561,6 +588,7 @@ def main() -> None:
|
|||
("user-docs/README.pdf", "User guide index"),
|
||||
("packages/verae-zapier-simulator/README.pdf", "Simulator README"),
|
||||
("packages/verae-fleet/docs/CONSOLE.pdf", "Operator console"),
|
||||
("packages/ui-docs/UI-REVIEW.pdf", "UI review (screenshots + live doors)"),
|
||||
("overview/README.pdf", "System overview"),
|
||||
("overview/INDEX.pdf", "Documentation index"),
|
||||
("docs/modules-pdf/", "Module PDFs (book)"),
|
||||
|
|
@ -583,6 +611,70 @@ def main() -> None:
|
|||
("sphinx/verae-zapier-modules.pdf", "Sphinx LaTeX PDF"),
|
||||
]
|
||||
|
||||
LIVE_DOORS = [
|
||||
("portal.png", "https://portal.zapier.georgelambert.org/portal/", "Customer portal",
|
||||
"Public signup, sign-in, API key, statement, invoices. Access-web door."),
|
||||
("api.png", "https://api.zapier.georgelambert.org/health", "Customer API",
|
||||
"Direct customer API (x-api-key). Not Zapier."),
|
||||
("leaf.png", "https://leaf.zapier.georgelambert.org/health", "S2S leaf",
|
||||
"Server-to-server NATS leaf plane. No billing subjects."),
|
||||
("zap.png", "https://zap.zapier.georgelambert.org/health", "Zapier plane",
|
||||
"Only Zapier Platform HTTPS. Cloud never talks to NATS."),
|
||||
("staff.png", "https://staff.zapier.georgelambert.org/", "Staff plane",
|
||||
"CS / sales / accounting door after IAM."),
|
||||
("iam.png", "https://iam.zapier.georgelambert.org/", "Staff IAM",
|
||||
"Named staff users, roles, permissions, sessions."),
|
||||
("login.png", "https://login.zapier.georgelambert.org/health", "Staff session",
|
||||
"Shared staff cookie; proxies IAM when STAFF_IAM_URL is set."),
|
||||
("cs.png", "https://cs.zapier.georgelambert.org/", "Customer service",
|
||||
"Review prepaid balance and apply credits (USD)."),
|
||||
("sales.png", "https://sales.zapier.georgelambert.org/", "Sales",
|
||||
"Per-customer quote, tier, and multiplier."),
|
||||
("acct.png", "https://acct.zapier.georgelambert.org/", "Accounting",
|
||||
"QuickBooks IIF and accounting CSV export."),
|
||||
("mw.png", "https://mw.zapier.georgelambert.org/health", "Middleware",
|
||||
"Zapier /zapier/v1, jobs, archive, chain (MOCK_VERAE in lab)."),
|
||||
("fleet.png", "https://fleet.zapier.georgelambert.org/", "Operator console",
|
||||
"Fleet replicas, Trace, Docs. Pause/stop honored by keep."),
|
||||
("docs.png", "https://zapier.georgelambert.org/", "This catalog",
|
||||
"Colored PDF documentation site."),
|
||||
("git.png", "https://git.georgelambert.org/", "Forgejo",
|
||||
"Independent module repos (SSH 2223)."),
|
||||
]
|
||||
|
||||
def live_section() -> str:
|
||||
live_dir = ROOT / "packages" / "ui-docs" / "screenshots" / "live"
|
||||
dest = SITE / "live"
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
cards_html = []
|
||||
for fname, href, title, desc in LIVE_DOORS:
|
||||
src = live_dir / fname
|
||||
img = ""
|
||||
if src.exists():
|
||||
copy_tree(src, dest / fname)
|
||||
img = f'<img src="/live/{fname}" alt="{title}"/>'
|
||||
cards_html.append(
|
||||
f'<article>{img}<div class="body"><h3>{title}</h3>'
|
||||
f'<a class="host" href="{href}">{href}</a>'
|
||||
f"<p>{desc}</p>"
|
||||
f'<a class="act" href="{href}">Open</a></div></article>'
|
||||
)
|
||||
review = ""
|
||||
pdf = ROOT / "packages" / "ui-docs" / "UI-REVIEW.pdf"
|
||||
if pdf.exists():
|
||||
copy_tree(pdf, SITE / "packages" / "ui-docs" / "UI-REVIEW.pdf")
|
||||
review = (
|
||||
'<p>Screenshot atlas with usage notes: '
|
||||
'<a href="/packages/ui-docs/UI-REVIEW.pdf">UI-REVIEW.pdf</a>.</p>'
|
||||
)
|
||||
return (
|
||||
f'<section><h2>Live services (NS1 · HTTPS)</h2>'
|
||||
f"<p>Each name is on Let’s Encrypt via Caddy on "
|
||||
f"<strong>NS1.GEORGELAMBERT.ORG</strong>. NATS, keep, and archive workers stay on loopback.</p>"
|
||||
f"{review}"
|
||||
f'<div class="live">{"".join(cards_html)}</div></section>'
|
||||
)
|
||||
|
||||
def extra_section(items: list[tuple[str, str]]) -> str:
|
||||
lis = "".join(
|
||||
f'<li><a href="{h}">{lab}</a></li>'
|
||||
|
|
@ -615,6 +707,7 @@ def main() -> None:
|
|||
</ul>
|
||||
</section>
|
||||
{extra_section(extra_pdf)}
|
||||
{live_section()}
|
||||
"""
|
||||
rest_md = f"""
|
||||
{cards("md")}
|
||||
|
|
@ -640,6 +733,7 @@ def main() -> None:
|
|||
</ul>
|
||||
</section>
|
||||
{extra_section(extra_md)}
|
||||
{live_section()}
|
||||
"""
|
||||
|
||||
(SITE / "index.html").write_text(
|
||||
|
|
|
|||