-
-
Notifications
You must be signed in to change notification settings - Fork 2
Contributing a Durable Store
itsmylab edited this page Aug 4, 2026
·
1 revision
Generated from
docs/contributions/durable-store.md. Edit the canonical source through a pull request.
Use this playbook when Canopy-owned project knowledge or workflow state must survive app restarts and may be written by the WebView, agents, or Remote.
flowchart LR
Writers[WebView, agent bridge, Remote, sweep]
Rust[Rust store authority]
Disk[Atomic files under ~/.canopy]
Pulse[change::pulse]
Event[Debounced store:change]
Router[src/stores.ts]
Cache[Owning frontend cache]
UI[Panels and detail views]
Index[Optional rebuildable Spot index]
Writers --> Rust --> Disk
Rust --> Pulse --> Event --> Router --> Cache --> UI
Disk --> Index
The store write is the announcement point. A caller-side event misses writes from every other caller.
src-tauri/src/<store>.rs schemas, validation, mutations, atomic persistence
src-tauri/src/change.rs Store variant and invalidation pulse
src-tauri/src/lib.rs managed state and command registration
src/<store>.ts cache, refresh, mutation wrappers, UI event/channel
src/stores.ts one store-change router
src/components/<Store>*.tsx list/detail presentation
src-tauri/src/spot.rs optional derived indexing
Use notes.rs and research.rs as references.
- Decide whether the data belongs to Canopy or to the user's repository.
- Choose a project-scoped layout under
~/.canopy/<store>/for Canopy-owned data. - Define stable IDs, bounded list summaries, and separately fetched details.
- Reject empty, dotted, path-like, or traversal-containing IDs.
- Canonicalize attachment/source paths and verify containment.
- Serialize mutations with managed state.
- Write temporary files and atomically rename them.
- Cap body, source, attachment, list, and search sizes.
- Add Tauri commands and register them in
lib.rs. - Add a
change::Storevariant and pulse after successful mutations. - Register one module-scope frontend handler with
registerStore. - Refetch authoritative data after invalidation.
- Add indexing only as a rebuildable derivative.
- Test path attacks, partial writes, concurrent mutations, limits, and every status transition.
flowchart TD
List[List API: bounded summaries]
Get[Get API: one full record]
Raw[Raw source/attachment: explicit fetch]
Search[Search API: bounded matches]
List --> Get
Get --> Raw
List --> Search
Do not return every full body or raw attachment in list calls.
cargo test --manifest-path src-tauri/Cargo.toml --no-default-features <store>::tests
npm run test -- src/<store>.test.ts src/storeChangeGuard.test.ts
npm run typecheck- Data location and ownership justified.
- IDs and derived paths are contained.
- Mutations are serialized and atomic.
- Payloads and item counts are capped.
- List/detail/raw tiers are separate.
- Rust write boundary pulses the change bus.
- Frontend cache refetches on invalidation.
- Index is derivative, not authoritative.
- Failure and traversal tests added.
Generated from FluidWorksApp/canopy-ide. Canonical documentation changes belong in the main repository.
Canopy Architecture
- Home
- Architecture
- Core Rust System
- LLM Context
- Integration Guide
- Contribution Playbooks
- Testing and Coverage
- Publish the Wiki
Playbooks