persistTopicProgressUpdate method
Persist a user_topic_progress upsert through OutboxedWrites.
updateProgress already uses onConflict: 'user_id, topic_id' so
the replay is naturally idempotent. LWW within a single topic is
by drain order (created_at ordering in the outbox).
Implementation
Future<void> persistTopicProgressUpdate(
String topicId,
Map<String, dynamic> updates,
) async {
final supabase = ref.read(supabaseDatasourceProvider);
final outboxed = ref.read(outboxedWritesProvider);
await outboxed.persistUpdate(
table: 'user_topic_progress',
localId: topicId,
payload: {'topic_id': topicId, ...updates},
supabaseCall: () => supabase.updateProgress(topicId, updates),
);
}