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
+4 -2
View File
@@ -15,17 +15,19 @@ const DEFAULT_CATALOG = Object.freeze({
id: 'roguelike-interior', label: 'Kenney Roguelike Interior', kind: 'render-pack',
projection: 'topdown', tier: 0, unlockMinCredits: null, grantOnly: false, premium: false
}),
// Graduated ladder — unlock by lifetime credit spend OR by subscription tier, whichever comes
// first: Fancy(skins) at 1 credit / supporter, Iso at 10 / premium, 3D at 25 / operator.
'generated-skins': Object.freeze({
id: 'generated-skins', label: 'Premium Generated Skins', kind: 'render-pack',
projection: 'topdown', tier: 1, unlockMinCredits: 1, grantOnly: false, premium: true
}),
'iso-dungeon': Object.freeze({
id: 'iso-dungeon', label: 'Kenney Isometric Dungeon', kind: 'render-pack',
projection: 'iso', tier: 1, unlockMinCredits: 1, grantOnly: false, premium: true
projection: 'iso', tier: 2, unlockMinCredits: 10, grantOnly: false, premium: true
}),
'kenney-3d-characters': Object.freeze({
id: 'kenney-3d-characters', label: 'Kenney Animated 3D Characters', kind: 'render-pack',
projection: '3d', tier: 1, unlockMinCredits: 1, grantOnly: false, premium: true
projection: '3d', tier: 3, unlockMinCredits: 25, grantOnly: false, premium: true
})
});