Skip to content

chore(vetkeys): split encrypted_notes_app_vetkd into self-contained motoko + rust examples#1445

Open
marc0olo wants to merge 7 commits into
masterfrom
chore/split-vetkeys-encrypted-notes-app-vetkd
Open

chore(vetkeys): split encrypted_notes_app_vetkd into self-contained motoko + rust examples#1445
marc0olo wants to merge 7 commits into
masterfrom
chore/split-vetkeys-encrypted-notes-app-vetkd

Conversation

@marc0olo

Copy link
Copy Markdown
Member

Summary

Splits the vetkeys encrypted_notes_app_vetkd example into two self-contained examples (one per language) — same restructure as #1443 / #1444. Previously it lived only under rust/vetkeys/encrypted_notes_app_vetkd/ with a shared Svelte frontend symlinked into motoko/ and rust/ subdirs.

motoko/vetkeys/encrypted_notes_app_vetkd/   backend/app.mo + own frontend/ + icp.yaml + mops.toml
rust/vetkeys/encrypted_notes_app_vetkd/      backend/ (flattened) + own frontend/ + icp.yaml + Cargo.toml

Frontend (Svelte)

  • Duplicated per language; bindings generated by the @icp-sdk/bindgen Vite plugin from the committed backend/backend.did (replaces scripts/gen_bindings.sh).
  • Unified the binding imports. The shared frontend imported the bindings via three inconsistent paths (declarations/encrypted_notes/encrypted_notes_rust, …/backend.did, and ../lib/backend — the last of which didn't resolve and only survived as an erased import type). All now import from a single ../bindings/backend.
  • Added a root workspace package.json so npm run dev / npm run build run from the example root; kept all Svelte deps.

Backend

  • Motoko: idiomatic camelCase public interface (createNote, getNotes, updateNote, addUser, removeUser, deleteNote, encryptedSymmetricKeyForNote, symmetricKeyVerificationKeyForNote; EncryptedNote.encryptedText). The vetKD management-canister interface is kept snake_case (fixed system API). moc 1.11.0 + --default-persistent-actors (dropped persistent). Committed backend/backend.did.
  • Rust: unchanged (snake_case); relocated, and the hand-maintained .did moved to backend/backend.did.

Each frontend matches its own backend (Motoko camelCase / Rust snake_case).

Docs & CI

  • README split per language (cross-linked); prerequisites link each tool with its command inline.
  • test.sh added (all backend methods here are update calls — deliberately, for certification — so no --query).
  • vetkeys-encrypted-notes-app-vetkd.yml: motoko + rust jobs on the new paths, watching both, running test.sh.

Note on type-checking

The frontend carries pre-existing svelte-check type issues (auth-store discriminated-union typing, missing lib type declarations, implicit-any). The build has always been vite build (esbuild, no type-check) and never gated on svelte-check; this change introduces none of those errors.

CODEOWNERS

Unchanged — /motoko/vetkeys/ and /rust/vetkeys/ both map to @dfinity/core-protocol.

Verification (local)

  • Motoko: vite build + deploy, test.sh PASS, and a created note survives an upgrade.
  • Rust: cargo/wasm build + deploy, test.sh PASS.
  • Both frontends build and serve.

Part of the vetkeys split series (#1443, #1444). Remaining: password_manager, password_manager_with_metadata.

🤖 Generated with Claude Code

…otoko + rust examples

Same split as basic_ibe (#1443) / basic_bls_signing (#1444): move the Motoko
variant to motoko/vetkeys/encrypted_notes_app_vetkd and flatten the Rust
variant to rust/vetkeys/encrypted_notes_app_vetkd, each self-contained with
its own frontend copy (previously a shared Svelte frontend symlinked into
motoko/ and rust/ subdirs).

- Frontend (Svelte): per-language copy; bindings via the @icp-sdk/bindgen Vite
  plugin from the committed backend/backend.did (replaces scripts/gen_bindings.sh).
  Unified the three inconsistent binding import paths (declarations/…/encrypted_notes_rust,
  …/backend.did, ../lib/backend) to a single ../bindings/backend. Root workspace
  package.json so `npm run dev` runs from the example root; kept all Svelte deps.
- Motoko: idiomatic camelCase public interface (createNote, getNotes, updateNote,
  addUser, removeUser, deleteNote, encryptedSymmetricKeyForNote,
  symmetricKeyVerificationKeyForNote; EncryptedNote.encryptedText). The vetKD
  management-canister interface is kept snake_case (fixed system API). moc 1.11.0
  + --default-persistent-actors (dropped `persistent`). Committed backend/backend.did.
- Rust: unchanged (snake_case); relocated, and the hand-maintained .did moved to
  backend/backend.did.
- READMEs split per language (linked prerequisites); test.sh added (all methods
  are update calls here — no query); CI split into motoko + rust jobs.

Note: the frontend carries pre-existing svelte-check type issues (auth store
typing, missing lib type decls) that the build never gated on (build is
`vite build`); this change introduces none.

CODEOWNERS unchanged: /motoko/vetkeys/ and /rust/vetkeys/ both map to
@dfinity/core-protocol.

Verified: Motoko deploy + test.sh + a note survives an upgrade; Rust cargo
build + deploy + test.sh; both frontends build/serve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
marc0olo and others added 3 commits July 16, 2026 18:13
The backend methods require a non-anonymous caller (e.g. get_notes asserts
not isAnonymous), but the CI default identity is anonymous — so the added
test.sh failed. This is why the original example shipped without a test.sh.
Drop both test.sh files and run deploy-only in CI (matching the original
workflow); the deploy itself verifies build + install.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump the Rust recipe to @dfinity/rust@v3.3.0 and rename the Cargo package to
`backend`, dropping the custom `package:` from the recipe config (matching the
other vetkeys examples). No Makefile / candid-extractor section here — this
backend's .did is hand-maintained (no export_candid).

Verified: rust deploy succeeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…list, drop web3 jargon

- Motoko README "API level": link to the Motoko password_manager examples
  (../password_manager, ../password_manager_with_metadata) instead of the Rust
  ones (depends on the password_manager split PRs #1446/#1447 being merged).
- security-checklist.md: condense to a focused, language-specific version for
  each of Motoko and Rust (was a 165-line identical copy carried from the older
  device-based encrypted_notes — it wrongly claimed "no inter-canister calls"
  (this version calls the vetKD management canister) and referenced
  submit_ciphertexts / device removal that don't exist here). Link it from each
  README.
- Drop "smart contract" web3 jargon from the backend comments (app.mo, lib.rs):
  "a single canister smart contract" -> "a single canister".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@marc0olo

Copy link
Copy Markdown
Member Author

Heads-up on cross-links: the Motoko README's API level section now links to the Motoko password manager examples (../password_manager, ../password_manager_with_metadata). Those paths only exist once the password-manager split PRs (#1446, #1447) are merged. If this PR merges first, those two links will 404 until #1446/#1447 land — worth ordering the merges accordingly (or I can temporarily point them at the Rust siblings and switch them back afterward).

Also in this update:

  • security-checklist.md condensed into a focused, language-specific version for each of Motoko and Rust. The previous file was a 165-line identical copy carried over from the older device-based encrypted_notes and was inaccurate for the vetKD version — it claimed "no inter-canister calls" (this version calls the vetKD management canister) and referenced submit_ciphertexts / device removal that don't exist here. Each README now links its own checklist.
  • Dropped "smart contract" web3 jargon from the backend comments ("a single canister smart contract" → "a single canister").

marc0olo and others added 3 commits July 17, 2026 12:31
…ogy, drop "dapp"

- Update backend doc links to current URLs: resource limits
  (references/resource-limits), query-vs-update calls, Motoko actors-async, and
  the upgrade-a-canister guide (canister-management/lifecycle). Drop the dead
  `motoko/main/upgrades/` links.
- Motoko: fix outdated "stable" terminology in comments — actor fields are
  retained across upgrades unless `transient`; there is no `stable` keyword in
  use. Rename the `stable_*` upgrade-buffer vars to `*Backup` and describe the
  transient-maps + backup-buffers + pre/postupgrade pattern accurately.
- Replace "dapp" with "app" in READMEs, checklists, and comments; normalize the
  security best-practices link to https://docs.internetcomputer.org/guides/security/overview/.

Verified: Motoko compiles and state survives an upgrade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cklists

Use task-list checkboxes so the distinction is explicit and scannable: [x] marks
what the example implements, [ ] marks recommendations left out for simplicity
that a production app should still address. All checked items were verified
against the backend code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hooks

Under enhanced orthogonal persistence, `mo:core` Map fields are retained across
upgrades automatically. The maps were declared `transient` and then manually
snapshotted into backup arrays in `preupgrade`/`postupgrade` — machinery that
existed only to undo the self-imposed `transient`. Drop `transient` from the
three maps, delete the backup arrays and both system hooks, and remove the now
unused `Iter`/`Debug` imports.

Verified: a note created before an upgrade is still present after it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@marc0olo
marc0olo requested a review from Copilot July 17, 2026 14:52
@marc0olo
marc0olo marked this pull request as ready for review July 17, 2026 14:53
@marc0olo
marc0olo requested review from a team as code owners July 17, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Splits the encrypted_notes_app_vetkd vetkeys example into two self-contained examples (Motoko and Rust), each with its own Svelte/Vite frontend and build configuration, and updates docs/CI accordingly.

Changes:

  • Introduces a full Motoko variant (motoko/vetkeys/encrypted_notes_app_vetkd) with its own backend, frontend, and toolchain config.
  • Restructures the Rust variant (rust/vetkeys/encrypted_notes_app_vetkd) into the canonical layout and switches the frontend to Vite @icp-sdk/bindgen-generated bindings.
  • Updates security checklists/READMEs and adjusts the CI workflow to run separate motoko/rust deploy jobs.

Reviewed changes

Copilot reviewed 62 out of 72 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
rust/vetkeys/encrypted_notes_app_vetkd/security-checklist.md Rewrites the Rust security checklist into a shorter, checklist-style document.
rust/vetkeys/encrypted_notes_app_vetkd/rust/icp.yaml Removes the legacy nested Rust icp.yaml (old project layout).
rust/vetkeys/encrypted_notes_app_vetkd/rust-toolchain.toml Adds a Rust toolchain file (WASM target configuration).
rust/vetkeys/encrypted_notes_app_vetkd/README.md Updates Rust README to reflect the new self-contained structure and commands.
rust/vetkeys/encrypted_notes_app_vetkd/package.json Adds a root workspace package.json to run frontend scripts from example root.
rust/vetkeys/encrypted_notes_app_vetkd/motoko/mops.toml Removes legacy Motoko config under the old shared example structure.
rust/vetkeys/encrypted_notes_app_vetkd/icp.yaml Adds new top-level Rust example icp.yaml with backend/frontend canisters.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/vite.config.ts Switches dev setup and adds Vite icpBindgen integration for bindings generation.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/src/store/notes.ts Updates imports to use generated bindings path.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/note.ts Updates EncryptedNote type import to use generated bindings path.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/actor.ts Updates bindings import/env var name to the canonical backend canister.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/scripts/gen_bindings.sh Removes the old manual bindings generation script.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/package.json Simplifies scripts and adds @icp-sdk/bindgen dependency for build-time generation.
rust/vetkeys/encrypted_notes_app_vetkd/frontend/.gitignore Ensures generated bindings and build output aren’t committed.
rust/vetkeys/encrypted_notes_app_vetkd/Cargo.toml Adds a workspace manifest and release profile settings at example root.
rust/vetkeys/encrypted_notes_app_vetkd/backend/src/lib.rs Updates doc links/wording in comments; keeps core canister logic intact.
rust/vetkeys/encrypted_notes_app_vetkd/backend/Cargo.toml Renames crate to backend and keeps dependency set for the canister.
rust/vetkeys/encrypted_notes_app_vetkd/backend/backend.did Adds the committed Candid interface for the Rust backend.
motoko/vetkeys/encrypted_notes_app_vetkd/security-checklist.md Adds a Motoko-specific security checklist mirroring the Rust checklist format.
motoko/vetkeys/encrypted_notes_app_vetkd/README.md Adds Motoko README with updated build/deploy instructions and cross-link to Rust.
motoko/vetkeys/encrypted_notes_app_vetkd/package.json Adds a root workspace package.json to run frontend scripts from example root.
motoko/vetkeys/encrypted_notes_app_vetkd/mops.toml Pins moc/toolchain and configures canister entry/candid generation for Motoko.
motoko/vetkeys/encrypted_notes_app_vetkd/icp.yaml Renames canisters to canonical backend/frontend and updates asset build paths.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/vite.config.ts Adds Vite config + bindgen plugin + dev cookie injection for local dev.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/tsconfig.json Adds Svelte TS config for the Motoko frontend.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/tailwind.config.mjs Adds Tailwind/DaisyUI config for styling.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/svelte.config.js Adds Svelte preprocess config.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/store/notifications.ts Adds notification store and error helper for UI feedback.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/store/notes.ts Adds notes store, note polling, and backend integration for the Motoko frontend.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/store/draft.ts Adds localStorage-backed draft persistence.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/store/auth.ts Adds Internet Identity auth flow and session handling for the Motoko frontend.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/main.ts Adds Motoko frontend entrypoint wiring.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/sleep.ts Adds a small sleep helper.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/note.ts Adds note model + serialization/encryption helpers (Motoko binding shape).
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/enums.ts Adds small TS helper for union key narrowing.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/crypto.ts Adds vetKeys crypto service implementation and caching strategy.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/actor.ts Adds actor creation wiring for the Motoko backend bindings.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/global.d.ts Adds Svelte global type reference.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/TagEditor.svelte Adds tag editing UI component.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Spinner.svelte Adds spinner component for loading states.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/SidebarLayout.svelte Adds authenticated layout shell and navigation.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/SharingEditor.svelte Adds sharing UI to add/remove principals.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Notifications.svelte Adds notifications UI component.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Notes.svelte Adds notes list view with filtering.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/NoteEditor.svelte Adds rich-text editor component (typewriter-editor integration).
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Note.svelte Adds note card component for the list view.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/NewNote.svelte Adds “new note” flow with draft persistence and encryption.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/LayoutAuthenticated.svelte Adds authenticated routing layout.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Hero.svelte Adds unauthenticated landing/login UI.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Header.svelte Adds header/nav bar component.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/EditNote.svelte Adds note edit view including save/delete/share operations.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/DisclaimerCopy.svelte Adds disclaimer text snippet.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/components/Disclaimer.svelte Adds dismissible disclaimer banner.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/App.svelte Adds root app component selecting auth vs authenticated layout.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/app.css Adds Tailwind entry CSS.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/public/.ic-assets.json5 Adds asset certification + CSP configuration.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/postcss.config.mjs Adds PostCSS/Tailwind pipeline config.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/package.json Adds frontend deps/scripts (Svelte + bindgen).
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/index.html Adds frontend HTML entry.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/.npmrc Adds npm legacy peer deps config for this frontend.
motoko/vetkeys/encrypted_notes_app_vetkd/frontend/.gitignore Ensures generated bindings and build output aren’t committed.
motoko/vetkeys/encrypted_notes_app_vetkd/backend/utils/Hex.mo Adds hex encode/decode utility used by the Motoko backend.
motoko/vetkeys/encrypted_notes_app_vetkd/backend/backend.did Adds the committed Candid interface for the Motoko backend.
motoko/vetkeys/encrypted_notes_app_vetkd/backend/app.mo Refactors Motoko backend API naming and upgrade/persistence approach.
.github/workflows/vetkeys-encrypted-notes-app-vetkd.yml Splits CI into separate motoko/rust deploy jobs and updates watched paths.
Comments suppressed due to low confidence (5)

motoko/vetkeys/encrypted_notes_app_vetkd/backend/app.mo:17

  • The main canister is defined as an actor class with mutable state (nextNoteId, notesById, etc.), but it is no longer marked persistent. The --default-persistent-actors flag does not apply to actor classes in general, and the code/comments below claim state is retained across upgrades; without persistent that guarantee can break. Consider matching the established pattern used by other stateful actor classes (e.g. motoko/canister_factory/backend/Counter.mo:3).
    motoko/vetkeys/encrypted_notes_app_vetkd/backend/app.mo:183
  • The size limit check in updateNote validates the existing note text (note_to_update.encryptedText) instead of the new encryptedText argument, so oversized updates can bypass MAX_NOTE_CHARS.
    rust/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/actor.ts:18
  • createActor passes a possibly-undefined canisterId into the generated actor factory. Other examples in this repo fail fast with a clear error if the ic_env cookie/env is missing (e.g. rust/photo_gallery/frontend/src/actor.ts:14-18). Adding an explicit check here will avoid confusing runtime failures.
    rust/vetkeys/encrypted_notes_app_vetkd/backend/src/lib.rs:63
  • Typo in comment: "appliation" → "application".
    rust/vetkeys/encrypted_notes_app_vetkd/backend/Cargo.toml:5
  • This crate is still using Rust 2018 edition, which is inconsistent with the rest of this repo (e.g. rust/candid_type_generation/backend/Cargo.toml:4 uses 2024, and rust/vetkeys/basic_vetkd/backend/Cargo.toml:4 uses 2021). Updating the edition avoids older language semantics and keeps examples aligned.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread motoko/vetkeys/encrypted_notes_app_vetkd/frontend/src/lib/actor.ts
Comment thread .github/workflows/vetkeys-encrypted-notes-app-vetkd.yml
@marc0olo

Copy link
Copy Markdown
Member Author

Thanks @Copilot. I looked into all four points. Three are pre-existing issues carried over verbatim from the original shared frontend (this PR only splits the example into self-contained Motoko/Rust copies — the frontend changes here are limited to import paths, snake_casecamelCase method names to match the backend, and the PUBLIC_CANISTER_ID:backend env key), and the fourth is intentional:

  • store/notes.ts — uninitialized notePollerHandle: pre-existing. When it is undefined the guard notePollerHandle !== null is still true, so clearInterval(undefined) runs, which is a no-op in browsers. No functional impact.
  • store/notes.ts — unhandled rejection in the poll loop: pre-existing. It only surfaces as a console warning on an already-failing poll (showError on the error path).
  • lib/actor.ts — no fail-fast on a missing canisterId: pre-existing. This is a defensive guard rather than a bug; a normal deploy always injects the canister id.
  • CI has no test.sh: intentional. None of these vetKeys examples shipped a test.sh on master, and CI's default identity is anonymous (2vxsx-fae), which several of these backends reject (e.g. getNotes asserts a non-anonymous caller) — so a CLI test.sh would trap in CI even though it passes locally. The workflow is therefore deploy-only, which still verifies the build and install.

Since none of these were introduced by this PR, I'm leaving the frontend untouched to keep the split faithful and avoid re-testing behavior that already works. They can be addressed separately upstream if desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants