fix(data): enforce 32-char display_name limit at sync client boundary (M-22)

opt_in_leaderboard in sync_client.rs was passing display_name through
as-is, relying solely on the engine's .chars().take(32) call upstream.
Add the truncation in the sync client so any caller is protected, and
also apply it at save-time in handle_display_name_confirm so settings
never stores an over-length name.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-17 21:29:38 -07:00
parent 2301cc65d3
commit 2e52f544f1
2 changed files with 4 additions and 1 deletions
+3
View File
@@ -309,6 +309,9 @@ impl SyncProvider for SolitaireServerClient {
async fn opt_in_leaderboard(&self, display_name: &str) -> Result<(), SyncError> { async fn opt_in_leaderboard(&self, display_name: &str) -> Result<(), SyncError> {
let token = self.access_token()?; let token = self.access_token()?;
let url = format!("{}/api/leaderboard/opt-in", self.base_url); let url = format!("{}/api/leaderboard/opt-in", self.base_url);
// Enforce the server's 32-char column limit at the client boundary so
// the server never receives an over-length name regardless of caller.
let display_name: String = display_name.chars().take(32).collect();
let resp = self let resp = self
.client .client
+1 -1
View File
@@ -746,7 +746,7 @@ fn handle_display_name_confirm(
return; return;
} }
if let Some(mut settings) = settings { if let Some(mut settings) = settings {
let trimmed = buf.0.trim().to_string(); let trimmed: String = buf.0.trim().chars().take(32).collect();
settings.0.leaderboard_display_name = if trimmed.is_empty() { settings.0.leaderboard_display_name = if trimmed.is_empty() {
None None
} else { } else {