Replace all display-name occurrences across web pages, Rust source, docs, and Cargo metadata. Update localStorage token key from sq_token to fs_token. Tagline "Klondike Solitaire" retained as genre descriptor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.3 KiB
Ferrous Solitaire — Session Handoff
Last updated: 2026-05-12 — Leaderboard display name shipped (03be4fc). All commits pushed to origin.
Phase 8 closes the self-hosted-server connection arc end-to-end: login/register modal, re-auth on token expiry, account deletion flow, server deployment artifacts (Dockerfile + docker-compose), replay upload on win, web replay player (WASM + HTML/CSS/JS served by the server), leaderboard opt-in/out, and full server integration tests.
Current state
- HEAD locally:
03be4fc(feat: leaderboard custom display name). - HEAD on origin:
03be4fc(fully pushed). - Working tree: clean (only
solitaire-release.jks.bak2untracked — intentional). - Build:
cargo clippy --workspace --all-targets -- -D warningsclean. - Tests: 1300+ passing / 0 failing across the workspace.
- Tags on origin:
v0.9.0throughv0.22.0.
What shipped in Phase 8 (432061c – bd388fe)
| Commit | Summary |
|---|---|
432061c |
Sync setup modal (login/register/connect/disconnect) |
6ce5564 |
Re-auth on expired session + server deployment artifacts |
272d31f |
Account deletion flow + handle_sync_buttons refactor |
bd388fe |
CHANGELOG v0.23.0 documentation |
Also shipped (pre-Phase 8 but post-v0.22.0, already in CHANGELOG):
solitaire_wasmcrate: WASM ReplayPlayer bindings for browser-side replay playback- Server replay API:
POST /api/replays,GET /api/replays/recent,GET /api/replays/:id - Server web UI:
/replays/:idHTML route +ServeDir /webstatic assets - DB migration 002:
replaystable + two indexes - Full server integration tests for replay endpoints
push_replayinsync_plugin(uploads on win, writes share URL into replay history)- Stats panel "Copy Share Link" button reads
share_urlfrom replay history
Open punch list (ordered by priority)
1. Documentation debt (no code)
- CHANGELOG [Unreleased] → v0.23.0 — done this session
- ARCHITECTURE.md update — all 8 gaps closed, bumped to v1.3
- SESSION_HANDOFF.md update — this file
2. Leaderboard wiring gaps
- Best-score auto-post. Done (
303c78a):update_leaderboard_if_opted_incalled from both first-push and merge paths insync.rs; uses SQLiteMIN/MAXin the UPDATE so scores never regress on stale data. - Display name = username. Done (
03be4fc):leaderboard_display_name: Option<String>added toSettings; editor modal in leaderboard panel; persists tosettings.json;handle_opt_in_buttonprefers custom name over username.
3. Security hardening
- Refresh token rotation. Done (
b129664):refresh_tokenstable (migration 003); jti embedded in JWT; rotate-on-use pattern; 3 integration tests. - Sync endpoint rate limiting. Done (
6e6f3ef):UserIdKeyExtractordecodes JWT for per-user identity; falls back to IP; burst 10 / 6 min steady-state; integration test passes.
4. Android validation
- Android Keystore functional test. Done (2026-05-11, Pixel 7 AVD,
Android 14):
load_access_token()exercised viastart_pull; logcat confirmedNotFoundreturned cleanly — no JNI panic. Seedocs/android/PLAYABILITY_TODO.mdP4. - JNI clipboard functional test. Done (2026-05-11): temporary
KEYCODE_Chook confirmedClipboardManager.setPrimaryClip()succeeds on Android 14. Hook reverted. Production path requires Interaction::Pressed + non-nullshare_url. Note:adb shell input tapdoesn't deliver touch events on headless AVD (documented). cargo apk build --libnoisy stderr — upstream cargo-apk bug;--libis the canonical command (CLAUDE.md §15.1, docs/ANDROID.md). No in-repo fix possible.
5. Feature completeness
- Theme importer UI. Done (
613bbf8): "Scan for new themes" button in Settings Appearance section. Shows import path label, scans user_theme_dir() for .zip archives, fires InfoToastEvent per file, refreshes ThemeRegistry. mirror_achievementremoved. Done (549a817): method was a no-op default never overridden and never called; achievements already sync viaSyncPayloadpush. Deleted from trait and blanket impl.- WASM build script. Done (
40d0712):build_wasm.shat repo root documentswasm-pack build --target web, cleans up pkg metadata files, includes dependency guard + install instructions. - Server password reset. Done (
7514684):--reset-password <username>subcommand reads new password from stdin, bcrypt-hashes it, invalidates all active sessions for the user.
5b. Android UX polish (2026-05-12)
-
UX-1 — Modal Done button in gesture zone.
apply_safe_area_to_modal_scrimssystem added toSafeAreaInsetsPlugin(safe_area.rs). Pads everyModalScrimbottom byinsets.bottom / scale. Fires on resource change +Added<ModalScrim>. Verified on device. -
UX-5b — Home mode glyph corruption. Geometric Shapes (U+25xx, absent from FiraMono) replaced with card suits U+2660–2666 in
home_plugin.rs. Affects Zen/Challenge/Daily mode selector buttons at level 5+. -
UX-7 — Help text wrap. Android HUD entry shortened to
"Open menu (Stats, Settings, Profile...)"inhelp_plugin.rs— fits one line. -
BUG-3 — Multi-modal stacking.
handle_menu_buttonnow checksscrims: Query<(), With<ModalScrim>>and guardsspawn_menu_popoverwithscrims.is_empty(). Verified on device: ≡ tap while Stats open does nothing.Note: These 4 fixes are implemented and verified but not yet committed.
6. Testing gaps
- Server 401 → refresh → retry path. Done (
198df75): bothjwt_refresh_on_401_succeeds(pull) andpush_retries_after_401_on_expired_access_token(push) insolitaire_data/tests/sync_round_trip.rs. - WASM winning-replay step-through. Done (
b4ada2a): greedy solver searches seeds 1–200 at test time; steps every move throughReplayPlayer; assertsis_won = trueon the finalStateSnapshot.
ARCHITECTURE.md gaps (for the update pass)
Items missing from the doc:
solitaire_wasmcrate (§2 workspace + §3 responsibilities)- Replay API endpoints (§9 API Reference — 3 new routes)
- Web replay player route (
/replays/:id+ServeDir /web) SyncProvidertrait: 6 added methods- Theme system in Bevy plugin table (§5)
Settingsnew fields:color_blind_mode,high_contrast_mode,reduce_motion_mode,window_geometry,selected_card_back,selected_background- DB migration 002 (§7)
- Update "Last Updated" date
Process notes
- Commit attribution: use
funman300as git user. Co-author line:Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>. - Commit format:
type(scope): descriptionper CLAUDE.md §7. - Never commit without:
cargo test --workspacepassing + clippy clean. - Sub-agents stage/verify only; orchestrator commits.
CARD_PLAN.mdreferenced intheme/module comments but not present in repo. Clean up references or commit the file.- Token-port pattern (v0.20.0): when migrating tokens, walk every concrete artifact downstream — PNGs, SVGs, literals, comments. Three "walked past this" follow-ups in v0.21.0 all had this shape.
Resume prompt
You are a senior Rust + Bevy developer working on Ferrous Solitaire.
Working directory: <Rusty_Solitaire clone path>.
Branch: master. v0.23.0 is the current version (HEAD: 03be4fc). Fully pushed.
READ FIRST (in order):
1. SESSION_HANDOFF.md — this file
2. CHANGELOG.md — [0.23.0] section has full Phase 8 detail
3. CLAUDE.md — unified-4.0 rule set
4. ARCHITECTURE.md — v1.3, fully up to date
5. docs/ui-mockups/ — design system + mockup library
6. docs/android/ — Android setup + build runbook
7. ~/.claude/projects/<this-project>/memory/MEMORY.md
OPEN WORK:
Phase 8 punch list is fully closed. All items verified complete.
Remaining nuisance: `cargo apk build --lib` noisy stderr (cosmetic, non-blocking).
4 Android UX fixes are implemented and verified but NOT YET COMMITTED:
- BUG-3 (hud_plugin.rs): multi-modal stacking guard
- UX-7 (help_plugin.rs): help text wrap on Android
- UX-5b (home_plugin.rs): FiraMono glyph corruption in mode selector
- UX-1 (safe_area.rs): modal Done button in gesture zone
Commit those first, then suggest Phase 9 planning.