Skip to content

feat: Phase 2 cloud sync client (crates/cloud)#43

Merged
dave6892 merged 2 commits into
mainfrom
feat/phase2-cloud-client
Mar 30, 2026
Merged

feat: Phase 2 cloud sync client (crates/cloud)#43
dave6892 merged 2 commits into
mainfrom
feat/phase2-cloud-client

Conversation

@dave6892

@dave6892 dave6892 commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds crates/cloud — the client-side cloud sync library for nichinichi
  • Extends crates/types with CloudConfig (opt-in, defaults to disabled)
  • Local-only functionality is completely unchanged

New crate: crates/cloud

File Purpose
client.rs CloudClient — HTTP sync operations (reconcile, push, pull, auth)
manifest.rs SyncManifest — local file index for diff-based sync
merge.rs Conflict resolution: RemoteWins / LocalWins / Error, block-level merge for daily entry files
error.rs CloudError types

Config change (crates/types)

Adds an optional cloud field to Config:

pub struct CloudConfig {
    pub base_url: String,         // default: "https://sync.nichinichi.app"
    pub token: Option<String>,    // None = not signed in
    pub last_synced_at: Option<DateTime<Utc>>,
    pub conflict_strategy: ConflictStrategy,
}

Omitting cloud: from ~/.nichinichi.yml keeps existing behaviour.

Test plan

  • cargo build -p nichinichi-cloud passes with no errors
  • cargo test -p nichinichi-cloud passes (merge unit tests)
  • Existing crates unaffected: cargo test -p nichinichi-parser -p nichinichi-sync
  • CloudConfig deserialises correctly from YAML with and without the cloud: key

What's next (Phase 2.2)

Wire CloudClient into the Tauri file watcher hook and add Tauri commands (cloud_sign_in, cloud_sync_now, get_cloud_status, etc.).

🤖 Generated with Claude Code

Introduces the client-side cloud sync layer for nichinichi.
Local functionality is unchanged; cloud is additive and opt-in.

- crates/cloud: new CloudClient crate (reqwest-based HTTP client)
  - client.rs: CloudClient with sync, push_file, pull_changed,
    sign_in, sign_out, register methods
  - manifest.rs: local file manifest (SyncManifest, ManifestEntry)
    for diff-based reconciliation with the server
  - merge.rs: conflict resolution strategies (RemoteWins/LocalWins/
    Error) and merge_entry() for daily entry block-level merging
  - error.rs: CloudError types
- crates/types: add CloudConfig struct (base_url, token,
  last_synced_at, conflict_strategy) as optional field on Config
- Cargo.toml: add crates/cloud workspace member

Next: wire CloudClient into file watcher and Tauri commands (Phase 2.2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dave6892 dave6892 self-assigned this Mar 29, 2026
@dave6892 dave6892 added the enhancement New feature or request label Mar 29, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dave6892 dave6892 merged commit a800a4c into main Mar 30, 2026
2 checks passed
@dave6892 dave6892 deleted the feat/phase2-cloud-client branch March 30, 2026 02:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant