Skip to content

docs: certified variables guide#63

Merged
marc0olo merged 2 commits into
mainfrom
docs/guides-backends-certified-variables
Apr 16, 2026
Merged

docs: certified variables guide#63
marc0olo merged 2 commits into
mainfrom
docs/guides-backends-certified-variables

Conversation

@marc0olo
Copy link
Copy Markdown
Member

Summary

  • Explains the three-step certification flow (update → query → client verification) with ASCII diagram
  • Documents key constraints: 32-byte root hash limit, update-only writes, upgrade clearing behavior, query-only certificate access
  • Rust: complete RbTree-backed certified key-value store using ic-certified-map 0.4 and ic-cdk 0.19; #[init], #[post_upgrade], set, delete, get, and batch set_many methods
  • Motoko: simple single-value pattern (CertifiedData from mo:core + sha2 hash) and full multi-value store using ic-certification/CertTree with per-key Merkle witnesses
  • TypeScript client-side verification using @dfinity/certificate-verification with all 6 verification steps
  • CLI deploy and test commands using icp (not dfx)
  • Common mistakes section covering 6 pitfalls (writing in query, forgetting post_upgrade, witness size, etc.)
  • All code snippets verified against dfinity/cdk-rs, caffeinelabs/motoko-core, dfinity/examples, dfinity/response-verification

Note: pre-existing build failure in https-outcalls.mdx (uninitialized examples submodule) is not caused by this page.

Sync recommendation

Informed by dfinity/icskillsskills/certified-variables/SKILL.md; informed by dfinity/cdk-rs, caffeinelabs/motoko-core, dfinity/response-verification, dfinity/portaldocs/building-apps/security/data-integrity-and-authenticity.mdx

@marc0olo
Copy link
Copy Markdown
Member Author

Review: Certified Variables

Verified clean

  • ic_cdk::api::certified_data_set and data_certificate(): Both function names verified in .sources/cdk-rs/ic-cdk/src/api.rs at lines 325 and 334. Correct.
  • ic-cdk = "0.19": Confirmed current version (0.19.0) in .sources/cdk-rs/ic-cdk/Cargo.toml. Correct.
  • ic-certified-map = "0.4": Current version is 0.4.1 — the "0.4" constraint correctly resolves to it. Correct.
  • ciborium = "0.2" for witness serialization: Confirmed canonical for this pattern — the certified-variables icskill (.sources/icskills/skills/certified-variables/SKILL.md) uses exactly ciborium = "0.2" and ciborium::into_writer for witness encoding. Correct.
  • All 3 internal links resolve: ../../concepts/security.md ✓, ../../guides/frontends/certification.md ✓, ../../reference/ic-interface-spec.md
  • CLI commands: icp deploy backend, icp canister call backend set/get/delete — all valid icp-cli commands with correct Candid argument syntax.
  • Three-step certification flow (update → query → client verify) accurately described.
  • Key constraints (32-byte limit, update-call-only, upgrade clearing) all correctly documented.
  • 6 common mistakes section — all technically accurate.
  • Motoko simple certification: CertifiedData.set(hash) with Sha256.fromBlob(#sha256, ...) is the correct pattern for single-value certification.
  • Motoko CertTree pattern: ct.setCertifiedData(), ct.put(path, value), ct.reveal(path), ct.encodeWitness(witness) — API calls match the ic-certification mops package pattern from the icskill.
  • No dfx references ✓
  • No banned URLs ✓
  • Frontmatter complete ✓
  • <!-- Upstream: --> comment present ✓

Needs human verification

  • TypeScript imports @icp-sdk/core/agent and @icp-sdk/core/principal: These are the new unified JS SDK packages (replacing @dfinity/agent and @dfinity/principal). The lookup_path and HashTree imports from @icp-sdk/core/agent should be verified against .sources/icp-js-sdk-docs/ to confirm the module path is correct. The page correctly cites js.icp.build for the full API reference.

No must-fix items found

…upResultToBuffer

Verified against .sources/icp-js-sdk-docs/public/core/latest.zip:
- @icp-sdk/core/agent exports both lookup_path (function) and HashTree (type alias): confirmed
- @icp-sdk/core/principal exports Principal (class): confirmed
- lookup_path returns LookupResult (discriminated union), NOT Uint8Array|null.
  The previous code passed the LookupResult object directly to TextDecoder.decode()
  and checked it with `\!leafData` — both incorrect for the new SDK API.

Fix: import lookupResultToBuffer from @icp-sdk/core/agent and wrap lookup_path call.
lookupResultToBuffer converts LookupResult → Uint8Array|undefined, enabling correct
undefined check and TextDecoder.decode() usage.

Note: npm run build fails on a pre-existing issue in https-outcalls.mdx (missing
.sources/examples submodule files) unrelated to this change.
@marc0olo
Copy link
Copy Markdown
Member Author

Feedback addressed:

  • Verified TypeScript imports from @icp-sdk/core/agent and @icp-sdk/core/principal against .sources/icp-js-sdk-docs/ (SDK v5.2.1) — both confirmed as valid exports
  • Bug found and fixed: lookup_path returns LookupResult (discriminated union), not Uint8Array | null. Added lookupResultToBuffer import from @icp-sdk/core/agent (confirmed export) and wrapped lookup_path(...) calls — lookupResultToBuffer(lookup_path(...)) returns Uint8Array | undefined, enabling correct === undefined check and TextDecoder.decode() usage

@marc0olo marc0olo merged commit fefe28b into main Apr 16, 2026
1 check passed
@marc0olo marc0olo deleted the docs/guides-backends-certified-variables branch April 16, 2026 13:05
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.

1 participant