diff --git a/SVSim.Database/Models/ViewerBattlePassClaimEntry.cs b/SVSim.Database/Models/ViewerBattlePassClaimEntry.cs
new file mode 100644
index 0000000..36355b4
--- /dev/null
+++ b/SVSim.Database/Models/ViewerBattlePassClaimEntry.cs
@@ -0,0 +1,17 @@
+using SVSim.Database.Common;
+using SVSim.Database.Enums;
+
+namespace SVSim.Database.Models;
+
+///
+/// Per-claim record. Presence of a row = is_received: true on the wire reward.
+/// Unique on (ViewerId, SeasonId, Track, Level).
+///
+public class ViewerBattlePassClaimEntry : BaseEntity
+{
+ public long ViewerId { get; set; }
+ public int SeasonId { get; set; }
+ public BattlePassTrack Track { get; set; }
+ public int Level { get; set; }
+ public DateTimeOffset ClaimedAt { get; set; }
+}
diff --git a/SVSim.Database/Models/ViewerBattlePassProgressEntry.cs b/SVSim.Database/Models/ViewerBattlePassProgressEntry.cs
new file mode 100644
index 0000000..b935f51
--- /dev/null
+++ b/SVSim.Database/Models/ViewerBattlePassProgressEntry.cs
@@ -0,0 +1,18 @@
+using SVSim.Database.Common;
+
+namespace SVSim.Database.Models;
+
+///
+/// Per-viewer-per-season progress: gauge total, premium flag, weekly cap bucket.
+/// Lazy-created on first /battle_pass/info read. Unique on (ViewerId, SeasonId) per
+/// memory project_owned_collection_unique_index.
+///
+public class ViewerBattlePassProgressEntry : BaseEntity
+{
+ public long ViewerId { get; set; }
+ public int SeasonId { get; set; }
+ public int CurrentPoint { get; set; }
+ public bool IsPremium { get; set; }
+ public int WeeklyPoints { get; set; }
+ public DateTimeOffset? WeeklyPeriodStart { get; set; }
+}