0.2.0: webhook mode, hardening, and a storefront overhaul
The theme of this release: the default stack stays at zero infrastructure,
and everything around it got faster, safer, and easier to audit.
Opt-in webhook mode: delivery in seconds
Default fulfillment is unchanged. A scheduled Action polls Stripe; no server,
no webhook endpoint, nothing new to run. Webhook mode is for sellers who want
the invite to land in seconds instead of minutes:
- Two interchangeable single-file relays, dependency-free:
webhook-mode/relay-cloudflare.mjs
(Cloudflare Workers free tier) and
webhook-mode/relay-node.mjs(Val Town free
tier, or any Node ≥ 20 box behind TLS). - The relay verifies the Stripe webhook signature (HMAC-SHA256, constant-time
compare, 5-minute replay window) and fires arepository_dispatch. It
holds no Stripe API key, does no fulfillment, and forwards no buyer data.
Fulfillment truth still comes from Stripe's API through the normal poller
logic, so a forged or replayed webhook can at worst trigger an empty run. - The poll stays on as the safety net: whichever fires first delivers, the
other no-ops. An optional heartbeat workflow catches cron drift. - Setup is ~10 minutes:
webhook-mode/README.md.
Full walkthrough and threat model in
docs/instant-delivery.md. The signature
verification is covered by
scripts/test/dispatch.test.js:
known-good vector passes; tampered payload, forged signature, and stale
timestamp are rejected.
Hardening
- GitHub Actions pinned to full commit SHAs across the deploy workflow and
the setup templates (supply chain). - Every config-authored URL is escaped when written into an HTML attribute,
including the buy-buttonpayment_linkhref. Covered by tests. - Markdown renderer: image
srcattributes escaped, rejected URL schemes
surfaced instead of silently passed through, safety tests added. - Fulfillment ledger: dedup guard by ref, so concurrent runners (poll +
webhook racing) can't double-append a sale. - Org-wide security policy
with private vulnerability reporting enabled on this repo, plus
CONTRIBUTING
and CODE_OF_CONDUCT.
Storefront overhaul
standtheme modernized: coin-drop hero mark, ticket-style product cards,
ruled sections, unified logo/favicon geometry, dark-aware accents.- SEO plumbing, all at build time (no client JS): Open Graph/Twitter cards,
JSON-LD for the store, products, and guide articles, sitemap with
lastmod + priority, and an accessibility pass. - Positioning broadened to everyone selling to buyers with GitHub accounts.
- Two guides published:
Deliver digital products through GitHub
and Lemon Squeezy vs Gumroad vs DIY (2026).
Fee claims across the site were re-checked against Gumroad's and Lemon
Squeezy's published schedules (July 2026) and corrected where they had
drifted. - The live demo store now runs a two-product catalog, so multi-product
fulfillment is exercised in production, not just supported in theory.
Trust surface
- The full
terminaltheme from Pro is published in this repo
(themes/terminal/) as an auditable sample, alongside a
public evidence doc. Audit the code standard before
buying anything. - The Pro page now says plainly who shouldn't buy it.
- Stability promise in the README:
store.config.json, product frontmatter,
and the fulfillment grant format are stable. Breaking changes only in a
major version, with an UPGRADING note and a migration path.
Fixes
- Markdown renderer: inline formatting now works across wrapped source lines
(bold spanning a line break used to render literal**), and list items
with wrapped source lines stay inside their<li>. Regression tests for
both. - New
support_emailconfig key so the bot's acknowledgement messages carry
a real contact address.
48 tests passing across the core and dispatch suites (npm test).