diff --git a/CLAUDE.md b/CLAUDE.md
index 3786bb01..ce58af59 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -15,10 +15,12 @@ IOTA Notarization enables creation of immutable, on-chain records for arbitrary
whatever suites into the context the best. In this stylguide `Toolkit` is used for referencing the term. Use "title case"
allways for `Notarization Toolkit` (never use `Notarization toolkit` or `notarization toolkit`).
- The IOTA Trust Framework consist of Trust Framework Products (TF products)
-- The Notarization Toolkit contains two TF products: **Single Notarization** and **Audit Trails**
- - In the context of Notarization Toolkit documentation, Single Notarization and Audit Trails are called components
- - In the context of IOTA Trust Framework documentation, Single Notarization and Audit Trails are called TF products
- - These rules also apply to future TF products in the Notarization Toolkit (i.e. "Proof of Inclusion")
+- The Notarization Toolkit contains three TF products: **Single Notarization**, **Audit Trails**, and **Proof of Inclusion**
+ - In the context of Notarization Toolkit documentation, Single Notarization, Audit Trails, and Proof of Inclusion are
+ called components
+ - In the context of IOTA Trust Framework documentation, Single Notarization, Audit Trails, and Proof of Inclusion are
+ called TF products
+ - These rules also apply to future TF products in the Notarization Toolkit
- Regarding usage of singular and plural in TF product resp. Notarization Toolkit component names:
- If the product is meant itself:
- Use the product name (i.e. `Audit Trails`, `Notarization`) with singular form - example: "Audit Trails is the best ..."
diff --git a/README.md b/README.md
index 7d9be965..208abc77 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@
Introduction ◈
Where To Start ◈
+ Packages ◈
Documentation & Resources ◈
Contributing
@@ -28,30 +29,37 @@ The toolkit includes:
Use this for individual locked or dynamic notarizations of arbitrary data, documents, hashes, or latest-state records.
- **Audit Trails**
Use this for structured record histories with sequential entries, role-based access control, locking, and tagging.
+- **Proof of Inclusion**
+ Use this to construct portable cryptographic evidence that a transaction, event, or object state is included in a
+ certified IOTA checkpoint, and to verify that evidence locally.
-Each toolkit component is available as:
+## Where To Start
-- **Move Package** for the on-chain contracts
-- **Rust Package** for typed client access and transaction builders
-- **TypeScript/JS Package** using wasm bindings for the above-mentioned Rust package
+Use [Single Notarization](#single-notarization) for one on-chain object that stores arbitrary data, a document hash, or
+the latest state of a record.
-## Where To Start
+Use [Audit Trails](#audit-trails) for structured record histories with permissions, capabilities, tagging, and write or
+delete controls.
-See [Single Notarization resources](#single-notarization) for one on-chain proof object, such as a document hash, immutable record, or dynamic latest-state record.
+Use [Proof of Inclusion](#proof-of-inclusion) when a verifier needs portable evidence that a transaction, event, or
+object state is included in a certified checkpoint. Proof of Inclusion verifies existing ledger activity and does not
+define a separate on-chain object or Move Package.
-See [Audit Trails resources](#audit-trails) for structured record histories with permissions, capabilities, tagging, and write or delete controls.
+## Packages
-If you need to integrate the Notarization on-chain contracts into your own Move Package:
+Single Notarization and Audit Trails provide on-chain contracts:
-- [Notarization Move Package](./notarization-move)
+- [Single Notarization Move Package](./notarization-move)
- [Audit Trails Move Package](./audit-trail-move)
-If you want to build a client application:
+All three components provide Rust and TypeScript/JavaScript packages:
-- [Rust client for notarized records](./notarization-rs)
-- [Rust client for audit trails](./audit-trail-rs)
-- [Wasm bindings for notarized records](./bindings/wasm/notarization_wasm)
-- [Wasm bindings for audit trails](./bindings/wasm/audit_trail_wasm)
+- [Single Notarization Rust Package](./notarization-rs)
+- [Audit Trails Rust Package](./audit-trail-rs)
+- [Proof of Inclusion Rust Package](./poi-rs)
+- [Single Notarization Wasm Package](./bindings/wasm/notarization_wasm)
+- [Audit Trails Wasm Package](./bindings/wasm/audit_trail_wasm)
+- [Proof of Inclusion Wasm Package](./bindings/wasm/poi_wasm)
## Documentation and Resources
@@ -75,6 +83,15 @@ If you want to build a client application:
- [Wasm Package README](./bindings/wasm/audit_trail_wasm/README.md)
- [Wasm Examples](./bindings/wasm/audit_trail_wasm/examples/README.md)
+### Proof of Inclusion
+
+- [Rust Package README](./poi-rs/README.md)
+- [Rust API documentation](https://iotaledger.github.io/notarization/poi_rs/index.html)
+- [Build the CLI from source](./poi-rs/README.md#building-the-cli-from-source)
+- [Rust Examples](./examples/poi/README.md)
+- [Wasm Package README](./bindings/wasm/poi_wasm/README.md)
+- [Wasm Examples](./bindings/wasm/poi_wasm/examples/README.md)
+
## Contributing
We would love to have you help us with the development of the IOTA Notarization Toolkit. Each and every contribution is greatly valued.
@@ -83,4 +100,4 @@ Please review the [contribution](https://docs.iota.org/developer/iota-notarizati
To contribute directly to the repository, simply fork the project, push your changes to your fork and create a pull request to get them included.
-The best place to get involved in discussions about these libraries or to look for support at is the `#notarization` channel on the [IOTA Discord](https://discord.gg/iota-builders). You can also ask questions on our [Stack Exchange](https://iota.stackexchange.com/).
+The best place to get involved in discussions about these Packages or to look for support at is the `#notarization` channel on the [IOTA Discord](https://discord.gg/iota-builders). You can also ask questions on our [Stack Exchange](https://iota.stackexchange.com/).
diff --git a/bindings/wasm/README.md b/bindings/wasm/README.md
index fb1e438f..0d093e47 100644
--- a/bindings/wasm/README.md
+++ b/bindings/wasm/README.md
@@ -1,24 +1,26 @@
-# WASM build projects using wasm-bindgen
+# IOTA Notarization Toolkit Wasm Packages
-This folder contains several crates using wasm-bindgen to import or export TS types from & to JS runtimes. These crates
-are named _artifact_ in the following to indicate that the NodeJS based JS build system is used instead of cargo.
+This folder contains the Notarization Toolkit Wasm Packages. Each Package uses `wasm-bindgen` to expose Rust types and
+functions to JavaScript and TypeScript runtimes.
-The `build` folder provides build scripts needed to build the artifacts.
+The `build` folder provides the shared scripts needed to build the Packages.
-Here is an overview of the existing artifacts:
+The following Packages are available:
- `notarization_wasm`
Public surface of notarization-rs exported to JS/TypeScript
- `audit_trail_wasm`
Public surface of audit-trail-rs exported to JS/TypeScript
+- `poi_wasm`
+ Proof of Inclusion client and public surface of poi-rs exported to JS/TypeScript
-## Building an Artifact
+## Building a Package
-For build instructions please have a look into the artifact README file.
+See each Package README for its build instructions.
## Build process in general
-Each artifact is located in its own artifact folder (see above) containing the following important files and subfolders:
+Each Package has its own folder containing the following files and subfolders:
- `tsconfig` files for the `nodejs` and `web` runtimes
- The `package.json` file
@@ -26,61 +28,61 @@ Each artifact is located in its own artifact folder (see above) containing the f
Contains TS files used for wasm-bindings
- Contains `tsconfig` files for the `nodejs` and `web` runtimes with additional TS compiler configurations
- `node` folder
- Distribution folder for the `nodejs` runtime
+ Distribution folder for the Node.js runtime
- `web` folder
Distribution folder for the `web` runtime
- `src` folder
- Rust code of the crate/artifact
+ Rust code of the Package
- `tests` folder
Test code
- `examples` folder
Example code
-The build process is defined by run scripts contained in the artifacts `package.json` file.
-The build process for the `nodejs` and `web` runtimes, consists of the following steps:
+The scripts in each Package's `package.json` file define its build process.
+The build process for the Node.js and web runtimes consists of the following steps:
-- cargo build of the crate with target wasm32-unknown-unknown
-- wasm-bindgen CLI call, generating `___.js` and `___.d.ts` files in the distribution folder of the artifact (`node` or
+- Cargo build of the crate with target `wasm32-unknown-unknown`
+- `wasm-bindgen` CLI call, generating `___.js` and `___.d.ts` files in the Package distribution folder (`node` or
`web`)
- execute the `build/node` or `build/web` build script (see below)
-- typescript transpiler call (tsc)
+- TypeScript compiler call (`tsc`)
Converts the TS files in the `lib` folder into JS files.
- JS files are written into the distribution folder of the artifact.
+ JS files are written into the Package distribution folder.
The distribution folder is configured
- in the applied tsconfig file (located in the `lib` folder of the artifact).
+ in the applied `tsconfig` file located in the Package's `lib` folder.
- execute the `build/replace_paths` build script (see below)
## Build scripts contained in the `build` folder
### node.js
-Used by the `bundle:nodejs` run task in the package.json file of the artifact.
+Used by the `bundle:nodejs` script in the Package's `package.json` file.
Process steps:
- Add a [node-fetch polyfill](https://github.com/seanmonstar/reqwest/issues/910)
- at the top of the main js file of the artifact
-- Generate a `package.json` file derived from the original package.json of the artifact
+ at the top of the Package's main JS file
+- Generate a `package.json` file derived from the Package's original `package.json`
(done by `utils/generatePackage.js`)
### web.js
-Used by the `bundle:web` run task in the package.json file of the artifact.
+Used by the `bundle:web` script in the Package's `package.json` file.
Process steps:
-- In the main js file of the artifact:
+- In the Package's main JS file:
- Comment out a webpack workaround by commenting out all occurrences of
`input = new URL(, import.meta.url);`
- - Create an init function which imports the artifact wasm file.
+ - Create an initialization function that imports the Package's Wasm file.
- In the typescript source map file `.d.ts`:
- Adds the declaration of the above created init function to the typescript source map file
-- Generate a `package.json` file derived from the original package.json file of the artifact
+- Generate a `package.json` file derived from the Package's original `package.json`
(done by `utils/generatePackage.js`)
### replace_paths.js
-Processes all JS and TS files contained in the artifact distribution folder that have previously been created
+Processes all JS and TS files previously created in the Package distribution folder
by wasm-bindgen and the TS compiler (tsc) call.
For each file, it replaces aliases defined in the
@@ -98,7 +100,7 @@ It is used by the following run tasks for the following tsconfig files and distr
## Documentation Style Guide for generated TSDoc/JSDoc
-The [DOC-STYLEGUIDE.md](./DOC-STYLEGUIDE.md) states rules to be followed for the documentation
-of Rust types being compiled in TS/JS types using wasm-bindgen.
+The [DOC-STYLEGUIDE.md](./DOC-STYLEGUIDE.md) defines the documentation rules for Rust types compiled into
+JavaScript/TypeScript types with `wasm-bindgen`.
These rules are obligatory for developers and AI agents.
diff --git a/bindings/wasm/poi_wasm/README.md b/bindings/wasm/poi_wasm/README.md
index 6d9e1ccf..9f3d50c3 100644
--- a/bindings/wasm/poi_wasm/README.md
+++ b/bindings/wasm/poi_wasm/README.md
@@ -1,36 +1,30 @@
-# Proof of Inclusion Node.js Package
+# IOTA Proof of Inclusion Wasm Package
-This package generates a typed Node.js client for IOTA's `LedgerService` and
-connects it to `poi-rs` compiled as WebAssembly.
+## Introduction
-The generated client uses:
+The Proof of Inclusion Wasm Package provides the Node.js and TypeScript interface for Proof of Inclusion in the IOTA
+Notarization Toolkit. It connects a generated IOTA `LedgerService` client to `poi-rs` compiled as WebAssembly.
-- protobuf definitions pinned to the same `iota-rust-sdk` revision as the Rust
- workspace;
-- Protobuf-ES generated messages and service descriptors;
-- ConnectRPC's native Node.js gRPC transport over HTTP/2.
+Use the Package to construct portable proofs for IOTA transactions, events, and object states and to verify those proofs
+locally. `PoiClient` hides the generated protobuf client, ConnectRPC transport, and JavaScript-to-WASM source adapter,
+while Rust owns proof construction, committee resolution, and verification.
-## Schema workflow
+Proof of Inclusion operates on existing ledger activity and does not define a separate Move Package.
-[`grpc/iota-schema.lock.json`](grpc/iota-schema.lock.json) records the approved
-repository, exact Git revision and SHA-256 digest of the committed Buf image.
-Normal generation does not access the network.
+## Installation
-To intentionally download a different upstream schema:
+The Package currently builds from the repository. Install its development dependencies from this directory:
-```sh
-npm run grpc:schema:update --
+```bash
+npm install
```
-To regenerate the TypeScript client from the committed schema image:
-
-```sh
-npm run grpc:generate
-```
+Node.js 24 or later, Rust 1.85 or later, `wasm-bindgen-cli`, and `wasm-opt` are required to build the Package.
-Review the lock file, Buf image and generated TypeScript changes together.
+## Client Creation
-## Client creation
+Create a client for a named public network or pass an explicit gRPC endpoint. The Package never selects a network
+implicitly.
```ts
import { PoiClient } from "@iota/poi-wasm";
@@ -38,14 +32,16 @@ import { PoiClient } from "@iota/poi-wasm";
const mainnet = PoiClient.mainnet();
const testnet = PoiClient.testnet();
const devnet = PoiClient.devnet();
-const custom = new PoiClient("http://localhost:9000");
+const custom = new PoiClient("http://localhost:50051");
```
-No network is selected implicitly. The named constructors use the public IOTA
-gRPC endpoints. Construct `PoiClient` with an explicit endpoint for private
-nodes, archives, local networks, or alternative endpoints.
+Use an explicit endpoint for private nodes, archives, local networks, or alternative endpoints. Network selection
+configures the source of proof material; it does not make the proof trusted.
-## Proof construction
+## Proof Construction
+
+`PoiClient.makeProof()` constructs one proof for transaction, object, and event targets that belong to the same
+transaction.
```ts
import { PoiClient } from "@iota/poi-wasm";
@@ -60,26 +56,22 @@ const proof = await client.makeProof({
console.log(proof.toJSON());
```
-The `transaction` field selects the transaction explicitly. The `objects` and
-`events` arrays select any object and event targets that belong to the same
-transaction. Event sequence numbers and all other 64-bit values use JavaScript
-`bigint`.
+The `transaction` field selects the transaction explicitly. The `objects` and `events` arrays select object and event
+targets. Event sequence numbers and all other 64-bit values use JavaScript `bigint`.
-The serialized proof records the targets explicitly selected by the caller.
-Its checkpoint summary and checkpoint contents are sibling fields, while the
-required transaction proof contains the transaction, effects, and optional
-event evidence. Object targets contain the selected object values; event
-targets contain event IDs whose contents are selected from the authenticated
+The serialized proof records the targets explicitly selected by the caller. Its checkpoint summary and checkpoint
+contents are sibling fields, while the required transaction proof contains the transaction, effects, and optional event
+evidence. Object targets contain the selected object values, and event targets select events from the authenticated
transaction event list.
-`PoiClient` hides the generated protobuf client, gRPC transport, and
-JavaScript/WASM source adapter. The adapter passes only opaque BCS bytes and
-checkpoint sequence numbers into WASM. Rust decodes those values into existing
-IOTA domain types and delegates target resolution and proof construction to
-`poi-rs`.
+The JavaScript source adapter passes only opaque BCS bytes and checkpoint sequence numbers into WASM. Rust decodes those
+values into existing IOTA domain types and delegates target resolution and proof construction to `poi-rs`.
## Verification
+Create a verifier from the same `PoiClient`. Trusted-node resolution accepts the committee reported by a node already
+inside the caller's trust boundary.
+
```ts
import { CommitteeResolution } from "@iota/poi-wasm";
@@ -87,13 +79,7 @@ const verifier = client.verifier(CommitteeResolution.trustedNode());
await verifier.verify(proof);
```
-The verifier asks the client's node for the committee governing the proof
-checkpoint epoch. Rust validates the returned committee representation and
-performs proof verification locally with `poi-rs`.
-
-This mode places the node inside the caller's trust boundary. It does not
-authenticate committee lineage from genesis. To authenticate committee
-lineage from an already trusted committee:
+Use genesis-anchored resolution to authenticate committee lineage independently from the node:
```ts
import { readFile } from "node:fs/promises";
@@ -105,36 +91,82 @@ const verifier = client.verifier(resolution);
await verifier.verify(proof);
```
-`CommitteeResolution.fromGenesis()` decodes the BCS-encoded IOTA genesis blob
-and extracts its committee in Rust. Callers that already possess an extracted
-trusted committee can use `CommitteeResolution.anchored(committee)` instead.
-`Committee.fromJSON()` accepts the Rust
-`Committee` fields `epoch` and `voting_rights`, validates public keys, rejects
-duplicate authorities, requires total voting power to equal 10,000, and
-reconstructs the committee's derived lookup state.
+`CommitteeResolution.fromGenesis()` decodes the BCS-encoded IOTA genesis blob and extracts its committee in Rust.
+Callers that already possess an extracted trusted committee can use `CommitteeResolution.anchored(committee)` instead.
+`Committee.fromJSON()` accepts the Rust `Committee` fields `epoch` and `voting_rights`, validates public keys, rejects
+duplicate authorities, requires total voting power to equal 10,000, and reconstructs the committee's derived lookup
+state.
-The verifier fetches the certified checkpoint in each epoch-close proof,
-verifies it with the current committee, and only then accepts and caches the
-next committee. The node supplies evidence but is not trusted to choose the
-committee.
+The verifier fetches the certified checkpoint in each epoch-close proof, verifies it with the current committee, and
+only then accepts and caches the next committee. Retain the verifier when checking multiple proofs so it can reuse its
+authenticated committee cache. `CommitteeResolver.resolve(epoch)` and `Proof.verify(committee)` remain available for
+lower-level committee resolution and offline verification.
-Retain the verifier when checking multiple proofs so its authenticated
-committee cache is reused. `CommitteeResolver.resolve(epoch)` and
-`Proof.verify(committee)` remain available for callers that need the
-lower-level committee or offline-verification APIs.
+## Trust Boundaries
-## Package verification
+Treat the node, source adapter, and complete proof payload as untrusted until verification succeeds. Trusted-node
+resolution is appropriate only when the selected node is already an explicit trust anchor.
-```sh
-npm install
+Obtain genesis blobs and extracted anchor committees independently from the party that supplies the proof. The proof's
+`chain` value is informational and must not select the network, committee, genesis blob, or another trust anchor.
+
+## Schema Workflow
+
+[`grpc/iota-schema.lock.json`](grpc/iota-schema.lock.json) records the approved repository, exact Git revision, and
+SHA-256 digest of the committed Buf image. Normal generation does not access the network.
+
+Download a different upstream schema only as an intentional update:
+
+```bash
+npm run grpc:schema:update --
+```
+
+Regenerate the TypeScript client from the committed schema image:
+
+```bash
+npm run grpc:generate
+```
+
+Review the lock file, Buf image, and generated TypeScript changes together. The generated client uses Protobuf-ES
+messages and service descriptors with ConnectRPC's native Node.js gRPC transport over HTTP/2.
+
+## Development And Testing
+
+Build the Node.js Package:
+
+```bash
+npm run build
+```
+
+Regenerate the client, build `poi-rs` for `wasm32-unknown-unknown`, type-check the TypeScript boundary, and run the unit
+tests:
+
+```bash
npm run verify
```
-Verification regenerates the Node.js protobuf client from the committed schema
-image, builds `poi-rs` for `wasm32-unknown-unknown`, type-checks the TypeScript
-boundary, and runs the tests. The tests use an in-memory generated service
-implementation and do not require a running IOTA node.
+The unit tests use an in-memory generated service implementation and do not require a running IOTA node.
+
+## Examples
+
+The [Proof of Inclusion Wasm Examples](./examples/README.md) cover transaction, multi-target, verifier-reuse, object,
+and event proofs against the active IOTA CLI environment.
+
+## Documentation And Resources
+
+- [Proof of Inclusion Rust Package](../../../poi-rs/README.md)
+- [Proof of Inclusion Rust Examples](../../../examples/poi/README.md)
+- [Proof of Inclusion Wasm Examples](./examples/README.md)
+- [Repository Root](../../../README.md)
+
+## Contributing
+
+We would love to have you help us develop the IOTA Notarization Toolkit. Every contribution is greatly valued.
+
+Review the [contribution](https://docs.iota.org/developer/iota-notarization/contribute) sections in the
+[IOTA Docs Portal](https://docs.iota.org/developer/iota-notarization/).
+
+To contribute directly to the repository, fork the project, push your changes to your fork, and create a pull request.
-See [`examples/README.md`](examples/README.md) for network-configurable Proof of
-Inclusion examples covering transaction, multi-target, verifier reuse, object,
-and event proofs.
+Join the `#notarization` channel on the [IOTA Discord](https://discord.gg/iota-builders) for development discussions and
+support. You can also ask questions on [IOTA Stack Exchange](https://iota.stackexchange.com/).
diff --git a/bindings/wasm/poi_wasm/examples/README.md b/bindings/wasm/poi_wasm/examples/README.md
index 00108ce9..1f64f329 100644
--- a/bindings/wasm/poi_wasm/examples/README.md
+++ b/bindings/wasm/poi_wasm/examples/README.md
@@ -1,9 +1,21 @@
-# IOTA Proof of Inclusion WASM Examples
+# IOTA Proof of Inclusion Wasm Examples
+
+## Introduction
These examples construct and verify portable IOTA Proof of Inclusion proofs
with the `@iota/poi-wasm` Package. Each example creates fresh evidence through
Single Notarization instead of depending on fixed historical transactions.
+## Learning Objectives
+
+The examples demonstrate how to:
+
+- select transaction, object, and event proof targets;
+- construct single-target and multi-target proofs with `PoiClient`;
+- verify proofs with genesis-anchored or trusted-node committee resolution;
+- reuse a verifier and its authenticated committee cache; and
+- configure Proof of Inclusion from the active IOTA CLI environment.
+
## What Each Example Does
Every example has two distinct parts:
@@ -25,7 +37,7 @@ Package ID.
Install the following tools before running an example:
-- Node.js 20 or later;
+- Node.js 24 or later;
- the IOTA CLI configured for the target network;
- `jq`, which the Package publication script uses;
- JSON-RPC and gRPC access to the same IOTA network; and
@@ -75,7 +87,7 @@ never requests faucet funds or publishes a Package automatically on mainnet.
## Step 3: Build and Run
-Install dependencies and build the Proof of Inclusion Package:
+Install dependencies and build the Proof of Inclusion Wasm Package:
```bash
npm install
@@ -105,13 +117,13 @@ npm run example:node -- 05_event_proof
## Examples
-| Name | What the example proves |
-| :------------------------------------------------------------ | :----------------------------------------------------------------------------------------- |
-| [01_transaction_proof](./src/01_transaction_proof.ts) | The transaction that created a `Notarization` object using Locked Notarization. |
-| [02_multi_target_proof](./src/02_multi_target_proof.ts) | The creation transaction, resulting `Notarization` object, and emitted event in one proof. |
-| [03_reuse_verifier](./src/03_reuse_verifier.ts) | Two creation transactions while reusing one verifier and its committee cache. |
-| [04_object_proof](./src/04_object_proof.ts) | A freshly created `Notarization` object, starting from only its object ID. |
-| [05_event_proof](./src/05_event_proof.ts) | A fresh `LockedNotarizationCreated` event, starting from only its event ID. |
+| Name | What the example proves |
+| :------------------------------------------------------ | :----------------------------------------------------------------------------------------- |
+| [01_transaction_proof](./src/01_transaction_proof.ts) | The transaction that created a `Notarization` object using Locked Notarization. |
+| [02_multi_target_proof](./src/02_multi_target_proof.ts) | The creation transaction, resulting `Notarization` object, and emitted event in one proof. |
+| [03_reuse_verifier](./src/03_reuse_verifier.ts) | Two creation transactions while reusing one verifier and its committee cache. |
+| [04_object_proof](./src/04_object_proof.ts) | A freshly created `Notarization` object, starting from only its object ID. |
+| [05_event_proof](./src/05_event_proof.ts) | A fresh `LockedNotarizationCreated` event, starting from only its event ID. |
## Committee Trust
@@ -130,3 +142,10 @@ Obtain custom genesis blobs independently, verify that each blob belongs to the
selected network, and do not accept a trust anchor from the same untrusted party
that supplies the proof. Reuse a verifier when checking multiple proofs so it
can retain resolved committees.
+
+## Documentation And Resources
+
+- [Proof of Inclusion Wasm Package](../README.md)
+- [Proof of Inclusion Rust Package](../../../../poi-rs/README.md)
+- [Proof of Inclusion Rust Examples](../../../../examples/poi/README.md)
+- [Repository Root](../../../../README.md)
diff --git a/examples/poi/README.md b/examples/poi/README.md
index 2604273a..17080a3a 100644
--- a/examples/poi/README.md
+++ b/examples/poi/README.md
@@ -1,5 +1,7 @@
# IOTA Proof of Inclusion Examples
+## Introduction
+
These Rust examples create fresh ledger activity and use it to construct and verify portable IOTA Proof of Inclusion
proofs. Each example reads the active IOTA CLI environment and wallet, creates a locked `Notarization` object, and uses
the resulting transaction, object, or event as its proof target.
@@ -8,6 +10,16 @@ Proof construction and verification have separate trust responsibilities. The co
untrusted ledger evidence. Genesis-anchored verification authenticates that evidence from an independently trusted
genesis blob, while trusted-node verification places the connected node inside the verifier's trust boundary.
+## Learning Objectives
+
+The examples demonstrate how to:
+
+- select transaction, object, and event proof targets;
+- construct single-target and multi-target proofs with `PoiClient`;
+- verify proofs with genesis-anchored or trusted-node committee resolution;
+- reuse a verifier and its authenticated committee cache; and
+- keep proof transport separate from committee trust decisions.
+
## Prerequisites
Configure an IOTA CLI environment and active wallet address before running an example. The examples use the CLI
@@ -70,14 +82,14 @@ transactions. A non-mainnet run may also publish the Single Notarization Move Pa
## Examples
-| Name | Information |
-| :---------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
-| [01_transaction_proof](./01_transaction_proof.rs) | Creates a transaction proof, serializes it as JSON, and verifies it from a trusted network genesis blob. |
-| [02_multi_target_proof](./02_multi_target_proof.rs) | Combines transaction, changed-object, and emitted-event targets in one proof. |
-| [03_reuse_verifier](./03_reuse_verifier.rs) | Reuses one genesis-anchored verifier across proofs for two fresh transactions. |
-| [04_object_proof](./04_object_proof.rs) | Starts from a fresh object ID and lets the builder discover the transaction that created its latest version. |
-| [05_event_proof](./05_event_proof.rs) | Starts from a fresh event ID without declaring a separate transaction target. |
-| [advanced_01_committee_cache](./advanced/01_committee_cache.rs) | Persists authenticated committees in a cache scoped to the active network. |
+| Name | Information |
+| :-------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
+| [01_transaction_proof](./01_transaction_proof.rs) | Creates a transaction proof, serializes it as JSON, and verifies it from a trusted network genesis blob. |
+| [02_multi_target_proof](./02_multi_target_proof.rs) | Combines transaction, changed-object, and emitted-event targets in one proof. |
+| [03_reuse_verifier](./03_reuse_verifier.rs) | Reuses one genesis-anchored verifier across proofs for two fresh transactions. |
+| [04_object_proof](./04_object_proof.rs) | Starts from a fresh object ID and lets the builder discover the transaction that created its latest version. |
+| [05_event_proof](./05_event_proof.rs) | Starts from a fresh event ID without declaring a separate transaction target. |
+| [advanced_01_committee_cache](./advanced/01_committee_cache.rs) | Persists authenticated committees in a cache scoped to the active network. |
## Example Workflow
@@ -98,3 +110,10 @@ use trusted-node committee resolution so they can focus on target-driven discove
- Ensure the genesis blob belongs to the same network as the proof.
- Scope persistent committee caches to one network and genesis anchor.
- Use `CommitteeResolution::TrustedNode` only when the connected node is inside the verifier's trust boundary.
+
+## Documentation And Resources
+
+- [Proof of Inclusion Rust Package](../../poi-rs/README.md)
+- [Proof of Inclusion Wasm Package](../../bindings/wasm/poi_wasm/README.md)
+- [Proof of Inclusion Wasm Examples](../../bindings/wasm/poi_wasm/examples/README.md)
+- [Repository Root](../../README.md)
diff --git a/poi-rs/README.md b/poi-rs/README.md
index 20a9037a..a1bd8007 100644
--- a/poi-rs/README.md
+++ b/poi-rs/README.md
@@ -1,16 +1,89 @@
# IOTA Proof of Inclusion Rust Package
-The Proof of Inclusion Rust package provides proof data types and offline verification for inclusion claims in the IOTA
-Notarization Toolkit.
+## Introduction
-Use Proof of Inclusion when a verifier needs cryptographic evidence that a transaction, event, or object state is tied to
-a certified IOTA checkpoint. `ProofBuilder` fetches the proof material, while `ProofVerifier` verifies that material
-locally without trusting the source that supplied it.
+The Proof of Inclusion Rust Package constructs and verifies portable evidence that IOTA ledger data is included in a
+certified checkpoint. It is the Rust Package for Proof of Inclusion in the IOTA Notarization Toolkit.
+
+Use Proof of Inclusion when a verifier needs cryptographic evidence for a transaction, event, or object state without
+trusting the source that transports the proof. `PoiClient` provides the main entry point, `ProofBuilder` constructs the
+evidence, and `ProofVerifier` verifies it locally against a committee the caller trusts.
+
+Proof of Inclusion operates on existing IOTA ledger activity. It does not define a separate on-chain object or Move
+Package. Single Notarization and Audit Trails can create ledger activity that applications later prove, but Proof of
+Inclusion also supports transactions, events, and object states created by other IOTA applications.
+
+You can find the full IOTA Notarization Toolkit documentation [here](https://docs.iota.org/developer/iota-notarization).
+
+## Process Flows
+
+Proof construction and verification are separate workflows with different trust responsibilities. Proof construction
+collects evidence from a ledger source, while verification authenticates that evidence relative to a committee trust
+decision made by the caller.
+
+### Constructing a Proof
+
+The following sequence shows how `PoiClient` and `ProofBuilder` construct one proof for one or more targets. Every target
+must belong to the same transaction.
+
+```mermaid
+sequenceDiagram
+ actor Application
+ participant Client as PoiClient
+ participant Builder as ProofBuilder
+ participant Source
+ participant Net as IOTA Network
+ Application ->>+ Client: fn proof()
+ Client ->>- Application: ProofBuilder
+ Application ->> Builder: fn transaction(), object(), or event()
+ Application ->>+ Builder: fn build()
+ Builder ->>+ Source: fetch target and transaction evidence
+ Source ->>+ Net: gRPC ledger requests
+ Net ->>- Source: transaction, objects, events, and checkpoint
+ Source ->>- Builder: decoded source evidence
+ Builder ->> Builder: validate targets and construct proof
+ Builder ->>- Application: Proof
+```
+
+`Source` is the transport boundary. It fetches decoded transaction, object, checkpoint, chain, and committee evidence.
+`ProofBuilder` owns target resolution, consistency checks, duplicate suppression, and proof construction, so custom
+sources do not reimplement that workflow.
+
+### Verifying a Proof
+
+The following sequence shows committee-aware verification through `PoiClient::verifier()`. Committee resolution may
+fetch evidence, but `ProofVerifier` performs the final proof checks locally without making network requests.
+
+```mermaid
+sequenceDiagram
+ actor Verifier
+ participant Client as PoiClient
+ participant Resolver as CommitteeResolver
+ participant Source
+ participant Net as IOTA Network
+ participant ProofVerifier
+ Verifier ->>+ Client: fn verifier(resolution)
+ Client ->>- Verifier: CommitteeResolver
+ Verifier ->>+ Resolver: fn verify(proof)
+ Resolver ->>+ Source: resolve committee for checkpoint epoch
+ Source ->>+ Net: fetch committee or epoch-close evidence
+ Net ->>- Source: committee evidence
+ Source ->>- Resolver: decoded evidence
+ Resolver ->> Resolver: apply trusted-node or anchored resolution
+ Resolver ->>+ ProofVerifier: fn verify(proof)
+ Note right of ProofVerifier: Offline verification only
+ ProofVerifier ->>- Resolver: verification result
+ Resolver ->>- Verifier: verification result
+```
+
+`CommitteeResolution::TrustedNode` accepts committee data from a node already inside the caller's trust boundary.
+Anchored resolution starts from a trusted committee or genesis blob and authenticates every committee transition before
+accepting the committee required by the proof.
## Proof Construction
-`PoiClient` provides explicit constructors for the public IOTA networks. The client does not select a default network, so
-the calling application always chooses where it fetches proof material.
+`PoiClient` provides explicit constructors for the public IOTA networks. The client does not select a default network,
+so the calling application always chooses where it fetches proof material.
```rust,no_run
use iota_sdk_types::TransactionDigest;
@@ -36,35 +109,17 @@ A builder can stack multiple object and event targets by calling `object()` and
`objects()` and `events()` batch methods. Every target must belong to the same transaction. The builder ignores exact
duplicates and reuses one transaction and one checkpoint for the complete target set.
-`Source` is the transport boundary: it fetches decoded transaction, object, checkpoint, chain, and committee evidence.
-`ProofBuilder` owns target resolution, consistency checks, and proof construction, while `CommitteeResolver` owns
-committee authentication and caching, so custom sources do not reimplement either workflow.
-
-Network selection configures only the proof source. It does not make the returned proof trusted or select an authoritative
-committee for verification.
+Network selection configures only the proof source. It does not make the returned proof trusted or select an
+authoritative committee for verification.
The default `native-grpc` feature implements `Source` directly for the SDK `GrpcClient` and provides the public-network
-constructors. WASM packages can disable default features and supply a JavaScript-backed `Source` without compiling native
-gRPC.
-
-## Proof Model
-
-A `Proof` contains three layers of evidence:
-
-- `ProofTargets` recording the transaction, objects, and events explicitly selected by the caller.
-- A `CertifiedCheckpointSummary` and its `CheckpointContents` linking the transaction to a committee-certified
- checkpoint.
-- A required `TransactionProof` containing the transaction, its effects, and event data when event targets are present.
-
-Object targets contain their exact object values; verification derives each object reference and finds it in the
-transaction effects. Event targets contain `EventID` values, while the transaction proof carries the complete event list
-needed to verify the effects' event digest. A transaction target is present only when the caller explicitly requested the
-transaction itself, although transaction evidence supports every proof.
+constructors. WASM packages can disable default features and supply a JavaScript-backed `Source` without compiling
+native gRPC.
## Verification
-For the common source-backed workflow, create a verifier from the same `PoiClient`. The verifier resolves the committee
-required by the proof and then performs offline proof verification:
+Create a verifier from the same `PoiClient` for the common source-backed workflow. The verifier resolves the committee
+required by the proof and then performs offline proof verification.
```rust,no_run
use std::fs::File;
@@ -84,34 +139,94 @@ verifier.verify(proof).await?;
`CommitteeResolution::TrustedNode` is available when the connected node is explicitly inside the caller's trust
boundary. `CommitteeResolution::from_genesis()` loads an anchor committee from a trusted BCS-encoded genesis blob,
while `CommitteeResolution::anchored()` accepts an already extracted trusted committee. Use
-`CommitteeResolution::anchored_with_cache()` or `CommitteeResolution::from_genesis_with_cache()` to supply a cache
-that contains committees authenticated for the same network.
-Retain the verifier when checking multiple proofs so its authenticated committee cache is reused.
+`CommitteeResolution::anchored_with_cache()` or `CommitteeResolution::from_genesis_with_cache()` to supply a cache that
+contains committees authenticated for the same network.
-`ProofVerifier` remains the offline verification entry point for callers that already possess the authoritative
-committee. It verifies only the proof material passed by the caller.
+Retain the verifier when checking multiple proofs so it can reuse its authenticated committee cache. `ProofVerifier`
+remains the offline entry point for callers that already possess the authoritative committee.
Verification checks:
-- the checkpoint summary is certified by the supplied committee
-- the checkpoint contents match the certified checkpoint summary
-- the transaction digest matches the transaction effects
-- the transaction effects are included in the checkpoint contents
-- an explicitly requested transaction matches the packaged transaction
-- requested object targets derive references present in the transaction effects
-- event data, when required, matches the event digest recorded in the effects
-- requested event targets belong to the transaction and select events in the authenticated event list
+- the checkpoint summary is certified by the supplied committee;
+- the checkpoint contents match the certified checkpoint summary;
+- the transaction digest matches the transaction effects;
+- the transaction effects are included in the checkpoint contents;
+- an explicitly requested transaction matches the packaged transaction;
+- requested object targets derive references present in the transaction effects;
+- event data matches the digest recorded in the effects when the proof includes event targets; and
+- requested event targets belong to the transaction and select events in the authenticated event list.
+
+## Proof Model
+
+A `Proof` contains three layers of evidence:
+
+- `ProofTargets` records the transaction, objects, and events explicitly selected by the caller.
+- A `CertifiedCheckpointSummary` and its `CheckpointContents` link the transaction to a committee-certified checkpoint.
+- A required `TransactionProof` contains the transaction, its effects, and event data when event targets are present.
+
+Object targets contain their exact object values. Verification derives each object reference and finds it in the
+transaction effects. Event targets contain `EventID` values, while the transaction proof carries the complete event list
+needed to verify the effects' event digest. A transaction target is present only when the caller explicitly requests the
+transaction itself, although transaction evidence supports every proof.
## Trust Boundaries
-`ProofVerifier` is intentionally offline. It does not make RPC calls and does not decide which committee is authoritative.
-`CommitteeResolver::verify()` composes committee resolution with offline verification for source-backed workflows.
-`CommitteeResolver::resolve()` remains available when callers need the authenticated committee itself.
+`ProofVerifier` is intentionally offline. It does not make RPC calls and does not decide which committee is
+authoritative. `CommitteeResolver::verify()` composes committee resolution with offline verification for source-backed
+workflows, while `CommitteeResolver::resolve()` returns the authenticated committee when callers need it directly.
+
+Treat every proof payload as untrusted until verification succeeds. After successful verification, callers can trust
+the authenticated target claims relative to the supplied committee.
+
+The proof's `chain` value is informational. The verifier does not authenticate it, so applications must not use it to
+select a network, committee, genesis blob, or other trust anchor.
+
+## Command-Line Interface
+
+The optional `cli` feature builds the `poi` command for creating and verifying JSON proofs. CLI verification uses a
+trusted genesis blob and does not provide trusted-node verification.
+
+### Building the CLI From Source
+
+The project does not distribute pre-built `poi` binaries. Build the CLI locally from the repository source with Rust
+1.85 or later:
+
+```bash
+git clone https://github.com/iotaledger/notarization.git
+cd notarization
+cargo build --release -p poi-rs --features cli --bin poi
+```
+
+Cargo writes the binary to `target/release/poi` on Linux and macOS or `target\release\poi.exe` on Windows. Run the
+locally built binary from the repository root:
+
+```bash
+./target/release/poi --help
+```
+
+You can also build from source and install `poi` into Cargo's binary directory:
+
+```bash
+cargo install --path poi-rs --features cli --bin poi --locked
+```
+
+### Using the CLI
+
+```bash
+cargo run --release -p poi-rs --features cli --bin poi -- create \
+ --network testnet \
+ --transaction \
+ --output proof.json
+
+cargo run --release -p poi-rs --features cli --bin poi -- verify \
+ --network testnet \
+ proof.json
+```
-The verifier treats all proof payloads as untrusted until verification succeeds. After verification succeeds, callers can
-trust the authenticated target claims relative to the supplied committee.
+Run `cargo run --release -p poi-rs --features cli --bin poi -- --help` for all targets, network options, and file input
+formats.
-## Main Types
+## Glossary
- `Proof`: Versioned Proof of Inclusion envelope.
- `ProofV1`: Version 1 checkpoint and transaction evidence carried by `Proof::ProofV1`.
@@ -119,11 +234,39 @@ trust the authenticated target claims relative to the supplied committee.
- `ProofTargets`: Transaction, object, and event claims explicitly selected by the caller.
- `PoiClient`: Source-backed entry point for proof construction and committee-aware verification.
- `CommitteeResolution`: Trusted-node or anchored committee-resolution configuration, including the committee cache.
-- `ProofBuilder`: Network-aware or custom-source proof construction.
+- `ProofBuilder`: Proof-construction workflow for public networks or custom sources.
- `Source`: Ledger-read boundary for gRPC nodes, JavaScript clients, archives, fixtures, and other evidence sources.
- `SourceTransaction` and `SourceCheckpoint`: Transport-independent decoded evidence returned by a `Source`.
-- `CommitteeResolver`: Committee resolution and source-backed proof verification configured by `CommitteeResolution`.
+- `CommitteeResolver`: Committee resolution and source-backed verification configured by `CommitteeResolution`.
- `ProofVerifier`: Offline verifier for `Proof` values.
-- `SourceError`: Transport and response failures from a ledger source.
+- `SourceError`: Transport and response failure from a ledger source.
- `ProofBuilderError`, `CommitteeResolutionError`, `ProofVerificationError`, `VerifyError`, and `SerializationError`:
Operation-specific errors.
+
+## Documentation And Resources
+
+- [Proof of Inclusion Rust API documentation](https://iotaledger.github.io/notarization/poi_rs/index.html)
+- [Proof of Inclusion Rust Examples](https://github.com/iotaledger/notarization/tree/main/examples/poi/README.md)
+- [Proof of Inclusion Wasm Package](https://github.com/iotaledger/notarization/tree/main/bindings/wasm/poi_wasm/README.md)
+- [Proof of Inclusion Wasm Examples](https://github.com/iotaledger/notarization/tree/main/bindings/wasm/poi_wasm/examples/README.md)
+- [Repository Root](https://github.com/iotaledger/notarization/tree/main/README.md)
+
+This README is also the crate-level rustdoc entry point. Source files provide detailed API documentation for all public
+types and methods.
+
+## Bindings
+
+The [Proof of Inclusion Wasm Package](https://github.com/iotaledger/notarization/tree/main/bindings/wasm/poi_wasm)
+provides JavaScript and TypeScript bindings for Node.js applications.
+
+## Contributing
+
+We would love to have you help us develop the IOTA Notarization Toolkit. Every contribution is greatly valued.
+
+Review the [contribution](https://docs.iota.org/developer/iota-notarization/contribute) sections in the
+[IOTA Docs Portal](https://docs.iota.org/developer/iota-notarization/).
+
+To contribute directly to the repository, fork the project, push your changes to your fork, and create a pull request.
+
+Join the `#notarization` channel on the [IOTA Discord](https://discord.gg/iota-builders) for development discussions and
+support. You can also ask questions on [IOTA Stack Exchange](https://iota.stackexchange.com/).
diff --git a/poi-rs/src/cache/in_memory.rs b/poi-rs/src/cache/in_memory.rs
index b49d53ee..27b7d4f9 100644
--- a/poi-rs/src/cache/in_memory.rs
+++ b/poi-rs/src/cache/in_memory.rs
@@ -9,7 +9,7 @@ use tokio::sync::RwLock;
use super::{CommitteeCache, CommitteeCacheError};
-/// In-memory committee cache for library usage and tests.
+/// In-memory committee cache for application use and tests.
#[derive(Clone, Debug, Default)]
pub struct MemoryCommitteeCache {
committees: Arc>>,