Milestone 0: import zappier billing, Verae middleware, and Zapier research

Compose-ready workspace: packages/zappier (rate card, portal, Stripe),
packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier
(CLI app), vendor/zapier-platform, and research/zapier vendor corpus.

Gate 0 structure checks pass. Product code and research are not yet wired.
This commit is contained in:
George Lambert 2026-09-09 02:37:36 -04:00
commit b4150c8250
1364 changed files with 6814366 additions and 0 deletions

View file

@ -0,0 +1,87 @@
# CONTACTS-ALL.md — what was collected
**Source file:** [CONTACTS-ALL.md](../CONTACTS-ALL.md) (index + coverage + top 50)
**Machine copies:** [contacts-all.csv](../contacts-all.csv), [contacts-all.json](../contacts-all.json) (9,985 rows)
**Snapshot:** 17 August 2026, Zapier public catalog (API v4 + app-page scrape)
This is the **full public Zapier directory**, not the 15-vertical brief. Every row has at least **name + Zapier listing URL**.
## Why it exists
Outreach and partnership work needed a single table of every public Zapier app: who they are, how to reach them, and how large they are on Zapier. The 15-vertical subset (`CONTACTS.md`) is richer on HQ and legal name; this file is breadth.
## Coverage (9,985 apps)
| Field | Count | Share |
|-------|------:|------:|
| Apps in catalog | 9,985 | 100% |
| Website | 9,917 | 99% |
| Phone or email or sales form | 7,075 | 71% |
| Email | 4,063 | 41% |
| Phone | 3,064 | 31% |
| Sales / contact URL | 5,243 | 53% |
| Support URL | 246 | 2% |
| LinkedIn | 248 | 2% |
| HQ address | 215 | 2% |
| Legal name filled (often empty string) | — | treat HQ/legal as curated-only |
| In the 15 `Vendors.txt` verticals | 256 | 3% |
| Premium flag | 84 | 1% |
| Beta flag | 364 | 4% |
| Published Zap usage greater than 0 | 9,319 | 93% |
| Sum of published Zap usage | 4,017,170 | — |
**Contact source:** site scrape 9,729 · curated deep-research 256.
## What each row contains
`name`, `slug`, `zapier_url`, `website`, `phone`, `email`, `all_emails`, `sales_form`, `support`, `linkedin`, `hq_address`, `legal_name`, `categories`, `description`, `zap_usage`, `popularity_rank`, `is_premium`, `is_beta`, `in_vendors_txt_verticals`, `contact_source`, `scrape_error`.
Auth method is **not** on the public directory page (see `CAPABILITIES.md` / help scrape for the ~1,971 apps that state auth).
## Largest apps by published Zap usage (excerpt)
Built-in Zapier helpers dominate the top (Filter, Webhooks, Formatter, Schedule, Paths, Code, Email, Delay, AI, Looping, Tables). Largest **third-party** names include Google Sheets, Gmail, Slack, Google Calendar, Drive, HubSpot, Forms, Notion, Facebook Lead Ads, Mailchimp, Stripe, Outlook, Calendly, Typeform, Airtable, Trello, Salesforce, ChatGPT, Jotform, monday.com, Shopify.
These are **directory Zap counts**, not revenue and not unique customers.
## Top Zapier directory categories (an app can have several)
| n | Category |
|--:|----------|
| 1,089 | CRM |
| 504 | Marketing Automation |
| 350 | Forms and Surveys |
| 348 | Sales and CRM |
| 331 | eCommerce |
| 330 | Marketing |
| 314 | Phone and SMS |
| 289 | Project Management |
| 274 | AI Assistants |
| 270 | Scheduling and Booking |
| 269 | Developer Tools |
| 244 | Communication |
| 236 | Productivity |
| 230 | Accounting |
| 186 | HR Talent and Recruitment |
| 172 | Documents |
## How to use it
- **Spreadsheet work:** open `contacts-all.csv`.
- **Filter to the 15 verticals:** `in_vendors_txt_verticals` true, or use `CONTACTS.md`.
- **Outreach:** prefer `sales_form` when email/phone are blank. That is the normal SaaS path.
- **Do not** treat scrape phones as gospel (JS sites and footers produce noise). Confirm on the vendor site before calling.
## Limits
- ~952 rows recorded a scrape error; they still have catalog identity.
- Many sites are JS-only or form-only — 29% have no phone, email, or form URL.
- HQ / LinkedIn / support URLs were **not** scraped for the long tail; those fields are almost all from the 256 curated companies.
- Personal employee inboxes were omitted on purpose.
## Related
- Deeper 15-vertical directory: `CONTACTS.md`
- USP / fit / “record they create”: `VENDOR-RESEARCH.md`
- Triggers / actions / calling convention: `CAPABILITIES.md`
- Mongo: `zapier.apps` on NS1 (same catalog)

View file

