App Store review 1.2.2: the reviewer's store got a test charge, but billing.check ran with isTest:false and ignored it, so the approved plan never registered. Checks now count test subscriptions too, and cancel uses each subscription's own test flag. Uninstall resets the stored plan to free (Shopify cancels the subscription), so a reinstall asks for approval again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
billing.request throws a 401 with the approval URL in X-Shopify-API-Request-Failure-Reauthorize-Url for App Bridge to follow, but a React Router form submission rendered it as an error page. The action now returns the URL and the page opens it at the top level. Invalid-session retries are still rethrown for App Bridge.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /auth/login no longer asks for a myshopify domain (App Store 2.3.1). With
?shop= it still hands off to OAuth; otherwise it points to Shopify.
- Billing API charges are test charges outside production and on partner
development stores (shop.plan.partnerDevelopment), so reviewers can pick a
paid plan. Real shops are charged as before.
- SCREENCAST.md matches the recording.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shopify deletes an app's validation and delivery/payment customizations on
uninstall. Datewise now remembers which ones were on (settings.checkoutFunctions,
kept in sync with Shopify whenever Settings loads) and switches them back on
when a shop reinstalls.
LISTING.md and alt text updated to what the listing form accepted (5 features,
20-char search terms, 64-char alt text, no "plan" outside pricing).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- brand/make_screenshots.py frames raw shots at 1600x900 with captions + alt text
- brand/LISTING.md: introduction, details, features, search terms, testing steps
- bookings filters no longer overflow; footer reads '1 booking'; no empty pager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DataAccessLog records bookings list/view/export and run-sheet views (actor, action,
target, time); pruned after 12 months by the worker; migration 0003.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ensureShop: concurrent installs reuse the row created by the other request (P2002)
- order tagging and booking metafield log Shopify userErrors instead of failing silently
- widget keeps a readable 760px width in full-width theme sections
- setup guide links to Shopify's pickup settings so checkout offers pickup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- storefront applied maxLocations to the first locations by priority, even switched-off
ones, so a Starter shop whose enabled location wasn't first got no methods
- switching on a location beyond the plan limit now explains why instead of being ignored
- widget shows a message (en/fr) when no method is available and clears aria-busy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Prisma extension seals booking name/email/phone/address and waitlist contacts with
AES-256-GCM on write and opens them on read (incl. nested reads)
- keyed-hash columns for exact email/phone lookups (privacy webhooks, booking search,
waitlist de-duplication); migration 0002
- tests prove only ciphertext is stored; privacy/terms/SECURITY.md updated to match
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- brand/: 1200x1200 full-bleed app icon, 1600x900 feature image, transparent logos,
favicons, guidelines (palette, type, usage) and the build script
- / is now a branded landing page with no shop-domain form (App Store 2.3.1)
- /privacy and /terms describe Datewise's actual data handling and sub-processors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
activateAppId pointed at a non-existent 'datewise-embed' handle; the embed is 'embed'.
Adds an addAppBlockId link that places the scheduler block on the cart template.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>