Skip to content

0.4.0: invitations that do not expire, and subscriptions

Latest

Choose a tag to compare

@LucideLarp LucideLarp released this 20 Jul 18:19

Two capabilities that change what you can sell, and one that stops you losing a sale you already made.

Invitations no longer expire out from under a buyer

GitHub expires an unaccepted repository invitation after seven days. Until now that meant a buyer who did not open the email lost what they paid for, permanently, while Stripe said paid, the ledger said delivered and the run was green.

scripts/renew-invites.js re-issues a pending invitation at six days, which restarts GitHub's clock. Three renewals maximum with a 24 hour cooldown, so a buyer gets about three weeks of open door and never an endless stream of email. When it gives up it says so in a line your monitoring can grep, rather than going quiet.

It runs as a step inside the fulfillment job you already have, so it costs no additional Actions minutes. The arithmetic is in docs/setup.md section 6.

Refunds are respected structurally. --revoke owner/repo:username removes access, deletes any pending invitation, and records the revocation permanently. Renewal refuses anyone on that list, and the planner refuses to run at all if it cannot read the list, rather than assuming nobody was revoked.

Subscriptions, opt-in

If you point a fulfillment grant at a recurring Stripe price, buyers were already delivered correctly. What did not happen was anything when the subscription ended.

scripts/reconcile-subs.js closes that. Every Stripe subscription status maps to a documented action, past_due is never treated as a lapse because Stripe is still retrying the card, and there is a configurable grace period after a genuinely terminal state.

Three properties worth knowing before you turn it on:

  • It is off unless you add a subscriptions block. A store without one behaves exactly as before, and scripts/fulfill.js is byte for byte unchanged from the previous release, so one-time selling cannot have regressed.
  • Reporting mode is the default. It tells you what it would revoke and revokes nothing until you set enforce: true.
  • It only ever revokes grants it recorded itself. Sellers, collaborators, one-time buyers and anyone who had access before you enabled it are out of scope by construction, not by a check that might miss.

There is also a circuit breaker: a pass that would revoke an unusual share of your customers refuses and alarms instead.

Treat enforcement as new. Run it in reporting mode for a while first, which is what that mode exists for.

Honest limit, stated in docs/subscriptions.md: removing a collaborator stops future pulls, it does not claw back what was already cloned. A lapsed subscriber keeps the last version they pulled. What they lose is updates.

A fifth theme

atrium joins terminal, editorial, brutalist and midnight. One flush left axis, a single spacing unit, one colour used with conviction, one short entrance and then stillness. The other four were reworked, and terminal was shipping another theme's theme-color, so a light mode browser painted the wrong chrome around a dark page.

Theme previews are sized for the box they actually occupy now, lossless, about 21 percent lighter.

Also

The docs are on the store as real pages, and their headings have anchors, so docs/setup.md's own internal links resolve instead of going nowhere. Fragment links are checked by a test.

241 tests, up from 91 two releases ago. Anything guarding money or access is mutation checked: the guard is broken deliberately and the test has to go red, because a test that cannot fail proves nothing.