@ -0,0 +1,87 @@
# CONTACTS.md — what was collected
**Source file:** [CONTACTS.md](../CONTACTS.md) (AZ table + 15 vertical sections)
**Machine copies:** [contacts.csv](../contacts.csv), [contacts.json](../contacts.json) (256 brands)
**Snapshot:** 17 August 2026
**Parent brief:** `Vendors.txt` (15 verticals) → live Zapier catalog filter
This is the **deeper 15-vertical subset**, not the 9,985-app dump. Contacts come from official about / legal / contact pages. Personal employee inboxes were omitted. `—` means not published first-party.
## Why it exists
`Vendors.txt` named verticals and counts, not companies. The catalog was matched to products that create contemporaneous records (signatures, inspections, claims, filings, recordings, certificates). Result: **270 placements / 256 unique** brands (some products sit in more than one vertical in the research narrative; the contact JSON is 256 unique slugs).
## Coverage (256 unique brands)
| Field | Count | Share |
|-------|------:|------:|
| Brand / website | 256 | 100% |
| Sales / demo / contact URL | 252 | 98% |
| LinkedIn | 248 | 97% |
| Support URL | 246 | 96% |
| HQ address | 215 | 84% |
| Legal / company name | 204 | 80% |
| Email | 164 | 64% |
| Phone | 147 | 57% |
Unique legal entities with a published name: **193**. Several parents own more than one Zapier-listed product.
## Shared parents (switchboard once)
| Brands | Legal / parent |
|-------:|----------------|
| 3 | 8am, LLC (CasePeer, DocketWise, MyCase) |
| 3 | Filevine, Inc. (Filevine, VineSign, …) |
| 3 | Zoho Corporation |
| 2 | Paperform Pty Ltd |
| 2 | Workday, Inc. |
| 2 | Canvas Solutions, Inc. (Device Magic / GoCanvas family) |
| 2 | Intellistack, LLC |
| 2 | SurveyMonkey Inc. |
Also called out in the directory: Vertafore, Applied, Nemetschek/GoCanvas, SafetyCulture, OneTrust, Smarsh, Pearson/Credly.
## How the file is organized
1. **How to use** — OEM starts at Sales / demo, then `sales@` / `partnerships@` if listed.
2. **All vendors AZ** — one table: company, brand, phone, email, sales URL, HQ.
3. **Fifteen vertical sections** — the same companies grouped as in `Vendors.txt`, with per-vertical contact tables.
Vertical headings in `CONTACTS.md`:
1. E-Signature and Execution
2. Contract Lifecycle Management
3. Inspection, Safety and Field Evidence
4. Construction and Change Orders
5. Legal Practice and Case Management
6. Insurance and Claims
7. Accounting, Audit and Tax
8. HR, ATS and Employment Records
9. Property, Title and Mortgage
10. Meeting and Call Recording / Transcription
11. Document Generation and PDF Automation
12. Credentials and Certificates
13. Forms and Field Data Capture
14. GRC, Compliance and Risk
15. Logistics and Chain of Custody
## How to use it
- **Partnership / OEM:** sales form first; confirm the number on the linked page before dialing.
- **Do not** email personal employee inboxes (they were never collected).
- **Full catalog outreach** (non-vertical): `CONTACTS-ALL.md` / `contacts-all.csv`.
- **Why this vendor / what record they mint:** `VENDOR-RESEARCH.md` and `profiles/01``05`.
## Limits
- Numbers and inboxes change.
- Many SaaS vendors only publish a form — that URL **is** the contact path.
- A few brands have no sales URL (rare).
- This file is not a capability dump (no trigger/action lists). See `CAPABILITIES.md`.
## Related
- Full directory: `CONTACTS-ALL.md`
- Fit, USP, Zap counts, “record they create”: `VENDOR-RESEARCH.md`
- Long dossiers: `profiles/`
- Mongo: `zapier.apps` filtered by the same slugs

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="680"
viewBox="0 0 1100 680" role="img" aria-label="High-level architecture: Zapier to Verae via middleware">
<title>High-level architecture: Zapier to Verae via middleware</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">HIGH-LEVEL ARCHITECTURE</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Verae Time x Zapier</text>
<text x="24" y="70" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">Zapier never calls api.veraetime.net and never speaks NATS. HTTPS only at the public edge.</text>
<rect x="20" y="90" width="1060" height="150" rx="12" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.2"/>
<text x="36" y="112" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#C2410C" text-anchor="start">PUBLIC · Zapier cloud</text>
<rect x="20" y="258" width="700" height="280" rx="12" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.2"/>
<text x="36" y="280" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">YOUR INFRASTRUCTURE · public HTTPS edge + private workers</text>
<rect x="740" y="258" width="340" height="280" rx="12" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.2"/>
<text x="756" y="280" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#B45309" text-anchor="start">PRIVATE NETWORK</text>
<rect x="20" y="556" width="700" height="104" rx="12" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.2"/>
<text x="36" y="578" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#15803D" text-anchor="start">VERAE TIMESTAMPING SERVICE</text>
<rect x="740" y="556" width="340" height="104" rx="12" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.2"/>
<text x="756" y="578" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#C2410C" text-anchor="start">ZAPIER REST HOOKS</text>
<rect x="40" y="128" width="150" height="88" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="115" y="158" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">User</text>
<text x="115" y="178" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">Zap editor</text>
<text x="115" y="192" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">connection form</text>
<rect x="250" y="122" width="360" height="100" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="430" y="148" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Zapier Platform CLI app</text>
<text x="430" y="168" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">scratch/veraetime (session TS) or verae-zapier (zmw_ JS)</text>
<text x="430" y="183" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">runs on Zapier cloud when a Zap step executes</text>
<rect x="660" y="128" width="180" height="88" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#94A3B8" stroke-width="1.4"/>
<text x="750" y="158" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Zap trigger</text>
<text x="750" y="178" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">Timestamp Completed</text>
<text x="750" y="192" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">hooks.zapier.com</text>
<line x1="190" y1="172" x2="250" y2="172" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="220.0" y="161.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">configure / run</text>
<line x1="610" y1="172" x2="660" y2="172" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="635.0" y="161.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">hook fires Zap</text>
<rect x="48" y="300" width="644" height="120" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="370" y="326" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">verae-zapier-middleware /zapier/v1/*</text>
<text x="370" y="348" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">Auth bridge · tenants · entitlements · rate limits · REST Hook store</text>
<text x="370" y="364" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">GET /health POST /auth/login GET /auth/me POST /timestamp[/wait|/batch]</text>
<text x="370" y="380" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">POST /verify GET /status/{jobId} POST/DELETE /webhooks/*</text>
<line x1="430" y1="222" x2="430" y2="300" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="438" y="265.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="start">HTTPS Bearer zmw_ / zmt_</text>
<rect x="760" y="300" width="300" height="92" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="910" y="328" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">NATS JetStream</text>
<text x="910" y="348" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">ZAPIER_JOBS · EVENTS · WEBHOOKS</text>
<text x="910" y="362" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">never on the public internet</text>
<line x1="692" y1="346" x2="760" y2="346" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="726.0" y="335.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">publish (private)</text>
<rect x="760" y="412" width="300" height="108" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="910" y="438" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Workers</text>
<text x="910" y="458" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">job-poller jobs.watch</text>
<text x="910" y="473" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">event-router jobs.events</text>
<text x="910" y="488" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">webhook-deliver webhooks.deliver</text>
<line x1="910" y1="392" x2="910" y2="412" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="48" y="596" width="644" height="50" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="370" y="616" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">api.veraetime.net</text>
<text x="370" y="634" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="500" fill="#334155" text-anchor="middle">POST /auth/login POST /api/timestamp 202 {jobId} GET /api/status/{jobId} POST /api/verify</text>
<line x1="220" y1="420" x2="220" y2="596" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="228" y="512.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="start">sync HTTPS</text>
<line x1="820" y1="520" x2="370" y2="596" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="595.0" y="548.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">poll / create</text>
<rect x="760" y="596" width="300" height="50" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="910" y="626" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="600" fill="#0F2744" text-anchor="middle">POST hooks.zapier.com timestamp.completed</text>
<line x1="910" y1="520" x2="910" y2="596" stroke="#C2410C" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="918" y="562.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="start">HTTPS egress</text>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="520"
viewBox="0 0 1100 520" role="img" aria-label="Security boundaries">
<title>Security boundaries</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">SECURITY BOUNDARIES</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">What is public, what stays private</text>
<rect x="20" y="80" width="1060" height="200" rx="12" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.4"/>
<text x="40" y="106" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#C2410C" text-anchor="start">PUBLIC INTERNET</text>
<rect x="48" y="124" width="300" height="130" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="198" y="158" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Zapier cloud</text>
<text x="198" y="180" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">CLI app performs</text>
<text x="198" y="194" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">z.request only</text>
<text x="198" y="208" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">no NATS, no Verae JWT</text>
<rect x="400" y="124" width="300" height="130" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="550" y="158" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Middleware HTTPS</text>
<text x="550" y="180" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">/zapier/v1 only</text>
<text x="550" y="194" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">TLS required in prod</text>
<text x="550" y="208" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">rate limit + entitlements</text>
<rect x="752" y="124" width="300" height="130" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="902" y="158" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Zapier hook URLs</text>
<text x="902" y="180" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">untrusted egress</text>
<text x="902" y="194" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">timeouts required</text>
<text x="902" y="208" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">SSRF allowlist = Phase 15</text>
<line x1="348" y1="189" x2="400" y2="189" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="374.0" y="178.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">HTTPS in</text>
<line x1="700" y1="189" x2="752" y2="189" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="726.0" y="178.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">HTTPS out</text>
<rect x="20" y="300" width="1060" height="196" rx="12" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.4"/>
<text x="40" y="326" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#B45309" text-anchor="start">PRIVATE · do not expose ports 4222 / store / TOKEN_SECRET</text>
<rect x="48" y="348" width="320" height="126" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="208" y="380" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">NATS JetStream</text>
<text x="208" y="402" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">tokenRef, not raw JWT</text>
<text x="208" y="416" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">private network + auth</text>
<text x="208" y="430" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">mTLS is Phase 15</text>
<rect x="400" y="348" width="320" height="126" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="560" y="380" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">Workers + file store</text>
<text x="560" y="402" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">STORE_PATH store.json</text>
<text x="560" y="416" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">single-node MVP</text>
<text x="560" y="430" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Postgres/Redis = Phase 15</text>
<rect x="752" y="348" width="300" height="126" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="902" y="380" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="middle">api.veraetime.net</text>
<text x="902" y="402" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Verae JWT stays here</text>
<text x="902" y="416" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">server-side login only</text>
<text x="902" y="430" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">MOCK_VERAE for tests</text>
<line x1="368" y1="411" x2="400" y2="411" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="720" y1="411" x2="752" y2="411" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="560"
viewBox="0 0 1100 560" role="img" aria-label="Two-hop authentication">
<title>Two-hop authentication</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">AUTHENTICATION</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Two hops · Zapier never sees the Verae JWT</text>
<rect x="20" y="80" width="1060" height="220" rx="12" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.4"/>
<text x="40" y="106" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#1A6B6B" text-anchor="start">HOP 1 · end user → middleware</text>
<rect x="48" y="126" width="220" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="158" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">User in Zapier</text>
<text x="158" y="178" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">username + password</text>
<text x="158" y="192" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">or zmw_ API key</text>
<text x="158" y="206" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">api_base_url</text>
<text x="158" y="220" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">default :3100</text>
<rect x="320" y="126" width="280" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="460" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">POST /zapier/v1/auth/login</text>
<text x="460" y="178" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">loginWithCredentials</text>
<text x="460" y="192" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">or loginWithApiKey</text>
<text x="460" y="206" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">returns accessToken</text>
<text x="460" y="220" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">stored as sessionKey (TS)</text>
<rect x="650" y="126" width="200" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="750" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Tokens issued</text>
<text x="750" y="178" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">zmw_ tenant API key</text>
<text x="750" y="192" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">zmt_ HMAC session</text>
<text x="750" y="206" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">TOKEN_SECRET</text>
<text x="750" y="220" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">never commit</text>
<rect x="880" y="126" width="176" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="968" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Auth test</text>
<text x="968" y="178" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">GET /auth/me</text>
<text x="968" y="192" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">tenant + plan</text>
<text x="968" y="206" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">usage</text>
<text x="968" y="220" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">401 → refresh</text>
<line x1="268" y1="200" x2="320" y2="200" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="600" y1="200" x2="650" y2="200" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="850" y1="200" x2="880" y2="200" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="20" y="320" width="1060" height="216" rx="12" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.4"/>
<text x="40" y="346" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#15803D" text-anchor="start">HOP 2 · middleware → Verae (server-side only)</text>
<rect x="48" y="366" width="300" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="198" y="396" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">veraeClient</text>
<text x="198" y="418" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">POST /auth/login on Verae</text>
<text x="198" y="432" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">or MOCK_VERAE=true</text>
<text x="198" y="446" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">JWT held in process</text>
<text x="198" y="460" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">redacted in DEBUG_VERAE</text>
<rect x="400" y="366" width="300" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="550" y="396" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">api.veraetime.net</text>
<text x="550" y="418" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Authorization: Bearer &lt;JWT&gt;</text>
<text x="550" y="432" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">timestamp / status / verify</text>
<text x="550" y="446" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">source of truth</text>
<text x="550" y="460" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">not reachable from Zapier</text>
<rect x="752" y="366" width="300" height="148" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#C2410C" stroke-width="1.8"/>
<text x="902" y="396" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#C2410C" text-anchor="middle">Do not leak</text>
<text x="902" y="418" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">no Verae JWT in Zapier</text>
<text x="902" y="432" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">no JWT in NATS (use tokenRef)</text>
<text x="902" y="446" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">no secrets in git</text>
<text x="902" y="460" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">no secrets in debug logs</text>
<line x1="348" y1="440" x2="400" y2="440" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="700" y1="440" x2="752" y2="440" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="620"
viewBox="0 0 1100 620" role="img" aria-label="Create Timestamp async plus REST Hook">
<title>Create Timestamp async plus REST Hook</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">FLOW A</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Create Timestamp · async job + hook</text>
<rect x="-10" y="78" width="160" height="36" rx="6" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="70" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">Zapier app</text>
<line x1="70" y1="114" x2="70" y2="590" stroke="#94A3B8" stroke-dasharray="3 5"/>
<rect x="210" y="78" width="160" height="36" rx="6" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="290" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">Middleware</text>
<line x1="290" y1="114" x2="290" y2="590" stroke="#94A3B8" stroke-dasharray="3 5"/>
<rect x="430" y="78" width="160" height="36" rx="6" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="510" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">NATS</text>
<line x1="510" y1="114" x2="510" y2="590" stroke="#94A3B8" stroke-dasharray="3 5"/>
<rect x="650" y="78" width="160" height="36" rx="6" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="730" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">Workers</text>
<line x1="730" y1="114" x2="730" y2="590" stroke="#94A3B8" stroke-dasharray="3 5"/>
<rect x="870" y="78" width="160" height="36" rx="6" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="950" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">Verae / Hooks</text>
<line x1="950" y1="114" x2="950" y2="590" stroke="#94A3B8" stroke-dasharray="3 5"/>
<line x1="70" y1="148" x2="290" y2="148" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="180.0" y="137.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">1 POST /timestamp</text>
<line x1="290" y1="190" x2="950" y2="190" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="620.0" y="179.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">2 entitlement + POST /api/timestamp</text>
<line x1="950" y1="232" x2="290" y2="232" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="620.0" y="246.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">3 202 { jobId }</text>
<line x1="290" y1="274" x2="70" y2="274" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="180.0" y="288.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">4 return jobId to Zap</text>
<line x1="290" y1="322" x2="510" y2="322" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="400.0" y="311.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">5 publish jobs.watch</text>
<line x1="510" y1="364" x2="730" y2="364" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="620.0" y="353.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">6 job-poller</text>
<line x1="730" y1="406" x2="950" y2="406" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="840.0" y="395.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">7 GET /api/status/{jobId}</text>
<line x1="950" y1="448" x2="730" y2="448" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="840.0" y="462.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">8 pending: Nak + delay</text>
<line x1="730" y1="490" x2="510" y2="490" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="620.0" y="504.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">9 terminal → jobs.events</text>
<line x1="510" y1="532" x2="730" y2="532" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="620.0" y="521.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">10 match webhooks</text>
<line x1="730" y1="574" x2="950" y2="574" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="840.0" y="563.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">11 POST timestamp.completed</text>
<text x="24" y="612" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="500" fill="#64748B" text-anchor="start">Pair this action with the Timestamp Completed hook trigger. Zapier does not poll Verae.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="480"
viewBox="0 0 1100 480" role="img" aria-label="Create Timestamp and Wait">
<title>Create Timestamp and Wait</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">FLOW B</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Create Timestamp and Wait</text>
<text x="24" y="72" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">In-process path is live today. Wait-via-NATS is Phase 9.</text>
<rect x="40" y="100" width="200" height="80" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="140" y="132" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Zapier</text>
<text x="140" y="152" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">POST /timestamp/wait</text>
<rect x="320" y="100" width="260" height="80" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="450" y="132" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Middleware</text>
<text x="450" y="152" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">create job, then wait</text>
<line x1="240" y1="140" x2="320" y2="140" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="280.0" y="129.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">HTTPS</text>
<rect x="320" y="230" width="260" height="100" rx="8" fill="#E8F1F8" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="450" y="260" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#1A6B6B" text-anchor="middle">NATS_ENABLED=false</text>
<text x="450" y="280" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">in-process poller (Phase 6)</text>
<text x="450" y="294" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">returns StatusResponse</text>
<rect x="640" y="230" width="400" height="100" rx="8" fill="#F3EDE0" fill-opacity="1" stroke="#B45309" stroke-width="1.4"/>
<text x="840" y="260" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#B45309" text-anchor="middle">NATS_ENABLED=true · Phase 9 (open)</text>
<text x="840" y="280" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">subscribe to jobs.events</text>
<text x="840" y="294" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">hard timeout → { jobId, status: pending }</text>
<line x1="450" y1="180" x2="450" y2="230" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="580" y1="180" x2="840" y2="230" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="40" y="380" width="1020" height="72" rx="8" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.4"/>
<text x="550" y="410" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">Return to Zapier</text>
<text x="550" y="430" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">completed / failed status object or pending + jobId on timeout (Zapier can Find Job Status next)</text>
<line x1="450" y1="330" x2="450" y2="380" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="840" y1="330" x2="840" y2="380" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="560"
viewBox="0 0 1100 560" role="img" aria-label="NATS subject topology">
<title>NATS subject topology</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">NATS + JETSTREAM</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Private subjects, streams, and workers</text>
<rect x="40" y="88" width="250" height="250" rx="10" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<rect x="54" y="104" width="222" height="26" rx="4" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="0"/>
<text x="165.0" y="121.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="700" fill="#FFFFFF" text-anchor="middle">ZAPIER_JOBS</text>
<text x="165" y="156" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="600" fill="#134848" text-anchor="middle">verae.zapier.jobs.watch</text>
<text x="165" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Work queue</text>
<text x="165" y="200" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle"></text>
<text x="165" y="218" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">consumer: job-poller</text>
<text x="165" y="236" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">GET /api/status/{jobId}</text>
<rect x="310" y="88" width="250" height="250" rx="10" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<rect x="324" y="104" width="222" height="26" rx="4" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="0"/>
<text x="435.0" y="121.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="700" fill="#FFFFFF" text-anchor="middle">ZAPIER_EVENTS</text>
<text x="435" y="156" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="600" fill="#134848" text-anchor="middle">verae.zapier.jobs.events</text>
<text x="435" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Limits (time)</text>
<text x="435" y="200" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle"></text>
<text x="435" y="218" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">consumer: event-router</text>
<text x="435" y="236" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">enqueue webhooks / waiters</text>
<rect x="580" y="88" width="250" height="250" rx="10" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<rect x="594" y="104" width="222" height="26" rx="4" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="0"/>
<text x="705.0" y="121.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="700" fill="#FFFFFF" text-anchor="middle">ZAPIER_WEBHOOKS</text>
<text x="705" y="156" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="600" fill="#134848" text-anchor="middle">verae.zapier.webhooks.deliver</text>
<text x="705" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Work queue</text>
<text x="705" y="200" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle"></text>
<text x="705" y="218" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">consumer: webhook-deliver</text>
<text x="705" y="236" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">POST Zapier targetUrl</text>
<rect x="850" y="88" width="250" height="250" rx="10" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<rect x="864" y="104" width="222" height="26" rx="4" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="0"/>
<text x="975.0" y="121.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="700" fill="#FFFFFF" text-anchor="middle">ZAPIER_USAGE</text>
<text x="975" y="156" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="600" fill="#134848" text-anchor="middle">verae.zapier.usage</text>
<text x="975" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Optional</text>
<text x="975" y="200" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle"></text>
<text x="975" y="218" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">consumer: usage-writer</text>
<text x="975" y="236" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">billing export</text>
<line x1="290" y1="213" x2="310" y2="213" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="560" y1="213" x2="580" y2="213" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="830" y1="213" x2="850" y2="213" stroke="#94A3B8" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="40" y="364" width="1020" height="168" rx="10" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.4"/>
<text x="60" y="392" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">Ack semantics</text>
<text x="60" y="418" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">Job still pending Nak with delay ~ intervalMs or republish attempt+1</text>
<text x="60" y="440" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">Job terminal publish jobs.events, then Ack the watch message</text>
<text x="60" y="462" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">Webhook HTTP 2xx Ack · 5xx / network Nak until max_deliver</text>
<text x="60" y="484" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">Poison message terminate after max_deliver; DEBUG_VERAE=webhooks DLQ log</text>
<text x="60" y="506" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">Prefer tokenRef over embedding a Verae JWT in any NATS payload</text>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="640"
viewBox="0 0 1100 640" role="img" aria-label="Zapier operations mapped to middleware and Verae">
<title>Zapier operations mapped to middleware and Verae</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">OPERATIONS MAP</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Connector → /zapier/v1 → Verae wrap</text>
<rect x="20" y="78" width="1060" height="36" rx="0" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="40" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="start">Zapier</text>
<text x="280" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="start">Type</text>
<text x="400" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="start">Middleware</text>
<text x="700" y="101" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="start">Verae</text>
<rect x="20" y="114" width="1060" height="52" rx="0" fill="#FFFFFF" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="146" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Create Timestamp</text>
<text x="280" y="146" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">create</text>
<text x="400" y="146" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">POST /timestamp</text>
<text x="700" y="146" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">POST /api/timestamp → 202 jobId</text>
<rect x="20" y="166" width="1060" height="52" rx="0" fill="#EEF2F6" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="198" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Create Timestamp and Wait</text>
<text x="280" y="198" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">create</text>
<text x="400" y="198" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">POST /timestamp/wait</text>
<text x="700" y="198" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">create + poll / wait</text>
<rect x="20" y="218" width="1060" height="52" rx="0" fill="#FFFFFF" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="250" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Create Batch Timestamps</text>
<text x="280" y="250" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">create</text>
<text x="400" y="250" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">POST /timestamp/batch</text>
<text x="700" y="250" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">POST /api/batch/timestamp</text>
<rect x="20" y="270" width="1060" height="52" rx="0" fill="#EEF2F6" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="302" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Verify Certificate</text>
<text x="280" y="302" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">create</text>
<text x="400" y="302" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">POST /verify</text>
<text x="700" y="302" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">POST /api/verify</text>
<rect x="20" y="322" width="1060" height="52" rx="0" fill="#FFFFFF" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="354" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Find Job Status</text>
<text x="280" y="354" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">search</text>
<text x="400" y="354" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">GET /status/{jobId}</text>
<text x="700" y="354" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">GET /api/status/{jobId}</text>
<rect x="20" y="374" width="1060" height="52" rx="0" fill="#EEF2F6" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="406" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Find Job Verification</text>
<text x="280" y="406" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">search (TS)</text>
<text x="400" y="406" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">GET /status/{jobId}/verification</text>
<text x="700" y="406" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">GET /api/verify/{jobId}</text>
<rect x="20" y="426" width="1060" height="52" rx="0" fill="#FFFFFF" fill-opacity="1" stroke="#94A3B8" stroke-width="0.6"/>
<text x="40" y="458" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="600" fill="#0F2744" text-anchor="start">Timestamp Completed</text>
<text x="280" y="458" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">hook</text>
<text x="400" y="458" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="600" fill="#134848" text-anchor="start">POST /webhooks/subscribe</text>
<text x="700" y="458" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">(no Verae hook — middleware stores targetUrl)</text>
<text x="24" y="500" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">Creates return one object. Searches and hook perform return arrays. 404 on status search → [].</text>
<rect x="20" y="520" width="340" height="96" rx="8" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.4"/>
<text x="36" y="546" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#C2410C" text-anchor="start">Zapier cloud</text>
<text x="36" y="566" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">scratch/veraetime</text>
<text x="36" y="580" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">or verae-zapier</text>
<rect x="390" y="520" width="340" height="96" rx="8" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.4"/>
<text x="406" y="546" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#1A6B6B" text-anchor="start">Middleware :3100</text>
<text x="406" y="566" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">api_base_url / MIDDLEWARE_BASE_URL</text>
<text x="406" y="580" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">never api.veraetime.net from Zapier</text>
<rect x="760" y="520" width="320" height="96" rx="8" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.4"/>
<text x="776" y="546" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#15803D" text-anchor="start">Verae API</text>
<text x="776" y="566" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">JWT server-side only</text>
<text x="776" y="580" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="start">OpenAPI in scratch/our-api/</text>
<line x1="360" y1="568" x2="390" y2="568" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="730" y1="568" x2="760" y2="568" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="580"
viewBox="0 0 1100 580" role="img" aria-label="Middleware internals">
<title>Middleware internals</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">MIDDLEWARE INTERNALS</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">verae-zapier-api/verae-zapier-middleware</text>
<rect x="20" y="80" width="160" height="70" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="100" y="110" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">GET /health</text>
<text x="100" y="128" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="400" fill="#334155" text-anchor="middle">liveness</text>
<rect x="200" y="80" width="880" height="70" rx="8" fill="#0F2744" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="640" y="110" font-family="Helvetica, Arial, sans-serif" font-size="16" font-weight="700" fill="#FFFFFF" text-anchor="middle">Express /zapier → /v1</text>
<text x="640" y="132" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#CBD5E1" text-anchor="middle">authenticate · rateLimit on protected routes</text>
<rect x="20" y="172" width="340" height="180" rx="8" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.4"/>
<text x="36" y="198" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#1A6B6B" text-anchor="start">Public</text>
<text x="36" y="222" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">POST /v1/auth/login</text>
<text x="36" y="248" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">GET /v1/auth/me</text>
<text x="36" y="274" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">POST /v1/signup</text>
<text x="36" y="300" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">GET /v1/admin/* (X-Admin-Secret)</text>
<rect x="380" y="172" width="360" height="180" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="396" y="198" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">Protected /v1</text>
<text x="396" y="222" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">/timestamp /timestamp/wait /batch</text>
<text x="396" y="248" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">/verify</text>
<text x="396" y="274" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">/status/:jobId[/verification]</text>
<text x="396" y="300" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">/webhooks/subscribe|unsubscribe</text>
<rect x="760" y="172" width="320" height="180" rx="8" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.4"/>
<text x="776" y="198" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#B45309" text-anchor="start">Services + store</text>
<text x="776" y="222" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">auth / entitlement / tenant</text>
<text x="776" y="248" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">timestamp / verify / webhook</text>
<text x="776" y="274" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">store.json tenants usage hooks</text>
<text x="776" y="300" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">veraeClient (+ mock)</text>
<rect x="20" y="372" width="520" height="180" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="36" y="400" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">Flags</text>
<text x="36" y="426" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">NATS_ENABLED=false in-process job poller (Phase 6 product path)</text>
<text x="36" y="452" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">NATS_ENABLED=true JetStream workers; no in-process poller</text>
<text x="36" y="478" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">MOCK_VERAE=true deterministic jobs, no live Verae</text>
<text x="36" y="504" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">DEBUG_VERAE=auth,nats,jobs,webhooks,http,billing</text>
<rect x="560" y="372" width="520" height="180" rx="8" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.4"/>
<text x="576" y="400" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#15803D" text-anchor="start">Outbound</text>
<text x="576" y="426" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">HTTPS VERAE_API_BASE_URL (prod: api.veraetime.net)</text>
<text x="576" y="452" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">NATS NATS_URL nats://127.0.0.1:4222</text>
<text x="576" y="478" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">HTTPS Zapier targetUrl (webhook worker)</text>
<text x="576" y="504" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Never bind NATS to a public interface</text>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="520"
viewBox="0 0 1100 520" role="img" aria-label="Implementation phase roadmap">
<title>Implementation phase roadmap</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">ROADMAP</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">TODO.md phases and gates · do not skip</text>
<rect x="40" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="105" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">0 Docs</text>
<text x="105" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="170" y1="128" x2="190" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="190" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="255" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">1 Debug</text>
<text x="255" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="320" y1="128" x2="340" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="340" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="405" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">2 HTTP</text>
<text x="405" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="470" y1="128" x2="490" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="490" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="555" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">3 Store</text>
<text x="555" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="620" y1="128" x2="640" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="640" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="705" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">4 Client</text>
<text x="705" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="770" y1="128" x2="790" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="790" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="855" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">5 Auth</text>
<text x="855" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="920" y1="128" x2="940" y2="128" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="940" y="100" width="130" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="1005" y="124" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">6 Sync API</text>
<text x="1005" y="142" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="1005" y1="156" x2="1005" y2="190" stroke="#1A6B6B" stroke-width="1.8"/>
<line x1="24" y1="190" x2="1005" y2="190" stroke="#1A6B6B" stroke-width="1.8"/>
<line x1="24" y1="190" x2="24" y2="428" stroke="#1A6B6B" stroke-width="1.8"/>
<line x1="24" y1="238" x2="40" y2="238" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="40" y="210" width="180" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="130" y="234" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">7 NATS</text>
<text x="130" y="252" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="220" y1="238" x2="240" y2="238" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="240" y="210" width="180" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="330" y="234" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">8 Workers</text>
<text x="330" y="252" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="420" y1="238" x2="440" y2="238" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="440" y="210" width="180" height="56" rx="8" fill="#FEF3C7" fill-opacity="1" stroke="#B45309" stroke-width="1.4"/>
<text x="530" y="234" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">9 Wait-via-NATS</text>
<text x="530" y="252" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#64748B" text-anchor="middle">open blocker</text>
<line x1="24" y1="338" x2="40" y2="338" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="40" y="310" width="180" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="130" y="334" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">10 Tenancy</text>
<text x="130" y="352" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="24" y1="428" x2="40" y2="428" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="40" y="400" width="180" height="56" rx="8" fill="#1A6B6B" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="130" y="424" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#FFFFFF" text-anchor="middle">11 Zapier app</text>
<text x="130" y="442" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#99F6E4" text-anchor="middle">gate passed</text>
<line x1="220" y1="428" x2="240" y2="428" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="240" y="400" width="180" height="56" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="330" y="424" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">12 E2E local</text>
<text x="330" y="442" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#64748B" text-anchor="middle">next</text>
<line x1="420" y1="428" x2="440" y2="428" stroke="#94A3B8" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="440" y="400" width="180" height="56" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="530" y="424" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">13 Production</text>
<text x="530" y="442" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#64748B" text-anchor="middle">next</text>
<line x1="620" y1="428" x2="640" y2="428" stroke="#94A3B8" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="640" y="400" width="180" height="56" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="730" y="424" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">14 Private push</text>
<text x="730" y="442" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#64748B" text-anchor="middle">next</text>
<line x1="820" y1="428" x2="840" y2="428" stroke="#94A3B8" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="840" y="400" width="180" height="56" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="930" y="424" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#0F2744" text-anchor="middle">15 Harden</text>
<text x="930" y="442" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="500" fill="#64748B" text-anchor="middle">next</text>
<text x="24" y="500" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">Phase 9 is the open blocker before multi-instance wait. Phase 12 needs 8 + 10 + 11.</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="560"
viewBox="0 0 1100 560" role="img" aria-label="Research workspace and integration path">
<title>Research workspace and integration path</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">THIS WORKSPACE</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">How Grok, CLIs, Mongo, and the stack fit together</text>
<rect x="20" y="80" width="340" height="220" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="36" y="108" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">Laptop · this repo</text>
<text x="36" y="132" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">getting-started.md / .pdf</text>
<text x="36" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">scratch/veraetime</text>
<text x="36" y="180" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">verae-zapier-api/</text>
<text x="36" y="204" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">docs/diagrams/</text>
<text x="36" y="228" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">/zapier-build skill</text>
<text x="36" y="252" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">scripts/restart-grok.sh</text>
<rect x="380" y="80" width="340" height="220" rx="8" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.4"/>
<text x="396" y="108" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#1A6B6B" text-anchor="start">Local runtime</text>
<text x="396" y="132" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">zapier-platform 19.1.0</text>
<text x="396" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">zapier-sdk 0.77.1</text>
<text x="396" y="180" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">middleware :3100</text>
<text x="396" y="204" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">optional NATS :4222</text>
<text x="396" y="228" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">build + validate (no login)</text>
<text x="396" y="252" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">register / push need ~/.zapierrc</text>
<rect x="740" y="80" width="340" height="220" rx="8" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.4"/>
<text x="756" y="108" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#B45309" text-anchor="start">NS1 Mongo (tunneled)</text>
<text x="756" y="132" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">ssh -L 27017:127.0.0.1:27017 ns1</text>
<text x="756" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">db zapier</text>
<text x="756" y="180" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">apps · templates · help</text>
<text x="756" y="204" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">platform_reference</text>
<text x="756" y="228" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">never 70.88.205.138:27017 public</text>
<text x="756" y="252" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">creds in ~/.mcp-env only</text>
<line x1="360" y1="190" x2="380" y2="190" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="720" y1="190" x2="740" y2="190" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<text x="730.0" y="179.0" font-family="Helvetica, Arial, sans-serif" font-size="10" font-weight="600" fill="#134848" text-anchor="middle">tunnel</text>
<rect x="20" y="324" width="520" height="208" rx="8" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.4"/>
<text x="36" y="352" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#C2410C" text-anchor="start">Publish path</text>
<text x="36" y="378" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">1 validate locally against middleware</text>
<text x="36" y="404" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">2 zapier-platform login (browser)</text>
<text x="36" y="430" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">3 public HTTPS middleware (Phase 13)</text>
<text x="36" y="456" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">4 register + push private version (Phase 14)</text>
<text x="36" y="482" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">5 one human E2E Zap, then consider listing</text>
<rect x="560" y="324" width="520" height="208" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="576" y="352" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">Consume path (optional, not Verae publish)</text>
<text x="576" y="378" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">zapier-sdk login → call existing apps</text>
<text x="576" y="404" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Hosted MCP mcp.zapier.com/api/v1/connect</text>
<text x="576" y="430" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">discover → enable → inspect → execute</text>
<text x="576" y="456" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">writes need explicit approval; 2 tasks each</text>
<text x="576" y="482" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">do not mix with zapier-platform</text>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="620"
viewBox="0 0 1100 620" role="img" aria-label="Zapier and Verae billing layers">
<title>Zapier and Verae billing layers</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">BILLING</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="20" font-weight="700" fill="#0F2744" text-anchor="start">Two meters · Zapier tasks + Verae timestamps</text>
<text x="24" y="72" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">Publishing the Verae app is free. The customers Zapier plan is not Veraes invoice.</text>
<rect x="20" y="88" width="1060" height="80" rx="10" fill="#FFF1E6" fill-opacity="1" stroke="#C2410C" stroke-width="1.4"/>
<text x="40" y="116" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">A Zapier customer plan</text>
<text x="40" y="138" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Tasks / month (or Enterprise annual pool)</text>
<text x="40" y="156" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Free 100 · Pro from 750 · Team from 2k · Ent custom</text>
<rect x="20" y="178" width="1060" height="80" rx="10" fill="#E8F1F8" fill-opacity="1" stroke="#1A6B6B" stroke-width="1.4"/>
<text x="40" y="206" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">B Task multipliers</text>
<text x="40" y="228" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">1 = typical action (Create Timestamp)</text>
<text x="40" y="246" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">MCP execute = 2 AI Advanced = 3 Premium = 5</text>
<rect x="20" y="268" width="1060" height="80" rx="10" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="40" y="296" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">C Overflow</text>
<text x="40" y="318" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Pay-per-task on paid plans</text>
<text x="40" y="336" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Annual 1.25x · monthly 2.5x · cap 3x then pause</text>
<rect x="20" y="358" width="1060" height="80" rx="10" fill="#E8F6EE" fill-opacity="1" stroke="#15803D" stroke-width="1.4"/>
<text x="40" y="386" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">D Verae middleware plan</text>
<text x="40" y="408" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Timestamps / verifications / batch / RPM</text>
<text x="40" y="426" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">free 50 · starter 500 · pro 5k · enterprise contract</text>
<rect x="20" y="448" width="1060" height="80" rx="10" fill="#F3EDE0" fill-opacity="1" stroke="#B45309" stroke-width="1.4"/>
<text x="40" y="476" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">E Partner / embed</text>
<text x="40" y="498" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Directory publish = $0 to Verae</text>
<text x="40" y="516" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">White Label: Zapier bills the product co. (usage)</text>
<rect x="20" y="538" width="1060" height="80" rx="10" fill="#F1F5F9" fill-opacity="1" stroke="#334155" stroke-width="1.4"/>
<text x="40" y="566" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="700" fill="#0F2744" text-anchor="start">F Add-ons (not tasks)</text>
<text x="40" y="588" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Agents = activities Chatbots = seat/tier</text>
<text x="40" y="606" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#334155" text-anchor="start">Do not mix into the Zapier task estimate</text>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="680"
viewBox="0 0 1100 680" role="img" aria-label="Timestamped files on Peergos with tiered IPFS and cold retrieve">
<title>Timestamped files on Peergos with tiered IPFS and cold retrieve</title>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1A6B6B"/>
</marker>
<marker id="arrow-navy" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0F2744"/>
</marker>
<marker id="arrow-accent" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#C2410C"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#F8FAFC"/>
<text x="24" y="28" font-family="Helvetica, Arial, sans-serif" font-size="11" font-weight="700" fill="#1A6B6B" text-anchor="start">CLIENT PATTERN</text>
<text x="24" y="50" font-family="Helvetica, Arial, sans-serif" font-size="18" font-weight="700" fill="#0F2744" text-anchor="start">Timestamp · metadata · Peergos · pin cache · cold retrieve</text>
<text x="24" y="70" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="500" fill="#64748B" text-anchor="start">Keep the index hot. Do not keep every CID live on a gateway.</text>
<rect x="20" y="88" width="1060" height="200" rx="12" fill="#E8F1F8" fill-opacity="1" stroke="#C5D6E8" stroke-width="1.4"/>
<text x="36" y="112" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="700" fill="#1A6B6B" text-anchor="start">WRITE PATH (Zapier orchestrates; Verae timestamps the hash)</text>
<rect x="40" y="128" width="190" height="132" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="135" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">1 Source</text>
<text x="135" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Drive / mail /</text>
<text x="135" y="202" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Peergos outbox</text>
<rect x="250" y="128" width="190" height="132" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="345" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">2 Hash</text>
<text x="345" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">SHA-256 or</text>
<text x="345" y="202" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">envelope JSON</text>
<rect x="460" y="128" width="190" height="132" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="555" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">3 Verae</text>
<text x="555" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Create Timestamp</text>
<text x="555" y="202" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">jobId + hook</text>
<rect x="670" y="128" width="190" height="132" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="765" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">4 Store</text>
<text x="765" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">Peergos e2e file</text>
<text x="765" y="202" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">optional hot pin</text>
<rect x="880" y="128" width="190" height="132" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.4"/>
<text x="975" y="156" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="middle">5 Index</text>
<text x="975" y="182" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">cid · jobId · class</text>
<text x="975" y="202" font-family="Helvetica, Arial, sans-serif" font-size="12" font-weight="400" fill="#334155" text-anchor="middle">always on</text>
<line x1="230" y1="194" x2="250" y2="194" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="440" y1="194" x2="460" y2="194" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="650" y1="194" x2="670" y2="194" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<line x1="860" y1="194" x2="880" y2="194" stroke="#1A6B6B" stroke-width="1.8" marker-end="url(#arrow)"/>
<rect x="20" y="308" width="340" height="200" rx="8" fill="#FFF1E6" fill-opacity="1" stroke="#F0D2B8" stroke-width="1.4"/>
<text x="36" y="336" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#C2410C" text-anchor="start">HOT · cache pin</text>
<text x="36" y="362" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Kubo / Pinata / Filebase</text>
<text x="36" y="386" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Pinning Services API</text>
<text x="36" y="410" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">TTL = pinnedUntil</text>
<text x="36" y="434" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">drop when cold copy exists</text>
<rect x="380" y="308" width="340" height="200" rx="8" fill="#E8F6EE" fill-opacity="1" stroke="#B7DCC7" stroke-width="1.4"/>
<text x="396" y="336" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#15803D" text-anchor="start">WARM · Peergos</text>
<text x="396" y="362" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">e2e encrypted IPFS blocks</text>
<text x="396" y="386" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">user capabilities / sharing</text>
<text x="396" y="410" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">host cannot read plaintext</text>
<text x="396" y="434" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">not a public CDN</text>
<rect x="740" y="308" width="340" height="200" rx="8" fill="#F3EDE0" fill-opacity="1" stroke="#E0D2B4" stroke-width="1.4"/>
<text x="756" y="336" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#B45309" text-anchor="start">COLD · retrieve on demand</text>
<text x="756" y="362" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">S3 Glacier IR / Flexible / Deep</text>
<text x="756" y="386" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">or Filecoin / B2 / Storj</text>
<text x="756" y="410" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Iceberg = catalog, not bytes</text>
<text x="756" y="434" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">restore API → short re-pin</text>
<rect x="20" y="528" width="1060" height="128" rx="8" fill="#FFFFFF" fill-opacity="1" stroke="#0F2744" stroke-width="1.8"/>
<text x="36" y="556" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="700" fill="#0F2744" text-anchor="start">READ PATH GET /ipfs/{cid} or gateway miss</text>
<text x="36" y="582" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">1 look up index by cid (always-on). 2 pin-hot hit → serve. 3 Peergos capability → fetch encrypted blocks.</text>
<text x="36" y="604" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">4 storageClass glacier-* → StartRestore / vendor retrieve → 202 + Retry-After → rehydrate → optional short pin → serve.</text>
<text x="36" y="626" font-family="Helvetica, Arial, sans-serif" font-size="13" font-weight="400" fill="#334155" text-anchor="start">Never walk every pin provider. Never put raw files or Verae JWTs in the Zap.</text>
</svg>

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -0,0 +1,25 @@
# Architecture diagrams
SVG sources for [getting-started.md](../../getting-started.md) and `getting-started.pdf`.
| File | What it shows |
|------|----------------|
| [01-high-level-architecture.svg](01-high-level-architecture.svg) | End-to-end stack: Zapier cloud, middleware, NATS, workers, Verae, REST Hooks |
| [02-security-boundaries.svg](02-security-boundaries.svg) | Public HTTPS vs private NATS / store / Verae JWT |
| [03-auth-two-hop.svg](03-auth-two-hop.svg) | User → middleware tokens; middleware → Verae JWT |
| [04-flow-async-timestamp.svg](04-flow-async-timestamp.svg) | Create Timestamp + hook sequence |
| [05-flow-wait.svg](05-flow-wait.svg) | Create and Wait (in-process vs Phase 9 NATS) |
| [06-nats-topology.svg](06-nats-topology.svg) | Streams, subjects, consumers, ack rules |
| [07-operations-map.svg](07-operations-map.svg) | Zapier nouns → `/zapier/v1` → Verae |
| [08-middleware-internals.svg](08-middleware-internals.svg) | Express routes, store, flags |
| [09-phase-roadmap.svg](09-phase-roadmap.svg) | Gates 015 |
| [10-workspace-integration.svg](10-workspace-integration.svg) | Repo, CLIs, Mongo tunnel, publish vs consume |
| [11-zapier-billing.svg](11-zapier-billing.svg) | Zapier task plans vs Verae timestamp quotas vs embed |
| [12-peergos-ipfs-tiered-storage.svg](12-peergos-ipfs-tiered-storage.svg) | Timestamp + Peergos + pin cache + Glacier retrieve-on-demand |
Regenerate:
```bash
python3 scripts/generate-diagrams.py
python3 scripts/generate-getting-started-pdf.py
```

