Skip to content

docs(sync): require the positive sync head on the first push - #249

Merged
basit3407 merged 5 commits into
quran:mainfrom
haroon0x:docs/sync-first-push-head
Nov 5, 2026
Merged

basit3407 merged 5 commits into
quran:mainfrom
haroon0x:docs/sync-first-push-head

Conversation

@haroon0x

@haroon0x haroon0x commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Summary

The Sync tutorials told clients to push their first mutation with lastMutationAt=-1 and to read -1 back from GET /v1/sync as a "first-sync state". Both bundled specs say the opposite:

  • POST /v1/sync → lastMutationAt description: "The effective sync head returned by the get mutations endpoint. It includes virtual resources such as the default Favorites collection, so even a new user must send the positive timestamp returned by GET rather than -1. A stale or different value will be rejected." (openAPI/user-related-apis/v1.json, openAPI/user-related-apis/pre-live/v1.json)
  • GET /v1/sync → response lastMutationAt: "Effective sync head, including virtual resources such as the default Favorites collection."
  • The GET lastMutationAt query parameter (used for pagination) has minimum: 0, and the 409 examples no longer contain the First sync detected. Please use lastMutationAt=-1 for initial sync. variant.

A client that follows the current docs would get a 409 OutOfSyncError on its very first push.

Changes

docs/tutorials/sync/getting-started.mdx

  • Describe lastMutationAt as the push precondition (the server-assigned sync head) and state explicitly that the pull cursor is mutationsSince.
  • Rewrite "First Sync Behavior", the flowchart and Steps 1–3 around the positive head: a new user already has one because the head includes virtual resources such as the default Favorites collection.
  • Document the continuation head that GET /v1/sync pagination requires: page 2+ sends the lastMutationAt returned by page 1, and a changed head returns 409 and restarts the pull.

docs/tutorials/sync/handling-conflicts.mdx

  • Replace the "First-Sync Variant" (and its retired error message) with a "No First-Sync Exception" note: the same head rule applies to the first push, and -1 returns the ordinary OutOfSyncError.

tests/sync-docs-last-mutation-at.test.cjs (new)

  • Pins both specs to "positive head, not -1" and both tutorials to the corrected wording, so the docs cannot drift back.

Testing

node --test tests/sync-docs-last-mutation-at.test.cjs
# ✔ the pinned sync specs require the positive sync head, not -1
# ✔ the sync tutorials do not document a -1 first-push sentinel
# ✔ the sync getting-started guide explains that the first head is positive

The full node test suite also runs in CI (scripts/run-tests.cjs); the docusaurus-dependent tests need yarn install, which this change does not affect.

Notes for reviewers

  • The committed generated page docs/user_related_apis_prelive/sync-local-mutations.api.mdx still contains the old first-sync 409 example; it is regenerated by yarn gen-all at build time and was not hand-edited here.
  • I could not exercise the endpoint itself (pre-live OAuth credentials), so the fix is derived from the pinned specs plus the SDK's User Sync contract, which documents the same model (@quranjs/api README: "lastMutationAt must be the exact current sync head").

The sync tutorials told clients to send `lastMutationAt=-1` for a user's
first mutation and to read `-1` as a "first-sync state". Both pinned specs
say the opposite: the head returned by GET already includes virtual
resources such as the default Favorites collection, so a new user has a
positive head, and `-1` is rejected with a 409 OutOfSyncError.

- describe `lastMutationAt` as the push precondition, separate from the
  `mutationsSince` pull cursor
- rewrite the first-sync table, flowchart and steps around the positive head
- document the page-1 continuation head that GET pagination requires
- drop the retired "First sync detected..." error variant
- add a test pinning both specs and both tutorials to this contract
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T05:00:07.854749Z 78dde17 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9316f18d8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/tutorials/sync/getting-started.mdx Resolved
haroon0x and others added 3 commits November 5, 2026 00:26
The guide says Sync is pre-live only, but the pre-live spec does not declare
a `lastMutationAt` parameter on GET /v1/sync; only the production spec does.
Scope the pagination rule accordingly: keep the same `mutationsSince` across
pages, and use the page-1 continuation head where the deployment accepts it.
Production rejects GET /v1/sync page 2+ without the page-1
lastMutationAt, or with a different one, with 409 OutOfSyncError
(verified live). Describe it as required rather than optional.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Production GET page 2+ requires the page-1 head; a changed head means
  restart the pull, a missing head is a request bug (no restart loop).
- Pre-live does not accept lastMutationAt on GET: compare each page's
  returned head with page 1's instead.
- Keep mutationsSince, resources and limit fixed across pages.
- State the rule once in Step 2 and link to it; mention the GET
  continuation use in Key Concepts.
- offline-first-patterns: push with the head returned by the pull, not
  the mutationsSince cursor.
- handling-conflicts: add the mid-pull 409 case and use the pull cursor,
  not the head, as mutationsSince when recovering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@basit3407

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 0a9fcf12f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Resolve conflicts with quran#244 (Sync live in production): keep main's
first-sync wording and cursor model, keep this PR's pagination
continuation rules and mid-pull 409 case. Drop the 'not the pull
cursor' note, which contradicted main, and update the PR's test to
main's wording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@basit3407

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 78dde1707f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@basit3407
basit3407 merged commit 0184525 into quran:main Nov 5, 2026
1 check passed
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