From 7d1393b90cd57e1d280c9d52a52b5c0aa3a1e3c2 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Wed, 30 Sep 2026 18:07:42 +0400 Subject: [PATCH] docs: only a store's verdict about a purchase is a plain refusal --- plans/2026-09-24-badge-buy-in-browser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plans/2026-09-24-badge-buy-in-browser.md b/plans/2026-09-24-badge-buy-in-browser.md index d0a4b9c18f..826d8766a5 100644 --- a/plans/2026-09-24-badge-buy-in-browser.md +++ b/plans/2026-09-24-badge-buy-in-browser.md @@ -80,7 +80,7 @@ Getting the URL to an app that is already running is the part that half exists. The browser lane needs nothing. The store lane needs `purchaseBadge` to accept a store receipt and verify it — Apple's JWS offline, Google's token through the Publisher API, per `docs/protocol/badges-rpc.md`. No provider adapter for either exists today. -Two properties matter more than the plumbing. It must be idempotent per signing key, since the app will retry. And an unknown or invalid token must be a plain refusal, not a retryable error — Android has no local verification, so tampered clients will send junk tokens as a matter of course, and a retryable answer would leave the worker grinding on one that can never become valid. +Two properties matter more than the plumbing. It must be idempotent per signing key, since the app will retry. And only a store's verdict about a purchase may be a plain refusal: the client consumes a purchase answered `receipt_invalid`, so a store that has merely not answered — or that does not yet know a token it has just issued — must be answered retryably, or a paid badge is thrown away. Junk tokens from tampered clients are the cheap side of that trade: each costs one request per client trigger, nothing loops on the service, and Play refunds an unacknowledged purchase after three days. `docs/protocol/badges-rpc.md` has the classes. `badges-rpc.md` also specifies `getBadgeCatalog` and `getBadgeInvoice`. Neither is needed by anything here and neither should be built: the page owns the catalog and the invoice.