Repository navigation
docs(domain): add the Sync bounded context - #1297
Merged
github-actions[bot] merged 1 commit intoOct 15, 2026
Merged
github-actions[bot] merged 1 commit into
github-actions[bot] merged 1 commit into
Conversation
Sync had no place in the domain model although Backlog.Modules.Sync owns pairing, device tokens, owner scope and the replica protocol. Adds .devbook/domain/sync/ as a Supporting context, moves the pairing vocabulary, feature and requirements there from Tasks, and gives the context map its Sync node, edges and published-language row. Decision taken without asking: Supporting subdomain, Open Host Service upstream of Tasks, Sessions and Devbook, with the pairing language moved out of Tasks; the alternative is named in the pull request. Refs #762 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #762
Summary
Adds Sync to the domain model as a bounded context. New
.devbook/domain/sync/withcontext.md(boundary, and thesyncfeature-flag chapter that mergeddevice-pairing,task-syncandsession-sync),domain.md(Device and Pairing Code aggregates, the Change Precedence domain service, the cursor and identity value objects),domain.invariants.md(constant-time secret checks, one-use pairing codes, owner scope, the push cap — each withEnforced at:and its tests),model.md,features.mdandrequirements.md. Owner, Pairing code, Registration credential, Device token and the "Pairing a device" feature and requirements move there from Tasks; Tasks keeps Device and Tombstone. The context map gains the Supporting Sync row, a Sync node with labelled edges and a published-language row; the dependencies chapters of Inbox, Tasks, Sessions and Devbook, the building-block view,tech/desktop.mdand the README follow. No file undersrc/ortests/changes. This also settles thesyncrow of drift issue #896, which stays open for its other keys.Decision taken without asking (follow it, or ask for the alternative)
Question. How should Sync enter the domain model? Three choices: (1) its subdomain type; (2) the relationship pattern on each edge; (3) which DomainModels types are aggregates. Under (3), Tasks' domain.md, features.md and requirements.md currently own the pairing vocabulary (Owner, Pairing code, Registration credential, Device token, the 'Pairing a device' feature and its requirements), so the question includes whether those move.
Chosen. (1) Sync is a Supporting subdomain. It is built in-house (ADR 0005 rejected off-the-shelf sync) and its precedence and capture-document rules are tailored to Backlog's local-first model, but it is not what makes the product different. (2) Sync is upstream to Tasks, Sessions and Devbook as an Open Host Service with a Published Language: the replica protocol, as DTOs in Backlog.Modules.Sync.Abstractions. Each downstream context reaches it through a Backlog.Infrastructure.Sync adapter and never sees inside the documents. Inbox keeps its existing Customer/Supplier edge (Inbox is the customer of the intake channel, ADR 0009). (3) Device and Pairing Code are aggregate roots. Task and Annotation Change Precedence is a domain service. OwnerId, DeviceId, OwnerScope, SyncCursor, the three replica cursors and Session Record Key are value objects. Owner, Pairing code, Registration credential and Device token, plus the 'Pairing a device' feature and requirements, move from Tasks to Sync. Device (the shared-kernel machine identity cited by DeviceIdentity.cs) and Tombstone stay in Tasks. No new ADR.
Alternative. Classify Sync as Generic, and leave the pairing vocabulary, feature and requirements in Tasks. In that version the Sync context would hold only the replica mechanics (cursors, precedence, batch caps) and point back at tasks/domain.md for Owner, Pairing code, Registration credential and Device token.
Why the choice. The pairing rules are enforced only in Backlog.Modules.Sync: RedeemPairingCodeCommand, Sha256CredentialHasher and the OwnerScope threading. Only Sync's tests prove them (DevicePairingTests). Tasks code never touches a pairing code or a credential, so keeping those terms in Tasks would leave its language describing rules it does not own. The issue itself asks for the invariants and requirements to live in the Sync context. Supporting rather than Generic: the map has no Generic context so far, Sync is built in-house rather than bought, and it carries Backlog-specific rules (capture as a document kind, the annotation container, tombstone-wins-on-tie) that an off-the-shelf product would not supply. Under devbook-arc42.md, ownership and the boundary go in the context chapter, so no ADR is opened.
To follow the alternative instead. Taking the alternative would change three things. First, the context-map row would read Generic. Second, sync/domain.md, sync/features.md and sync/requirements.md would drop the moved terms, the 'Pairing a device' feature and its requirements, and link to them in Tasks instead; tasks/domain.md, tasks/features.md and tasks/requirements.md would stay as they are. Third, .devbook/tech/desktop.md and .devbook/arc42/05-building-block-view.md would need no re-pointing. The README rewrite, the inbox/dependencies.md fix, the new folder and the context-map node and edges would stay the same either way.
Acceptance criteria
Testing
cd "D:/iswp/762-sync-bounded-context" && dotnet build Backlog.WithoutAppHeads.slnf --configuration Release -p:TreatWarningsAsErrors=true && dotnet test --solution Backlog.WithoutAppHeads.slnf --no-build --configuration Release --max-parallel-test-modules 1 --parallel none --results-directory <scratchpad>/tr762 (plus: node .devbook/_tools/devbook-meta/build.mjs --check; node tools/devbook/check-metadata.mjs; node --test tools/devbook/check-metadata.test.mjs)build.mjs --check;check-metadata.mjs: 192 files, 0 blocking).Review
node tools/diagrams/archify-artifacts.mjs scanreports it asstale, where before it was rendered. The Devbook pane withholds it and reports it out of date (ArchifyDiagramArtifactsTests: An_artifact_authored_before_the_fence_was_edited_is_withheld_and_reported_as_out_of_date), so the rendered context map no longer shows.What could not be proved
sync/chapters and the context map againstBacklog.Modules.Sync..devbook/domain/_archify/context-map.1.*) is now stale and the Devbook pane withholds it. Re-deliver that one spec (notrender --all), or let feat(devbook): render Archify artifacts on demand instead of committing them #1294's on-demand rendering pick it up if that merges first.tasks/domain.md#deviceandsync/domain.md#deviceboth claim the term "device"; the chapters say how they differ (the shared-kernel machine vs. its registration under a service-issuedDeviceId).Merge Danger
Door. Two-way: a revert restores the previous chapters. No code, data or setting changes.
Blast radius. local — the domain/ chapters, the context map and the derived devbook database built from them.
Assumptions taken instead of asking
syncflag. Assumption: this change settles that row, and the PR body says so without closing [Devbook drift] .devbook/domain/ #896, which covers more.## Device, as AC3 names it. This raises one new advisory warning: tasks/domain.md#device and sync/domain.md#device both claim the term "device". The chapter text says why they differ: the shared-kernel machine against its registration with the sync service under a service-issued DeviceId. The repository already tolerates several such cross-context collisions, for example Sessions Environment and Environment.deployment: service, because the sync service is a separately deployed host (Backlog.Modules.Sync.Api). The context map has no bounded-context chapter for Sync to agree or disagree with.Opened as a draft by an attended run of
delivery-schedule:schedule-issue-sweep(2026-10-15), told by the owner to decide without asking and to name the choice and the alternative.🤖 Generated with Claude Code