Skip to content

docs: align device sync protocol page with the server implementation - #149

Open
sdornan wants to merge 5 commits into
mainfrom
claude/new-session-iabs8x
Open

sdornan wants to merge 5 commits into
mainfrom
claude/new-session-iabs8x

Conversation

@sdornan

@sdornan sdornan commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

docs/developers/device-sync-protocol.md didn't match what the RomM server implements. A client built from the old page would fail against a real server. This PR rewrites the page to match the backend (backend/endpoints/device/, backend/endpoints/sync/, backend/endpoints/saves.py, backend/endpoints/play_sessions.py and their response schemas), including the sync changes from rommapp/romm#4670, #4674, #4768 and #4789.

Changes

  • Authentication: explains that both Client API Tokens and web sessions (cookie plus CSRF) work, and replaces the scope table with the actual scope for each endpoint. For example, POST /api/play-sessions needs roms.user.write, not me.*. Passing device_id to the save endpoints also needs a devices.* scope, or the call returns 403.
  • Device registration: the real body fields (mac_address, client, client_version, sync_config, capabilities, allow_existing, allow_duplicate, reset_syncs, with no paths), and the real sync_mode values (api, file_transfer, push_pull). It explains how matching works (mac_address, then hostname + platform), the 200/201/409 responses, and the { device_id, name, created_at } response with a string UUID device_id.
  • Negotiate:
    • Request: the flat saves[] + rom_ids shape with an MD5 content_hash, pairing on (rom_id, slot), and the error codes (400/404).
    • Response: an integer session_id, action instead of type, no_op, the new delete action, save_id, and the total_* counts including total_delete.
    • Removes the destination/source/dest_path/resolution fields, which don't exist.
    • Every negotiate opens its own session. A session nobody completes is marked failed by a scheduled cleanup after 24 hours.
  • Moving bytes (new section): upload with overwrite/autocleanup/content_hash and the 409 guard, PUT update, download with optimistic, and the /downloaded confirmation with its optional content_hash.
  • Complete session: start_time/end_time/duration_ms/save_slot, the response shape, the 404/400 cases (an expired session can still be completed), and the standalone /api/play-sessions alternative.
  • Briefly mentions the session list/detail and push-pull endpoints.

It's merged with main (the humanize pass), so there are no conflicts. Frontmatter, title and "See also" links are kept. The page passes prettier and markdownlint with the repo's Trunk configs, and mkdocs build --strict succeeds.

AI disclosure

This change was written with AI assistance (Claude Code), working from a comparison of the page against the RomM server source. Please review it against the backend before merging.

🤖 Generated with Claude Code

https://claude.ai/code/session_013q3PdG4Zfn6QWeBCRnC1sm
https://claude.ai/code/session_016jZ2WEQAFScfBv7UGUscNZ

sdornan and others added 4 commits September 25, 2026 03:04
Correct scopes, device registration fields and response, negotiate
request/response shapes, and session completion payload. Document the
save upload/download/confirm endpoints and list RomM Desktop as a
reference client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013q3PdG4Zfn6QWeBCRnC1sm
…claude/pr-149-alignment-45er1r

# Conflicts:
#	docs/developers/device-sync-protocol.md
Negotiate can now return a `delete` action (with `total_delete`) when a
slot the device still holds was emptied on the server, and `download`
also covers a device holding a removed version. Sessions belong to one
launch rather than being cancelled by the next negotiate, and a session
the 24-hour cleanup expired can still be completed.

Also documents the `content_hash` baseline on upload, update and
download confirmation, the `capabilities` registration field, the 409
from `allow_existing: false`, how device matching actually works, and
the extra devices scope needed when passing `device_id` to the save
endpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jZ2WEQAFScfBv7UGUscNZ
@sdornan
sdornan changed the base branch from main to docs/retired-folder-keys-accepted September 28, 2026 14:50
@sdornan
sdornan changed the base branch from docs/retired-folder-keys-accepted to main September 28, 2026 14:50
@sdornan
sdornan marked this pull request as ready for review September 28, 2026 14:51
Copilot AI lite review requested due to automatic review settings September 28, 2026 14:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Address the documented authentication, scope, registration, and endpoint behavior gaps.

Review effort: Lite
Findings: 3 Medium severity

Open (3)
What changed in this PR

Updates the device sync protocol documentation to match the server’s current API.

Changes:

  • Documents authentication, registration, scopes, and negotiation.
  • Adds transfer, confirmation, deletion, and session-completion workflows.
  • Describes push-pull synchronization and related endpoints.
File Summary
docs/​developers/​device-sync-protocol.md Rewrites the device sync protocol reference.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/developers/device-sync-protocol.md Outdated
Comment thread docs/developers/device-sync-protocol.md Outdated
Comment thread docs/developers/device-sync-protocol.md
Session-authenticated clients need the romm_csrftoken cookie echoed in
an X-CSRFToken header, so name both instead of pointing at a page that
does not. A device-scoped slot upload also returns 409 when the device
has no baseline for the slot's latest save, including its first upload
to a slot another device filled. The push-pull endpoint needs
devices.write and was missing from the scope table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jZ2WEQAFScfBv7UGUscNZ

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants