feat(catalog): graduated cosmetic ladder + per-session test-unlock

Step 1 — real tiered unlocks (was flat: any credit unlocked skins+iso+3D):
- entitlements DEFAULT_CATALOG + migration 025 graduate the ladder — unlock by
  lifetime credit spend OR subscription tier, whichever first:
    Fancy (generated-skins)       1 credit  / supporter (tier 1)
    Iso   (iso-dungeon)          10 credits / premium   (tier 2)
    3D    (kenney-3d-characters) 25 credits / operator  (tier 3)
- Migration 025 UPDATEs the already-seeded 024 rows (idempotent).
- Tests updated to assert the ladder (1cr -> Fancy only; 10 -> +Iso; 25 -> all).

Step 2 — test the premium modes without paying:
- renderModes: ?unlock=1 (sticky via localStorage) flips RENDER_MODE_TEST_UNLOCKS
  for THAT browser only, so Fancy/Iso/3D are all clickable; ?unlock=0 turns it off.

Suite 57 suites / 414 tests green.
This commit is contained in:
jwinterm
2026-07-11 07:24:26 -04:00
parent e7fe16fcaa
commit 1b59d2f927
7 changed files with 45 additions and 14 deletions
+9 -2
View File
@@ -16,9 +16,16 @@
];
RK.entitlements = RK.entitlements || { premium: false, level: 'free', packs: {} };
// Production QA switch: set to true to temporarily bypass premium render-mode gating for
// testing. Default false — premium modes (Fancy/Iso/3D) gate behind pack entitlements.
// Per-session QA bypass for premium render-mode gating (Fancy/Iso/3D). Default OFF. A tester
// opts IN for their own browser only via ?unlock=1 (persisted) — nobody else is affected:
// ?unlock=1 -> on (sticky) ?unlock=0 -> off
RK.RENDER_MODE_TEST_UNLOCKS = false;
try {
var q = (root.location && root.location.search) || '';
var m = /[?&]unlock=([01])/.exec(q);
if (m) { try { root.localStorage.setItem('rk_unlock_all', m[1]); } catch (_) {} }
RK.RENDER_MODE_TEST_UNLOCKS = (root.localStorage && root.localStorage.getItem('rk_unlock_all') === '1');
} catch (_) { /* no location/localStorage */ }
RK.renderModeTestUnlocks = function () { return RK.RENDER_MODE_TEST_UNLOCKS === true; };
RK.modeMeta = function (id) {