# Phase 2: P2P Networking Mesh & Schema Extension ## Status: Ready for Agent Execution **Phase Goal:** Implement the libp2p P2P networking stack in `chronogrid_net`, extend the database schema with all missing entities, scaffold the headless daemon binary, and harden the verification pipeline. **Prerequisites:** Phase 1 complete ✅ **Estimated Complexity:** High **Blocking:** Phase 3 (Flutter UI requires sync events), Phase 4 (AI requires ingestion schema) --- ## Task 2.1 — Extend Schema with Missing Entities - [x] **Task 2.1**: Extend `docs/API_CONTRACTS/schema.sql` with the following new tables: - `time_blocks` — Calendar time-blocking entries linked to tasks - `attachments` — Binary/file attachments linked to notes or ingestion logs - `calendar_feeds` — CalDAV external feed configuration per namespace - `node_peers` — P2P peer registry (NodeId, public key, last seen, swarm membership) - `automation_rules` — Local trigger/action rule definitions - `ingestion_configs` — IMAP account and file-watcher configuration per namespace - Add `crdt_docs` entries for `time_block` entity type - Add indexes for all new foreign keys and query patterns - Verify `db.rs` `EXPECTED_TABLES` list is updated to include all new tables - All new tables must include `hlc_timestamp TEXT NOT NULL` for CRDT compatibility - Run `cargo test --package chronogrid_core` — all existing tests must still pass --- ## Task 2.2 — Implement chronogrid_net: Node Identity & Swarm Key - [x] **Task 2.2**: Implement node identity and swarm key management in `crates/chronogrid_net/`: - Add dependencies: `libp2p = { version = "0.54", features = ["noise", "quic", "mdns", "gossipsub", "kad", "identify", "relay"] }`, `tokio = { version = "1", features = ["full"] }`, `ed25519-dalek = "2"`, `rand = "0.8"` - Implement `NodeIdentity` struct: Ed25519 keypair generation, serialization, and `NodeId` (public key hash) - Implement `SwarmKey` struct: 256-bit random key generation, serialization, and validation - Implement `identity::generate_node_identity() -> NodeIdentity` - Implement `identity::load_or_create_identity(path: &Path) -> Result` — persists keypair to encrypted file - Unit tests: keypair generation, serialization round-trip, NodeId derivation, SwarmKey validation - Run `cargo test --package chronogrid_net` --- ## Task 2.3 — Implement chronogrid_net: Transport & Discovery Layer - [x] **Task 2.3**: Implement the libp2p transport stack and peer discovery in `crates/chronogrid_net/`: - Implement `transport::build_transport(identity: &NodeIdentity, swarm_key: &SwarmKey) -> Result>` - QUIC over UDP as primary transport - Noise XK handshake (Noise_XK_25519_ChaChaPoly_BLAKE2s) for authentication - Swarm Key pre-shared authentication layer - Implement `discovery::MdnsDiscovery` — zero-config LAN peer discovery - Implement `discovery::KademliaDht` — WAN peer discovery via Kademlia DHT - Implement `PeerEvent` enum: `PeerDiscovered { peer_id, addrs }`, `PeerExpired { peer_id }`, `PeerConnected { peer_id }`, `PeerDisconnected { peer_id }` - Unit tests: transport construction, mDNS event handling, DHT routing table operations - Run `cargo test --package chronogrid_net` --- ## Task 2.4 — Implement chronogrid_net: CRDT Delta Sync Protocol - [x] **Task 2.4**: Implement the CRDT delta exchange protocol over libp2p in `crates/chronogrid_net/`: - Implement `sync::VectorClock` — tracks per-entity HLC head state for delta computation - Implement `sync::DeltaPacket` — serializable struct containing compressed CRDT changesets - Implement `sync::SyncProtocol` — custom libp2p `NetworkBehaviour`: - On peer connect: exchange vector clocks via request/response protocol - Compute missing deltas by comparing remote vs. local vector clock - Compress delta bytes (LZ4 or zstd), encrypt with ChaCha20-Poly1305, stream over QUIC channel - On receive: decrypt, decompress, and return `Vec` for core to merge - Implement `sync::GossipsubBroadcast` — real-time state change notifications via Gossipsub - Implement `NetEvent` enum: `DeltasReceived { from_peer, deltas }`, `SyncComplete { peer_id }`, `SyncError { peer_id, reason }` - Unit tests: vector clock comparison, delta packet serialization, gossipsub message routing - Run `cargo test --package chronogrid_net` --- ## Task 2.5 — Implement chronogrid_net: P2P Swarm Manager - [x] **Task 2.5**: Implement the top-level `SwarmManager` in `crates/chronogrid_net/`: - Implement `SwarmManager` struct: owns the libp2p `Swarm`, runs the event loop in a dedicated Tokio task - Public API: - `SwarmManager::start(identity, swarm_key, listen_addrs) -> Result` - `SwarmHandle::trigger_sync() -> Result<()>` — initiates delta sync with all connected peers - `SwarmHandle::broadcast_event(event: GossipEvent) -> Result<()>` - `SwarmHandle::subscribe_events() -> tokio::sync::broadcast::Receiver` - `SwarmHandle::shutdown() -> Result<()>` - Integrate `MdnsDiscovery`, `KademliaDht`, `SyncProtocol`, and `GossipsubBroadcast` into a single `NetworkBehaviour` composite - Implement NAT hole-punching via libp2p Circuit Relay v2 (relay client mode) - Unit tests: swarm startup/shutdown, peer connection lifecycle, event subscription - Integration test: two in-process swarms exchange a CRDT delta and verify convergence - Run `cargo test --package chronogrid_net` --- ## Task 2.6 — Integrate chronogrid_net into chronogrid_core - [x] **Task 2.6**: Wire the P2P sync layer into `chronogrid_core`: - Add `chronogrid_net` as an optional dependency in `chronogrid_core/Cargo.toml` (feature: `"p2p"`) - Implement `core::sync::SyncEngine` — bridges `SwarmHandle` events to `Database` CRDT merges: - On `NetEvent::DeltasReceived`: deserialize Automerge changesets, merge into local `crdt_docs`, update SQL rows - On local CRDT mutation: compute delta vs. last-synced state, broadcast via `SwarmHandle` - Implement `core::sync::SyncEngine::merge_remote_deltas(deltas: Vec) -> Result>` — returns list of affected entity IDs - Unit tests: delta merge into in-memory database, conflict resolution with concurrent edits - Run `cargo test --package chronogrid_core --features p2p` --- ## Task 2.7 — Scaffold chronogrid_daemon Binary - [x] **Task 2.7**: Create the `apps/chronogrid_daemon/` headless binary crate: - Create `apps/chronogrid_daemon/Cargo.toml` with `[[bin]]` target `chronogrid-daemon` - Add `apps/chronogrid_daemon` to workspace `Cargo.toml` members list - Dependencies: `chronogrid_core`, `chronogrid_crypto`, `chronogrid_net`, `tokio`, `clap`, `serde`, `toml`, `tracing`, `tracing-subscriber` - Create `apps/chronogrid_daemon/src/main.rs`: - CLI argument parsing via `clap`: `--config `, `--db `, `--log-level ` - Config file loading from TOML (`/etc/chronogrid/config.toml` or `--config` path) - Initialize `chronogrid_crypto` key derivation and keychain retrieval - Initialize `chronogrid_core` database engine - Start `chronogrid_net` SwarmManager - Structured logging via `tracing` - Graceful shutdown on SIGTERM/SIGINT - Create `apps/chronogrid_daemon/config.example.toml` — documented example configuration - Create `docs/DEPLOYMENT/01-headless-daemon-setup.md` — systemd service setup guide - Run `cargo build --package chronogrid_daemon` --- ## Task 2.8 — Expand Verification Pipeline - [ ] **Task 2.8**: Expand `scripts/verify_agent_work.ps1` to cover all crates and run full test suite: - Add `cargo test --package chronogrid_crypto` step - Add `cargo test --package chronogrid_core` step - Add `cargo test --package chronogrid_ffi` step - Add `cargo test --package chronogrid_net` step - Add `cargo check --package chronogrid_daemon` step - Add schema table count validation (query SQLite in-memory and count tables) - Add check that `docs/API_CONTRACTS/schema.sql` contains all required table names - Improve error reporting with per-step timing and failure context - Run the expanded script and confirm all checks pass --- ## Task 2.9 — Update FFI Bridge Spec & Fix Type Inconsistency - [ ] **Task 2.9**: Update API contracts and fix the `due_date` type mismatch: - Fix `crates/chronogrid_ffi/src/api/types.rs`: change `due_date: Option` to `Option` and `completed_at: Option` to `Option` - Update `docs/API_CONTRACTS/ffi_bridge_spec.json` to document all 38 FFI functions across the 5 API modules (engine, database, crypto, task_crdt, note_crdt) - Add P2P sync FFI functions to the spec: `init_p2p_swarm`, `trigger_sync`, `subscribe_sync_events`, `get_connected_peers` - Run `cargo test --package chronogrid_ffi` — all tests must pass --- ## Phase 2 Completion Criteria - [ ] All 9 tasks above marked `[x]` - [ ] `cargo test --workspace` passes with zero failures - [ ] `scripts/verify_agent_work.ps1` exits with code 0 - [ ] `chronogrid_daemon` binary compiles for `x86_64-pc-windows-msvc` and `x86_64-unknown-linux-gnu` - [ ] `docs/API_CONTRACTS/schema.sql` contains all 13 tables (7 original + 6 new) - [ ] ADR created for P2P networking decisions (`docs/ARCHITECTURE/ADR/0006-p2p-libp2p-networking.md`) - [ ] `DECISION_LOG.md` updated with Phase 2 decisions