- analytics: getMapAnalytics queried map.name but the map_library column is
display_name (no name column) — every map-analytics call 500'd. Fixed select
+ groupBy to map.display_name.
- setup: guard ENCRYPTION_KEY length before AES-256-GCM createCipheriv — an
unset key crashed bare-metal setup with an opaque 'Invalid key length' 500;
now returns a clear 503. Also stop falsely marking bare-metal connected on
completeSetup; leave offline until the agent's first heartbeat.
- webstore: public checkout returned a FAKE PayPal order token + sandbox URL
that resolves to nowhere. Refuse honestly with 503 (payments coming soon)
instead of faking a transaction.
- store: module purchase wrote a fake txn_<ts> implying a charge; record it
honestly as a free Beta grant (transaction_id=beta-free-grant, amount 0).
Backend tsc green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>