View file

@ -0,0 +1,88 @@
# VENDOR-RESEARCH.md — what was collected
**Source file:** [VENDOR-RESEARCH.md](../VENDOR-RESEARCH.md)
**Compiled:** 17 August 2026
**Catalog:** Zapier API v4, 9,985 apps
**Contacts:** official company pages (same campaign as `CONTACTS.md`)
This is the **strategy layer** on top of the contact tables: 15 “immutable-proof” verticals, why each matters for a timestamping / seal product, Zap usage, fit, and a card per vendor (legal name, HQ, USP, record they create, Zapier rank).
## How the list was built
`Vendors.txt` named 15 verticals and approximate app counts, not vendor names. The live directory was filtered to products that create **contemporaneous records** (a signed envelope, an inspection, a claim note, a filed return, a recorded call, a certificate). Counts match the brief: **270 placements / 256 unique** companies.
Each card aims to include legal name, HQ, phone, email, sales/demo URL, support, LinkedIn, Zapier slug, published Zap count, parent, pricing posture, directory blurb, USP, and **the record they create** (what would be sealed). Many SaaS vendors only publish a form.
## Roll-up
| # | Vertical | n | Zap usage | Fit (as written) |
|---|----------|--:|----------:|------------------|
| 1 | E-Signature and Execution | 26 | 9,177 | High (crowded; differentiation is the point) |
| 2 | Contract Lifecycle Management | 7 | 223 | High (natural feature; higher ACV) |
| 3 | Inspection, Safety and Field Evidence | 18 | 1,198 | Strongest |
| 4 | Construction and Change Orders | 20 | 13,128 | High (SMB long tail is the fastest land) |
| 5 | Legal Practice and Case Management | 19 | 5,224 | High (ILTACON beachhead) |
| 6 | Insurance and Claims | 16 | 2,767 | High (low IT friction at agencies) |
| 7 | Accounting, Audit and Tax | 23 | 26,423 | High (IRS-examination adjacency) |
| 8 | HR, ATS and Employment Records | 26 | 4,178 | High |
| 9 | Property, Title and Mortgage | 17 | 12,547 | High with conflict caution (Catalis adjacency) |
| 10 | Meeting and Call Recording / Transcription | 24 | 20,578 | High (fast-growing; no one seals) |
| 11 | Document Generation and PDF Automation | 21 | 6,883 | Highest technical ease / OEM |
| 12 | Credentials and Certificates | 13 | 1,021 | High (verification already the use case) |
| 13 | Forms and Field Data Capture | 20 | 152,268 | Distribution, not ACV |
| 14 | GRC, Compliance and Risk | 10 | 93 | High OEM (under-represented on Zapier) |
| 15 | Logistics and Chain of Custody | 10 | 748 | Validate demand first |
Zap usage is Zapiers **published Zap count** for those apps, not revenue.
## How to read a vertical
Each numbered section typically has:
- Competitive density
- Why immutable proof matters (what buyers already think “proof” is)
- Fit rating
- Link to a long dossier under `profiles/` (five dossiers cover clusters of verticals)
- A vendor table (legal name, phone, email, sales URL)
- Then **per-vendor cards** (Docusign-style): HQ, Zapier rank, years on Zapier, parent, pricing posture, USP, **record they create**, contact notes
Example of “record they create”:
- Docusign — completed envelope + certificate of completion + audit log (vendor-attested)
- SignNow — signed document + workflow history
- eSignatures.com — web-signed contract + status webhooks
The research thesis: todays proof is **vendor-attested**. An independent cryptographic timestamp is a response they have to make.
## Files in this campaign
| File | Role |
|------|------|
| `VENDOR-RESEARCH.md` | This narrative + cards |
| `CONTACTS.md` / `contacts.csv` | Outreach table for the same 256 |
| `CONTACTS-ALL.md` / `contacts-all.csv` | All 9,985 public apps |
| `identified-vendors.json` | Machine list per vertical (slug, Zap count, USP blurb) |
| `profiles/01``05` | Long-form dossiers (e-sign/CLM; inspect/construction/logistics; legal/insurance/property; accounting/HR/GRC; meetings/docs/creds/forms) |
| `CAPABILITIES.md` | Triggers, actions, searches, hook vs poll |
| `Vendors.txt` | Original 15-vertical brief |
## Strategic read (from the roll-up, not new invention)
- **Most Zap volume in-scope:** Forms (152k) — distribution, low ACV.
- **Highest “seal is the product” adjacency:** e-sign, credentials, GRC, inspection.
- **Highest technical ease / OEM:** document generation and PDF automation.
- **Strongest field-evidence story:** inspection / safety.
- **Validate before a bet:** logistics and chain of custody (748 Zaps, n=10).
- **Crowded:** e-sign (Zapier Signatures category ~85 apps; 26 on this list).
## Limits
- Fit ratings are analyst judgment from public pages, not customer interviews.
- Zap counts are a popularity proxy and double-count multi-vertical placements in the 270 figure.
- Contact fields go stale; confirm before outreach.
- Not a substitute for `CAPABILITIES.md` (controls) or OpenAPI (Veraes own API).
## Related summaries
- [contacts-summary.md](contacts-summary.md) — 15-vertical contact coverage
- [contacts-all-summary.md](contacts-all-summary.md) — full catalog coverage

