chronogrid/DECISION_LOG.md

113 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Architectural Decision Log (ADL)
## [2026-08-09] - ADL-001: Distributed Local-First System Baseline
- **Status**: Accepted
- **Context**: Design a multi-platform (Windows, Linux, Android, Headless) productivity engine for time, project, and note management without centralized servers.
- **Decision**: Adopted Rust core with SQLCipher local storage, Automerge CRDT delta sync over libp2p, and Flutter presentation layer bound via C-FFI.
## [2026-08-09] - ADL-002: chronogrid_crypto Crate – Argon2id KDF & OS Keychain
- **Status**: Accepted
- **Context**: Task 1.2 required implementing the `chronogrid_crypto` crate with Argon2id master-key derivation and OS-native keychain bindings per `docs/ARCHITECTURE/02-security-and-crypto.md`.
- **Decision**:
- Argon2id parameters pinned: 64 MiB memory, 3 iterations, 4 threads, 16-byte random salt, 32-byte output.
- `DerivedKey` struct implements `Zeroize + Drop` to scrub sensitive memory on scope exit.
- OS keychain abstracted via `keyring` crate v3 (Windows Credential Manager / DPAPI, Linux SecretService / libsecret). Android keychain is excluded (`cfg(not(target_os = "android"))`) and will be handled by Flutter KeyStore bridge in Task 1.5.
- Raw key material is Base64-encoded before credential-store insertion for UTF-8 backend compatibility.
- Inline Base64 encode/decode helpers avoid adding an external Base64 dependency.
## [2026-08-19] - ADL-003: chronogrid_core Crate – SQLCipher 4.x Database Initializer
- **Status**: Accepted
- **Context**: Task 1.3 required implementing the `chronogrid_core` crate with SQLCipher 4.x encrypted database initialization matching `docs/API_CONTRACTS/schema.sql`.
- **Decision**:
- `rusqlite` v0.31 with `bundled-sqlcipher-vendored-openssl` feature bundles both SQLCipher and OpenSSL, ensuring a hermetic build with no external C library dependencies.
- The 32-byte Argon2id-derived master key is passed as a **raw hex key** via `PRAGMA key = "x'…'"`, bypassing SQLCipher's internal PBKDF2 derivation since Argon2id already provides equivalent or stronger protection.
- `PRAGMA cipher_compatibility = 4` enforces SQLCipher 4.x defaults (AES-256-CBC, HMAC-SHA512 page auth, 64 KiB page size).
- `PRAGMA foreign_keys = ON` is set on every connection per the schema specification.
- The canonical schema SQL from `docs/API_CONTRACTS/schema.sql` is embedded via `include_str!` at compile time, ensuring single-source-of-truth alignment without runtime file I/O.
- Post-initialization validation confirms all 6 expected tables exist (`namespaces`, `projects`, `tasks`, `notes`, `task_note_links`, `ingestion_logs`) plus 4 indexes.
- `Database` struct provides `open(path, key)` for file-backed and `open_in_memory(key)` for test databases; key length is validated at 32 bytes.
- 11 unit tests cover: table/index creation, FK enforcement, cascade deletes, wrong-key rejection, key length validation, schema idempotency, and CRUD round-trips across all tables.
## [2026-08-20] - ADL-004: chronogrid_core – Automerge CRDT Integration for Task & Note Registers
- **Status**: Accepted
- **Context**: Task 1.4 required integrating the Automerge CRDT engine into `chronogrid_core` so task and note entities support offline-first LWW register mutations with HLC-based causal ordering.
- **Decision**:
- Added `automerge = "0.5"` (resolved to v0.5.12) and `uuid = "1"` with `v4` feature to `chronogrid_core/Cargo.toml`.
- Extended `schema.sql` with `crdt_docs` table (`entity_id TEXT PK`, `entity_type TEXT`, `doc_bytes BLOB`, `updated_at INTEGER`) and `idx_crdt_docs_type` index.
- Implemented `crdt/` sub-module: `Hlc` (Hybrid Logical Clock with `tick()`/`update()`/`Display`/`FromStr`), `CrdtDoc` (generic Automerge wrapper with typed scalar accessors), `TaskCrdt` (11 mutable fields), `NoteCrdt` (4 mutable fields).
- Each entity mutation stamps the document with an advancing HLC timestamp. Fork/merge delegates to Automerge's deterministic conflict resolution.
- `Database` gained `save_crdt_doc()`, `load_crdt_doc()`, `delete_crdt_doc()` for serialized Automerge blob persistence.
- Added `CoreError::Crdt` and `CoreError::HlcParse` error variants.
- 45 unit tests (all passing): HLC ordering/parse, all scalar types, save/load/fork/merge round-trips, CRDT doc DB persistence, schema validation with `crdt_docs` table.
- Full ADR at `docs/ARCHITECTURE/ADR/0004-core-automerge-crdt-integration.md`.
## [2026-08-20] - ADL-005: chronogrid_ffi Crate – Flutter Rust Bridge v2 FFI Layer
- **Status**: Accepted
- **Context**: Task 1.5 required generating `flutter_rust_bridge` FFI bindings to bridge all Rust storage, CRDT, and cryptographic methods to the Flutter/Dart presentation layer.
- **Decision**:
- Created `crates/chronogrid_ffi/` crate with `cdylib` + `staticlib` + `lib` targets, depending on `chronogrid_core`, `chronogrid_crypto`, `flutter_rust_bridge = "=2.7.0"`, and `anyhow = "1"`.
- API uses a **serialized-bytes pattern**: CRDT documents cross FFI as `Vec<u8>` (Automerge binary); read functions return DTO structs (`FfiTaskData`, `FfiNoteData`, `FfiDerivedKey`).
- Global `Engine` singleton (`Mutex<Option<Engine>>`) holds the `Database` connection + `Hlc` clock. Thread-safe `with_engine()` / `with_engine_mut()` helpers provide access from FRB's isolate thread pool.
- 38 public FFI functions across 5 API modules: `engine` (init/close/status), `database` (CRDT doc persistence), `crypto` (key derivation + platform-gated keychain), `task_crdt` (18 create/read/set/clear/merge ops), `note_crdt` (8 create/read/set/clear/merge ops).
- All fallible functions return `anyhow::Result<T>`, which FRB v2 maps to Dart exceptions.
- Keychain functions compile on all platforms but return an error on Android (delegated to Flutter KeyStore bridge).
- `flutter_rust_bridge.yaml` configures codegen: Rust input from `api/`, Dart output to `apps/chronogrid_flutter/lib/src/rust/`.
- Flutter `pubspec.yaml` updated with `flutter_rust_bridge: ^2.7.0`, `ffi: ^2.1.0`, `meta: ^1.11.0`.
- 25 unit tests (all passing): engine lifecycle, DB CRDT doc persistence, task/note CRDT create/read/mutate/merge round-trips, crypto derivation, stateless read validation, no-engine error paths.
- Full ADR at `docs/ARCHITECTURE/ADR/0005-ffi-bridge-flutter-rust-bridge.md`.
## [2026-08-22] - ADL-007: chronogrid_core Schema Extension — Phase 2 Missing Entities (Task 2.1)
- **Status**: Accepted
- **Context**: Task 2.1 required extending `docs/API_CONTRACTS/schema.sql` with 6 missing entity tables identified in the ADL-006 architecture review as a critical gap blocking Phase 3 and Phase 4 development.
- **Decision**:
- Added 6 new tables: `time_blocks`, `attachments`, `calendar_feeds`, `node_peers`, `automation_rules`, `ingestion_configs`.
- All new tables include `hlc_timestamp TEXT NOT NULL` for CRDT compatibility, except `node_peers` which is managed by `chronogrid_net` and does not participate in CRDT sync.
- `node_peers` has no FK to `namespaces` — it is a global peer registry scoped to the node, not to a namespace.
- `attachments.storage_path` stores relative paths inside the encrypted vault directory; file bytes are stored outside SQLite to avoid BLOB size limits.
- `calendar_feeds` and `ingestion_configs` store credentials as encrypted blobs (`encrypted_password_blob`, `encrypted_imap_password_blob`) — never plaintext.
- `ingestion_configs` uses a `config_type` discriminator (`imap` | `file_watcher` | `hotkey`) with nullable type-specific fields, avoiding a separate table per ingestion type.
- `crdt_docs.entity_type` now supports `'time_block'` in addition to `'task'` and `'note'`.
- `EXPECTED_TABLES` in `crates/chronogrid_core/src/db.rs` updated from 7 to 13 entries; schema validation enforces all 13 tables on every database open.
- 12 new indexes added for all new FK columns and common query patterns.
- 8 new unit tests added covering CRUD round-trips, FK cascade/SET NULL behavior, and `time_block` CRDT doc persistence.
- Verification script confirmed: all 13 tables present in schema.sql (PASS), Flutter analysis clean (PASS).
- Full ADR at `docs/ARCHITECTURE/ADR/0007-schema-extension-phase2-entities.md`.
## [2026-08-22] - ADL-008: chronogrid_net Crate — Node Identity & Swarm Key (Task 2.2)
- **Status**: Accepted
- **Context**: Task 2.2 required implementing the foundational identity and cluster-authentication primitives for `chronogrid_net`: Ed25519 node keypair (`NodeIdentity`), SHA-256-derived `NodeId`, and 256-bit pre-shared `SwarmKey`.
- **Decision**:
- `ed25519-dalek v2` chosen for Ed25519 keypair generation (audited, `rand_core`-compatible, libp2p-compatible for Task 2.3 integration).
- `NodeId` = SHA-256(public key bytes) → 32-byte / 64-hex-char stable identifier; maps directly to `node_peers.id` primary key in schema.
- `SwarmKey` = 32 bytes from `OsRng`; `fingerprint()` = first 16 hex chars of SHA-256(key) → maps to `node_peers.swarm_key_fingerprint`.
- Both `NodeIdentity` and `SwarmKey` implement `ZeroizeOnDrop`; `PersistedIdentity` also zeroized to prevent secret hex strings lingering in heap.
- `SwarmKey::eq` uses constant-time XOR accumulation with `black_box` to mitigate timing side-channels.
- Persistence: `NodeIdentity` → JSON (hex-encoded keys); `SwarmKey` → 64-char hex file. Both stored inside encrypted vault directory.
- `load_or_create_identity()` and `SwarmKey::load_or_create()` provide idempotent file-backed initialization.
- 27 unit tests: generation uniqueness, determinism, hex/bytes round-trips, file I/O, error paths, debug redaction, constant-time equality.
- Full ADR at `docs/ARCHITECTURE/ADR/0008-net-node-identity-swarm-key.md`.
## [2026-08-22] - ADL-006: Architecture Review Board Assessment & Master Development Plan v2
- **Status**: Accepted
- **Context**: A comprehensive senior architecture review was conducted covering all crates, documentation, task structure, and the development plan. Phase 1 is complete and production-quality. Phases 2–5 require a structured execution plan to enable automated agent development.
- **Decision**:
- Created `docs/ARCHITECTURE/05-architecture-review-assessment.md` — full ARB assessment with gap analysis, risk register, and recommendations.
- Created `docs/ARCHITECTURE/06-master-development-plan.md` — authoritative execution plan superseding OSAD Section 8, with 37 tasks across Phases 2–5, quality gates, and acceptance criteria traceability.
- Created `docs/TASKS/phase_2_networking_and_schema.md` — 9 tasks for libp2p networking, schema extension, daemon scaffold, and verification pipeline hardening.
- Created `docs/TASKS/phase_3_flutter_ui_shell.md` — 10 tasks for Flutter BLoC architecture, all 4 primary views, FRB codegen, and build scripts.
- Created `docs/TASKS/phase_4_ai_and_automation.md` — 9 tasks for NLP engine, IMAP ingestion, file watchers, CalDAV server, and automation rules engine.
- Created `docs/TASKS/phase_5_headless_and_release.md` — 9 tasks for daemon completion, integration testing, performance testing, and release packaging.
- Fixed documentation typos in `docs/UI_UX/02-calendar-timeblocking.md` and `docs/UI_UX/03-kanban-gantt-views.md`.
- Expanded `docs/WORKFLOWS/01-master-user-story.md` from a stub to a substantive workflow reference document.
- Identified critical gaps: 6 missing schema tables, FFI type mismatch (`due_date: i64` vs `u64`), incomplete verification script, missing build scripts, unscaffolded daemon crate.
- Confirmed all Phase 1 architectural decisions as correct — no reversals required.
- Next task for automated execution: **Task 2.1 — Extend Schema with Missing Entities**.