web checkout: fail-closed CTA -> OIDC PKCE -> shop -> redemption

- app-config.js: public config placeholder (all null/false -> INERT). Operations
  populates OIDC client + shop tenant + checkout URL at deploy; no secrets.
- checkout.js: Authorization Code + S256 PKCE (public client, no secret), state CSRF
  guard, token in sessionStorage, code/state scrubbed from URL. Resolves premium via
  the ledger's per-user /me/entitlements (user's own OIDC token, never the shared
  read token) and sets window.SUCH_APP.premium for WebBillingManager. Redemption also
  resolves on page reload / next login (crypto is webhook-driven).
- index.html: load config+checkout in <head>; CTA calls SUCH_APP_startCheckout, else
  falls through to the store links (fail-closed). Store/itch buttons unchanged.
This commit is contained in:
jwinterm
2026-08-01 10:34:19 -04:00
parent 96e071350c
commit c5dcf5cd2b
3 changed files with 167 additions and 2 deletions
+10 -2
View File
@@ -10,6 +10,11 @@
<!-- Google AdSense — auto ads enabled at account level -->
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2501747033825166"
crossorigin="anonymous"></script>
<!-- Fail-closed web-app → checkout wiring. Inert until Operations populates
app-config.js (OIDC client + shop tenant); no secrets. -->
<script src="app-config.js"></script>
<script src="checkout.js"></script>
</head>
<body>
@@ -30,10 +35,13 @@
</div>
<div id="nag-store-links">
<!-- PRIMARY: our own website sales funnel -->
<!-- PRIMARY: real checkout when configured; else falls through to the apex
marketing site. checkout.js returns true when it starts OIDC login (we
then preventDefault); false → the href proceeds (fail-closed). -->
<a href="https://bauhausecho.com"
target="_blank" rel="noopener noreferrer"
class="nag-btn nag-btn-primary">
class="nag-btn nag-btn-primary"
onclick="return !(window.SUCH_APP_startCheckout &amp;&amp; window.SUCH_APP_startCheckout())">
Get the Full Game ▸
</a>