View file

@ -0,0 +1,291 @@
# Zapier cost structure and billing models
**Planning brief for Verae Time**
Source: official Zapier pricing at [zapier.com/pricing](https://zapier.com/pricing), captured 1718 August 2026 (USD).
Confirm live rates before a customer quote. The rate card at `/pricing/rates` was not fetchable at write time; multipliers below are those Zapier publishes on the main pricing page and “What is a task?” article (updated June 2026).
This document explains **how Zapier charges**, with examples, so we can design **Veraes** meter without colliding with or accidentally subsidizing Zapier.
---
## 1. The one idea that unlocks the rest
Zapier does **not** charge per Zap, per app, or per seat on Professional. It charges for **successful work**.
You buy two things that travel together:
1. A **plan level** — the feature set (Free / Professional / Team / Enterprise).
2. A **task tier** — a monthly (or Enterprise annual) allowance of **tasks**.
Then three other economies sit **beside** that, not inside it:
| Economy | Unit | Used for |
|---------|------|----------|
| **Core Zapier** | Task | Zaps, AI-by-Zapier, Code-by-Zapier, MCP, SDK |
| **Agents add-on** | Activity | Zapier Agents (does not draw tasks) |
| **Chatbots add-on** | Feature tier (number of bots) | Zapier Chatbots (not task-metered) |
| **Verae (us)** | Timestamp / verify / batch | Middleware `PLAN_LIMITS` — a **second invoice** |
Verae never appears on the Zapier invoice unless we sign a **White Label / Powered by Zapier** contract and resell Zapier usage ourselves.
---
## 2. What a task is (and is not)
A **task** is counted when Zapier **successfully completes** a unit of work. Failures are free.
### Counts
- A successful **action in another product**: Create Timestamp, post Slack, add a Drive file, write a Sheet row, call a webhook.
- A successful **Zapier MCP** tool execute (read or write).
- **AI by Zapier** and **Code by Zapier** (with multipliers / extra runtime — §4).
### Does not count
- The **trigger** (including polling every 115 minutes).
- **Logic and prep**: Filter, Paths, Formatter, Delay, Looping, Sub-Zap, Digest, Zapier Manager, Storage.
- **Zapier Tables** and **Zapier Forms** triggers and actions.
- Building, turning on, or testing a Zap until a step actually succeeds in production.
Shared pool: one allowance for the whole account. There is no separate MCP budget.
---
## 3. Plan levels (what you can build)
Plans are cumulative. Task **volume** is chosen separately (§5).
| | Free | Professional | Team | Enterprise |
|--|------|--------------|------|------------|
| Seats | 1 | 1 | 25 | Unlimited |
| Zap shape | Two-step only (trigger + 1 action) | Multi-step | Multi-step | Multi-step |
| Polling interval | 15 min | 2 min | 1 min | 1 min |
| Premium apps, webhooks | No | Yes | Yes | Yes |
| Filters, Paths, Formatter, AI by Zapier | No | Yes | Yes | Yes |
| Shared Zaps / connections, SAML SSO | No | No | Yes | Yes |
| SCIM, app controls, custom retention, TAM, BYOM | No | No | No | Yes |
| Task cycle | Monthly | Monthly | Monthly | **Annual** task limit |
| Pay-per-task overflow | No | Optional | Optional | Custom |
| Entry price (annual, USD/mo) | $0 (100 tasks) | **$19.99** (750 tasks) | **$69** (2,000 tasks) | Sales |
Also: 14-day Professional trial (no card). Non-profit: extra 15% off the subscription, **not** on pay-per-task. Live chat on Professional only at the **2,000+** task tier.
**Implication for Verae:** a Free customer can run **only** “new file → Create Timestamp” (two steps). Anything with a catalog write, Slack notify, or Wait **plus** another action needs Professional.
---
## 4. Variable pricing inside the task pool
Not every successful step costs one task. Zapier uses **multipliers** so expensive compute costs more of the same allowance.
| Work | Tasks per success | Notes |
|------|------------------:|-------|
| Typical third-party action (Verae Create Timestamp, Slack, Drive, Sheets, webhook) | **1** | The default. Design around this. |
| Standard AI by Zapier (default model) | **1** | Same as a normal action |
| Advanced AI by Zapier | **3** | Confirm on `/pricing/rates` |
| Premium AI by Zapier | **5** | Confirm on `/pricing/rates` |
| Zapier MCP `execute` (read or write) | **2** | Discover / inspect / enable are free meta-tools |
| Code by Zapier | 0 during **included** runtime; then **1 per extra 30 s** | Included: Free 1 s, Pro/Team 30 s, Enterprise 2 min. Extended runtime is opt-in on paid plans (18 min cap). |
| Zapier SDK | Free **while in beta** | Zapier will announce when beta pricing starts; assume it will join the task pool |
**Failed steps = 0 Zapier tasks.** They can still hit Verae (Autoreplay / customer retries). That is our problem, not Zapiers.
---
## 5. Task tiers and list price (USD, August 2026)
Self-serve is sold as **plan × tier**. Annual is ~33% off monthly. Figures are **per month**.
### Professional
| Tasks / mo | Annual / mo | Monthly / mo | Implied $/task (annual) |
|-----------:|------------:|-------------:|------------------------:|
| 750 | $19.99 | $29.99 | $0.027 |
| 1,500 | $39.00 | $58.50 | $0.026 |
| 2,000 | $49.00 | $73.50 | $0.025 |
| 5,000 | $89.00 | $133.50 | $0.018 |
| 10,000 | $129.00 | $193.50 | $0.013 |
| 20,000 | $189.00 | $283.50 | $0.0095 |
| 50,000 | $289.00 | $433.50 | $0.0058 |
| 100,000 | $489.00 | $733.50 | $0.0049 |
| 200,000 | $769.00 | $1,149.00 | $0.0038 |
| 500,000 | $1,499.00 | $2,199.00 | $0.0030 |
| 1,000,000 | $2,199.00 | $3,299.00 | $0.0022 |
| 2,000,000 | $3,389.00 | $5,099.00 | $0.0017 |
### Team (starts at 2,000)
| Tasks / mo | Annual / mo | Monthly / mo | Implied $/task (annual) |
|-----------:|------------:|-------------:|------------------------:|
| 2,000 | $69.00 | $103.50 | $0.035 |
| 5,000 | $119.00 | $178.50 | $0.024 |
| 10,000 | $169.00 | $253.50 | $0.017 |
| 20,000 | $249.00 | $373.50 | $0.012 |
| 50,000 | $399.00 | $598.50 | $0.008 |
| 100,000 | $599.00 | $898.50 | $0.006 |
| 1,000,000 | $2,499.00 | $3,749.00 | $0.0025 |
| 2,000,000 | $3,999.00 | $5,999.00 | $0.0020 |
Teams **entry** $/task is higher than Pro because you are buying seats, shared connections, and SSO — not cheaper tasks.
Tiers also exist at 300k / 400k / 750k / 1.25M / 1.5M / 1.75M (see getting-started §9 or zapier.com/pricing). Above 2M: Sales.
---
## 6. Overflow (pay-per-task)
On paid plans, a toggle decides what happens at the allowance:
| Setting | What happens |
|---------|----------------|
| **On** | Zaps and MCP keep running. Extra tasks bill at **1.25×** the plans base $/task (annual) or **2.5×** (monthly). Hard ceiling: **3×** subscribed tasks, then pause until next cycle or upgrade. |
| **Off** | Everything **stops** at the allowance. |
| **Free** | No overflow. Hits 100 and stops. |
Worked overage: Professional 750 annual → base ≈ $19.99 / 750 = **$0.0267**. Overflow ≈ **$0.0333**/task. Monthly base ≈ $0.0400; overflow ≈ **$0.100**/task. Same usage is ~3× more expensive on monthly overflow than annual overflow.
Enterprise uses an **annual** pool so seasonal spikes do not reset every month.
---
## 7. Other Zapier products (different models)
| Product | Model | Relation to tasks |
|---------|--------|-------------------|
| **Zap workflows** | Task | Core |
| **Zapier MCP** | Same task pool; **2 tasks** per successful execute | Meta-tools free |
| **Zapier SDK** | Beta free; expect tasks later | Consume, not publish |
| **AI by Zapier** | Task × model tier (1 / 3 / 5) | Inside the Zap |
| **Code by Zapier** | Included seconds + 1 task / 30 s extra | Inside the Zap |
| **Tables / Forms** | Plan limits (records, pages, upload size); **0 tasks** when used in Zaps | Separate caps |
| **Agents** | **Activities** (Free 400/mo; paid ~$33.33/mo annual for 1,500). Per-run cap 10 (Free) / 40 (paid). | Does **not** use tasks |
| **Chatbots** | Bot-count tiers (Free 2; paid ≈5 / ≈20) | Does **not** use tasks |
| **Canvas / Copilot** | Included; Free Copilot has a daily message limit | Not a usage meter |
| **Directory integration (us)** | **$0** to publish. Customers Zapier plan pays tasks. | Partner is not billed |
| **White Label / Powered by Zapier / embed** | Usage-based **to the product company**. End users may not need their own Zapier bill. | Sales contract |
| **NLA / AI Actions** | Retired | Do not design around this |
---
## 8. Worked examples (so the variables are visible)
Assume **Professional, billed annually**, and that every named action succeeds. Verae units are **our** meter.
### Example A — Two-step timestamp (Free-capable)
`New file in Drive``Verae: Create Timestamp`
| Volume | Zapier tasks | Fits | Zapier $ (annual) | Verae units |
|-------:|-------------:|------|-------------------|------------:|
| 80 files / mo | 80 | Free | $0 | 80 timestamps |
| 200 | 200 | Pro 750 | $19.99 | 200 |
| 600 | 600 | Pro 750 | $19.99 | 600 → **starter** (500) overflows **us** |
Lesson: the customer can still be on Zapier Free while **we** 402 them. The two meters trip at different points.
### Example B — Production pattern we recommend
`New file` → Filter → `Create Timestamp` → Formatter → write catalog row (Tables = **0** tasks) → Slack
If Slack is the only other third-party action: **2 tasks / file** (timestamp + Slack). Tables write is free.
| Files / mo | Passing filter | Zapier tasks | Cheapest Pro tier | Zapier $ | Verae timestamps |
|-----------:|---------------:|-------------:|-------------------|----------:|-----------------:|
| 1,000 | 20% (200) | 400 | 750 | $19.99 | 200 |
| 1,000 | 100% | 2,000 | 2,000 | $49 | 1,000 → **pro** on our side |
| 10,000 | 100% | 20,000 | 20,000 | $189 | 10,000 → enterprise / contract |
Filter early: 800 of 1,000 files dropped = **0 Zapier tasks and 0 Verae stamps** for those 800.
### Example C — Create and Wait vs hook
- **Wait in the Zap:** 1 task (the wait action). Fine for interactive “give me the certificate now.”
- **Async + Timestamp Completed hook + update row:** 1 task to create + 1 task when the hook fires an action = 2 tasks, but the Zap does not sit open. Prefer this at volume.
Polling `Find Job Status` every minute in a loop is the anti-pattern: each successful search is a task.
### Example D — Same work via Zapier MCP (an agent)
Agent calls: execute Create Timestamp, execute write Sheet, execute Slack.
3 executes × **2 tasks** = **6 tasks / file**, plus any Agent **activities** if they used Zapier Agents.
200 files = **1,200 Zapier tasks** → Pro 1,500 at **$39**/mo — three times the Zapier cost of Example B for the same Verae stamps (200).
**Planning rule:** MCP-shaped clients burn Zapier 2× per hop. Do not price Verae as if the customers only cost is our stamp.
### Example E — AI enrichment in the Zap
`New file` → Standard AI extract metadata (1) → Create Timestamp (1) → Sheet (1) = **3 tasks**.
Swap in Premium AI: **5 + 1 + 1 = 7 tasks**.
1,000 files: 3,000 vs 7,000 tasks → $89 vs $129 on Pro annual.
AI model choice is the customers Zapier bill, not ours — unless we bury AI inside **our** action (we should not).
### Example F — Overflow month
Customer on Pro 750 annual ($19.99). A campaign pushes 1,400 successful timestamp actions (and nothing else).
- Included: 750
- Overflow: 650 × ~$0.0333 ≈ **$22**
- Total Zapier ≈ **$42** that month
- Still under the 3× ceiling (2,250)
If they were on **monthly** Pro 750 ($29.99): overflow 650 × ~$0.100 ≈ **$65** + $30 = **~$95**.
### Example G — White Label (we are the billed party)
If Verae embeds Zapier and Zapier bills **us** per task, then 10,000 customer files × 2 tasks = 20,000 tasks ≈ **$189**/mo (Pro annual list) **plus** our timestamp COGS. That number has to sit in **our** COGS, not the customers Zapier account.
---
## 9. Veraes meter today (so we can place it)
From `verae-zapier-middleware` `PLAN_LIMITS`:
| Verae plan | Timestamps / mo | Verifications | Batch | RPM |
|------------|----------------:|--------------:|-------|----:|
| free | 50 | 50 | no | 30 |
| starter | 500 | 500 | yes, max 10 | 120 |
| pro | 5,000 | 5,000 | yes, max 100 | 600 |
| enterprise | unlimited / contract | contract | yes | 3,000 |
Over-quota → **402** `QUOTA_EXCEEDED`. Batch on free → **403** `PLAN_UPGRADE_REQUIRED`.
These fire **independently** of Zapiers pause / pay-per-task.
---
## 10. How this should shape *our* billing
1. **Never bundle “unlimited Zapier.”** We do not control their task tier, MCP multiplier, or overflow toggle.
2. **Meter what we uniquely do:** accepted timestamp jobs, verifies, maybe stored GB / pin-days / Glacier restores — not Zap steps.
3. **Mirror Zapiers shape if we want familiarity:** plan + included units + optional overage with a ceiling. Customers already understand 402 vs pause.
4. **Do not use Zapier-like 2× MCP pricing on our API.** MCP is Zapiers tax on agent hops. Our HTTP `/zapier/v1/timestamp` should stay **one Verae unit** whether the Zap used 1 task or an agent used 2.
5. **Price batch as a plan gate**, not as “N Zapier tasks.” Zapier will still charge **1 task** for the batch action; we decide whether 100 items cost 1 or 100 of *our* units. Today we count batch size against `batchMaxItems` and timestamp quota.
6. **Hook-friendly packaging:** include enough monthly stamps that the recommended “create + hook + catalog” pattern is cheaper on **our** side than polling.
7. **Three customer motions, three packages:**
- **Directory user** — they pay Zapier + they pay Verae (API key). Our list price must look fair next to ~$0.02$0.03 per Zapier task at Pro entry.
- **MCP / agent user** — they already pay 2 Zapier tasks per hop; keep Verae simple or they will skip us.
- **Embed / White Label** — we may owe Zapier usage; our price to the end user must cover that COGS or we only sell the timestamp and let them bring their own Zapier.
8. **Storage / Peergos / Glacier is a third meter** (see getting-started §10). Do not hide pin-days or restore fees inside “one timestamp.”
9. **Failed Zapier steps are free for them, not for us** if we already accepted the job. Bill on **accepted jobId** (202), not on Zapiers success callback.
10. **Quote two lines** in every proposal: “Your Zapier plan (estimate N tasks)” and “Verae (M timestamps).” Never a single blended number.
### Rough juxtaposition (order-of-magnitude)
At Pro 750 annual, Zapiers included work is about **2.7 cents per task**.
If our Create Timestamp is one Zapier task + one Verae stamp, the customers *Zapier* share of a two-step Zap is ~$0.027. Our stamp should be priced from **our** chain/ops cost, not matched 1:1 to that 2.7¢ — but if we charge **dollars** per stamp while Zapier is **cents** per step, SMB Zaps will feel “Verae-expensive” even when Zapier is the bigger invoice at volume.
---
## 11. Planning checklist
- [ ] For each target Zap, count **billable Zapier actions** (not steps on the canvas).
- [ ] Multiply MCP executes by **2**.
- [ ] Apply AI 1 / 3 / 5 if they enrich in the Zap.
- [ ] Pick the cheapest **Zapier** tier that covers that task count (or overflow math).
- [ ] Count **Verae** timestamps / verifies / batch separately; check 50 / 500 / 5,000 tripwires.
- [ ] If we embed Zapier, put Zapier list price into **our** COGS.
- [ ] Keep Peergos pin / Glacier restore off the timestamp SKU.
- [ ] Re-check [zapier.com/pricing](https://zapier.com/pricing) before any contract; this brief is dated **18 August 2026**.