From 03beccb5afb1a70218dcdb520b73d1faad999a10 Mon Sep 17 00:00:00 2001 From: Luan Nguyen Date: Wed, 11 Nov 2026 21:39:29 +1100 Subject: [PATCH] docs(notes): describe local feature scope and build limits --- README.md | 41 ++++++++-- docs/architecture.md | 178 +++++++++++++++++++++++++++++++++++-------- docs/windows.md | 58 +++++++++++++- 3 files changed, 233 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 2b2a207..fa8431d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Encrypted notes and pages that work offline and link to Orbyn Planner tasks. -**Status: being built. Nothing has launched, and there is nothing to install yet.** +**Status: being built. No public release is available.** Orbyn Notes is the second Everyday app in the Orbyn family, beside [Orbyn Planner](https://github.com/orbyn-dev/orbyn-planner). It runs on the open [orbyn-engine](https://github.com/orbyn-dev/orbyn-engine), so notes are encrypted on your device before they sync, and one Orbyn account signs in to every app. @@ -10,17 +10,44 @@ Orbyn Notes is the second Everyday app in the Orbyn family, beside [Orbyn Planne - Notes and pages, offline first, encrypted before upload. - Links between notes and Orbyn Planner tasks and events. -- Study, Clip and Journal inside the same app (Planned). +- Study, Clips and Journal in the same app, with connected features planned. -These are plans, not features you can use today. The product plan and designs are internal. +These are product goals. The local beta below implements part of them; the +product plan and designs are internal. ## Web beta implementation The local web beta is implemented under `web/`; it is not a published release. -Its scope is a single-browser encrypted library with a rich-text editor, local -search, tags, Trash/restore and Markdown import/export. New accounts use shared -Orbyn invites. Notes do not sync in this beta, and clearing browser data removes -their local keys and content. Export a readable Markdown backup first. +The local implementation has a rich-text library, tags, pins, version history, +Trash/restore, Markdown transfer and encrypted Study, Journal and Clips data. +Study supports local reviews, CSV transfer and cards made from selected saved +note passages, with verified source jumps. Journal has its own passphrase, +entries, habits and readable export. Clips saves links and text you paste; page +fetching, browser capture and highlights remain unfinished. A local Windows shell +is built from the same UI; see [Windows instructions](docs/windows.md). + +The local setup/search work adds optional Markdown setup and search across active +Notes, saved Clips (including archived items), and actual Study card directions. +Journal, Trash, review history and captured source quotes are excluded from search. +Large searches can pause for an explicit Continue; result pages keep exact totals. +These changes are still undergoing integration and native qualification. + +Settings → Study edits the five existing local review preferences with explicit +Save and Cancel. Daily limits affect the next normal session; already queued +cards, repeat reviews and Study more can exceed them. Changing the study-day +start regroups totals without rescheduling cards. Reminders, Planner tasks, +card suggestions and agent setup remain planned. + +Study reviews use two-dimensional card swaps, toast exits and delayed loading +feedback, with reduced-motion support. Grading waits for the answer entrance to +finish; presentation timers never record reviews or change scheduling. + +New accounts use shared Orbyn invites. This beta does not sync, and clearing a +browser or WebView profile removes its local keys and content. Export each module +separately before removing data: Notes Markdown excludes Study, Journal and Clips. +Study CSV preserves rendered card text and tags; it does not restore scheduling, +card types or passage links. These exports are not a complete workspace backup. +Local implementation does not mean all design frames or release checks are done. Use Node.js 24 and run these commands from `web/`: diff --git a/docs/architecture.md b/docs/architecture.md index 68f6af4..7676481 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -9,14 +9,18 @@ Rules that change go in this file with the change. ## Single-browser web beta `web/` contains the React/Vite/TypeScript application. The UI consumes the -`NotesStore`, account and Markdown-transfer interfaces in `src/domain/contracts.ts`. +`NotesStore`, account and Markdown-transfer interfaces in `src/domain/contracts.ts`, +plus the library and collections interfaces in their owning modules. Domain, persistence and account behavior are independent of the presentation layer. The structured document supports paragraphs, headings, lists, task items and links. -Search is a local projection of titles, textual document content and tags. +Search projects active Note titles, textual content and tags, saved Clips, and +actual Study card directions. Its integration/native qualification remains open. The engine revision and generated artifact provenance are pinned in `web/engine-pin.json`. Generated TypeScript contracts and the browser WASM package -belong to the same engine revision. Engine code retains its MIT/Apache notices. +use the recorded engine base. The current WASM build adds the reviewed local-zone +purge source patch recorded separately in that pin; it is not presented as part of +the base commit. Engine code retains its MIT/Apache notices. Authentication uses real OPAQUE and engine device keys; fixtures are test-only. New accounts use the engine's existing invite and email-verification protocol. Existing accounts use its sign-in, second-factor and pending-device protocol. @@ -58,33 +62,141 @@ sessions or generated exports. New workers wait for old windows to close rather than replacing a running editor. IndexedDB schema changes require separate compatibility review; changing the shell cache does not migrate user data. -Deferred: cross-device sync, attachments, Planner links, Study, Journal, Clipper, -public sharing, other native platforms and billing. Their visible navigation and -claims are omitted from the beta. - -## Local Windows shell - -The local Windows build embeds the existing web UI in Tauri2/WebView2 with a -44px custom caption. Native window controls and the system menu use narrowly -scoped commands for the local main window. Remote navigation and new windows -are denied. Normal close waits for the application draft/operation guards and a -matching close-request acknowledgement. The WebView profile remains separate -from browser profiles; builds do not migrate or erase it. This is an unsigned -local build, with no installer or public release qualification. See -[Windows build and boundaries](windows.md). - -## Delivery boundary: encrypted-owners - -Versioned library and Collections owners capture account/epoch authority for every commit. Migration and workspace erase use the pinned engine adaptation and preserve the previous encrypted snapshot on failure. Account identity, trust, approval checkpoints and unrelated zones are retained. These domain adapters precede workspace wiring in this delivery stack. - -## Delivery boundary: journal-vault - -Journal uses a separately protected envelope and private-form recovery. Account, epoch and genuine borrowed-owner closure revoke access before any late read or crypto result can publish. This clears live references and views, without claiming allocator zeroization or remote deletion. The Journal view is wired in a later slice. - -## Delivery boundary: native-link-transport - -The local main window alone may acknowledge bounded note intents or request validated HTTP(S) source opening. Commands independently verify the current injected caller URL. External URLs receive a fixed OS open verb with no argument expansion; arbitrary navigation and filesystem commands are unavailable. - -## Delivery boundary: journal-interface - -Journal removes unlocked content and populated credential forms synchronously on terminal owner revocation. Replaced or unmounted subscriptions cannot read dead owners or republish late crypto results. Stored writing remains encrypted and can reopen through a fresh eligible owner. +## Library and local collections + +The library writer owns `notes-local` and `notes-library-v1` in the same encrypted +snapshot transaction. Its catalog records pins, exact tag names/colors, bounded +immutable note versions and mutation receipts. Renaming or merging tags changes +membership atomically; restoring a version restores its title/document while +retaining current tags and pin state. Trash has explicit restore and empty actions; +the current implementation does not automatically purge notes after 30 days. + +The account-scoped `CollectionsStore` owns `notes-collections-v1/workspace`. Study, +the sealed Journal envelope and Clips share its epoch/revision CAS and one writer. +Collection schema3 supports anchored Study sources alongside legacy sources; +schema2 introduced Clips. Strict schema1 or schema2 validation precedes pure +read normalization; the first successful write persists schema3. A read alone +does not rewrite an existing record. Unknown versions, wrong authenticated +record types and corrupt payloads fail closed. The size cap adds exactly +the empty Clips field's UTF8 overhead to the schema1 cap, preserving readability +for valid legacy payloads at that boundary. Writes still reject capacity overflow, +including growth in a revision's serialized digits, without changing storage. + +Study persists decks, Basic/Reversed/Cloze entries, derived cards, review events +and preferences. Its current scheduler is versioned `orbyn-interval-v1`. Grades +and Undo use durable event identities and revision checks. Daily admission uses +the stored local timezone and day-start boundary. CSV transfer handles the +rendered front/back text and tags as independent rows. Import creates new Basic +cards; original card types, scheduling history and source anchors are not +restored. CSV is not a complete Study backup or Anki history transfer. + +The Study settings form borrows that same account-lifetime Collections owner. +An explicit Save patches only edited preference keys under epoch/revision checks; +conflicts retain raw edits and require a deliberate reload before retry. An +unconfirmed save is checked by reading the actual saved values, without replaying +the write. Dirty forms guard local navigation and native close. Owner closure, +account lock and epoch replacement clear their draft and pending continuations. +Caps apply to the next normal queue and do not replace a held queue or its captured +answer time. Due repetitions of already admitted cards and explicit Study more can +exceed the caps. The day-start hour changes derived daily grouping, leaving review +timestamps, schedules, stored timezone and algorithm unchanged. Visibility changes +follow a committed snapshot. The Undo toast uses a separate monotonic presentation +clock, paused by hover, focus, hidden documents or covering UI; expiry changes no +review event or Undo authority. Reminder delivery and connected Study services +remain incomplete. + +Review motion retains only scoped card/entry IDs and revision scalars. Outgoing +text is resolved from the current authorized snapshot, and an edit, removal or +scope change retires the phase. Reveal timestamps and confirmed review history +advance through their existing domain actions; visual completion never writes +either. Grading is admitted only after the answer has finished entering. The +toast's separate exit phase does not create a second dwell clock or an Undo +deadline. + +Study subscribes to internal lock, genuine owner-close and observed epoch events +before its first read. These callbacks synchronously clear private projections +and retire pending read/commit generations. Recovery explicitly asks the parent +to open a fresh owner under the existing navigation guards, rather than retrying +a closed handle. Another owner's erase can commit before this owner reads the +new epoch; synchronous clearing is guaranteed at local observation, not at an +unobserved remote commit. Cold-loader tickets belong to that same owner lifetime. + +Study source creation uses the existing library snapshot writer to commit the +entry, derived cards, source anchor and retry receipt atomically, with both +library and Collections revision checks. Library metadata schema2 adds anchors +and separate bounded source receipts; strict schema1 migration adds exactly the +two empty fields' serialized overhead to its size cap. No fourth zone or +IndexedDB schema change is introduced. Anchor creation lineage survives receipt +pruning, and its current mapped revision is separate from its creation revision. + +The editor supplies actual ProseMirror steps from an acknowledged saved base. +The writer replays and verifies those steps against the exact saved and final +documents before mapping attached passages. Supported surrounding edits and +formatting retain attachment; replacing selected content, including identical +text, detaches it. Unproved document or history replacements also detach it. +There is no quote-search fallback. Proof and combined anchor-mapping work have +explicit bounds; exceeding them requires an explicit replacement decision. +That confirmed recovery uses `NotesLibrary.replaceDocument`, which invalidates +attached sources even when the final document bytes are unchanged. It is a +distinct writer operation; ordinary metadata saves cannot stand in for it. +Source resolution reads the authenticated note, library and Collections state +together and rechecks freshness before the target editor validates and highlights +the passage. Unavailable and legacy sources cannot claim a verified highlight. +Create Undo has a separate stable retry identity and the original five-second +admission deadline; changed cards, schedules or anchors reject Undo. The source +UI and remaining design-frame qualification are still being verified locally. + +Journal uses a separate passphrase and non-extractable AES256-GCM key derived with +PBKDF2-SHA256, 600000 iterations. Fresh IVs and account/collection-epoch associated +data bind each envelope. General Notes search, history and Markdown export do not +include Journal plaintext. The vault removes its plaintext projection before +awaiting lock encryption and checks overdue absence on return as well as on timer +delivery. Unsaved body, habit-form and link-form intent can be retained in paired +encrypted recovery within that window; reopening requires real passphrase proof. +No browser restart recovery of these uncommitted forms is promised. JavaScript +strings cannot be guaranteed to have been physically erased from process memory. +Exports are deliberate readable files with manual-recovery limits. + +Clips stores validated HTTP(S) links and optional actual pasted text. It does not +fetch a page as part of local Save link. Duplicate comparison uses a separate +canonical URL; the validated original URL is retained. Read/read-later/archive +flags are independent. Prepared mutation input is captured before asynchronous +work and fingerprinted, with stable operation identities retained for explicit +unknown-result reconciliation. Durable bounded receipts distinguish changed and +no-op operations. A receipt-only no-op increments the collections revision while +leaving the clip revision unchanged. Create Undo requires the original unmodified +clip and expires five seconds after atomic admission, without restarting on replay. +Clips export includes complete JSON, readable items and recovery guidance. + +Each store captures the account lock generation. Same-identity reauthentication, +sign-out, closure and collection epoch changes revoke old asynchronous work. +Views clear held drafts and generated downloads on invalidation. A previously +prepared operation is never silently adopted into a new collection epoch. + +Whole-workspace erase validates the existing owned records and captures their +revisions before purging exactly the three content zone owners. The producer +purge removes their keys and cached uploads as well as current records. Fresh +keys, empty replacement records and new epochs commit atomically in the same +IndexedDB transaction. Account/device identity, trust/protection, the separate +approval checkpoint and unrelated zones remain. Failure preserves the previous +snapshot. Replacement stamps retain the required round-trip clock watermark +under the producer's normal future-stamp policy; the generic bare purge API has +only a live-instance clock guarantee. External exports and other copies are not +wiped by local erase. + +## Windows shell and remaining scope + +The local Windows build embeds the web UI in a Tauri2 shell with custom caption +controls and guarded close. Its WebView profile is separate from a normal browser +profile. The restricted source-opening command hands validated HTTP(S) destinations +to the OS; other native navigation and new-window requests remain denied. See +[Windows boundaries and build instructions](windows.md). Local builds do not +constitute a public release or a completed release qualification. + +Still incomplete: cross-device sync, attachments, Planner linking, per-note +protected locks, browser extension capture and extraction, reader highlights and +the clip-to-note bridge, full Study source-selection qualification, FSRS/Anki transfer, +agent integrations, public sharing, other native platforms and billing. The +local module slices above do not qualify every approved design frame. Unsupported +integration states must remain explicit; fixtures and generated API types do not +count as working services. diff --git a/docs/windows.md b/docs/windows.md index 1953476..9f6f6ec 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -7,7 +7,7 @@ browser profiles. Browser notes and account sessions are not migrated. ## Build -Use Windows with Node 24, the Rust MSVC toolchain in `%USERPROFILE%\.cargo\bin`, +Use Windows with Node 24, Rust 1.90 or newer with the MSVC toolchain in `%USERPROFILE%\.cargo\bin`, Visual Studio C++ build tools with the Windows SDK, and WebView2 installed. From `web`: @@ -33,10 +33,21 @@ Do not change the native origin to work around CORS or storage failures. ## Boundary and close behavior Only the local `main` webview receives the listed caption/event permissions. -External top-level navigation and all new-window requests are denied. The only -custom commands are `finish_close` and the parameter-free `show_system_menu`; +External top-level navigation and all new-window requests are denied. The +caption commands are `finish_close` and the parameter-free `show_system_menu`; both verify the injected calling window and its current local URL. No renderer -permission can destroy the window or access the filesystem, shell or process. +permission can destroy the window or access the filesystem or arbitrary processes. + +The separate `open_external_url` command hands a deliberate HTTP(S) source action +to the Windows default browser. It independently checks the local injected caller, +rejects credentials, other schemes, ambiguous backslashes, raw control characters +and URLs over 8192 UTF16 units. It checks the live window again on its existing +COM STA thread before obtaining the owned handle. `ShellExecuteW` receives only a +validated URL, a fixed `open` verb and null argument/directory pointers. There is +no general shell or process command. OS acceptance means handoff only; it does not +mark a clip read or prove that a page loaded. Failure leaves the source copyable. +Other native platforms report opening unavailable until their adapter is built. +Browser builds use ordinary safe external anchors with `noopener noreferrer`. Rust prevents every normal native close, then emits `notes-close-requested` with `{ requestId }`. Repeated requests share the pending safe-integer ID. @@ -61,3 +72,42 @@ Primary implementation references: [Tauri configuration](https://v2.tauri.app/re [capabilities](https://v2.tauri.app/security/capabilities/), [WebviewWindowBuilder](https://docs.rs/tauri/2.12.5/tauri/webview/struct.WebviewWindowBuilder.html), and [application command permissions](https://docs.rs/tauri-build/2.7.4/tauri_build/struct.AppManifest.html). +The restricted source handoff follows [Microsoft ShellExecuteW](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew). + +## Trying a new local candidate + +Save or explicitly discard any current draft, then close the older Notes window +normally before starting a newer executable. The stable app identity enforces a +single instance: opening another executable while the old process is running +focuses that existing process and does not replace its embedded frontend. +Keep the WebView profile; rebuilding does not require clearing keys or content. + +For a candidate containing setup and search, check the optional Markdown setup, +then search real Notes, Clips and Study cards. Archived Clip results open internally +without changing read/archive state. A card result previews its exact direction +without recording a review. Journal and Trash must not appear in search. Exercise +Previous/Next, Back to search, a source change and a failed/paused operation; do not +interpret a pending or paused search as zero results. Confirm that returning to a +Note preserves its writing, selection and Undo history. + +For a candidate containing Study settings, open Settings → Study before starting a +review, change a limit and choose Save changes, then reopen it. During a held +review, saving preferences must preserve the current card, revealed answer and +Undo history. Dirty Done, Escape and section changes must offer recovery; native +close must wait for an explicit save or discard and a new close request. Hovering +or focusing the Undo toast, or covering Study with Settings, pauses its remaining +five-second display time. Toast expiry does not remove review history. + +For a motion candidate, check reveal and grading with both normal and reduced +motion. Early numeric input during the answer entrance must not grade or queue a +review; a fresh input after it settles can grade once. Open and close Settings +during a transition, then verify that the held card and Undo remain correct. +Changing accounts must remove private Study content immediately. Decorative +phases alone must not block native close; genuine unsaved work still does. + +Browser automation against a disposable encrypted fixture does not qualify native +account entry, the OS file dialog, physical IME or Windows input behavior. A compiled +candidate is not a public release. Keep the previous executable until the new one +passes the required native checks. Setup/search introduces no new persistent corpus +schema, but rollback across a later schema change needs separate compatibility +verification. Never delete the app profile as a rollback step.